├── images ├── map.png ├── ploty.png ├── rpm.png ├── save.png ├── speed.png ├── timer.png ├── trim.png ├── folder.png ├── height.png ├── plotxy.png ├── zoomin.png ├── zoomout.png ├── analyzing.png ├── function.png ├── line-graph.png ├── mountain.png ├── zoomreset.png ├── timer-opaque.png ├── analyzing_icon.ico └── gasoline-pump.png ├── android ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── res │ └── values │ │ └── libs.xml ├── build.gradle ├── gradlew.bat ├── gradlew └── AndroidManifest.xml ├── src ├── main.cpp ├── DataMath.h ├── CustomFileDialog.h ├── CsvFileProcessor.h ├── DataMath.cpp ├── CustomFileDialog.cpp ├── CustomFileDialog.ui ├── DataMath.ui ├── SimpleCsvLogAnalyzer.h ├── CsvFileProcessor.cpp ├── SimpleCsvLogAnalyzer.ui └── SimpleCsvLogAnalyzer.cpp ├── icons.qrc ├── README.md ├── CsvAnalyzer.pro ├── ui_CustomFileDialog.h ├── ui_DataMath.h └── ui_SimpleCsvLogAnalyzer.h /images/map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/map.png -------------------------------------------------------------------------------- /images/ploty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/ploty.png -------------------------------------------------------------------------------- /images/rpm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/rpm.png -------------------------------------------------------------------------------- /images/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/save.png -------------------------------------------------------------------------------- /images/speed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/speed.png -------------------------------------------------------------------------------- /images/timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/timer.png -------------------------------------------------------------------------------- /images/trim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/trim.png -------------------------------------------------------------------------------- /images/folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/folder.png -------------------------------------------------------------------------------- /images/height.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/height.png -------------------------------------------------------------------------------- /images/plotxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/plotxy.png -------------------------------------------------------------------------------- /images/zoomin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/zoomin.png -------------------------------------------------------------------------------- /images/zoomout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/zoomout.png -------------------------------------------------------------------------------- /images/analyzing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/analyzing.png -------------------------------------------------------------------------------- /images/function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/function.png -------------------------------------------------------------------------------- /images/line-graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/line-graph.png -------------------------------------------------------------------------------- /images/mountain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/mountain.png -------------------------------------------------------------------------------- /images/zoomreset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/zoomreset.png -------------------------------------------------------------------------------- /images/timer-opaque.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/timer-opaque.png -------------------------------------------------------------------------------- /images/analyzing_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/analyzing_icon.ico -------------------------------------------------------------------------------- /images/gasoline-pump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/images/gasoline-pump.png -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dd-sudo/CSV-Analyzer/HEAD/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "SimpleCsvLogAnalyzer.h" 2 | 3 | #include 4 | 5 | // Application Icon made by Freepik from www.flaticon.com 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QApplication a(argc, argv); 10 | SimpleCsvLogAnalyzer w; 11 | w.show(); 12 | return a.exec(); 13 | } 14 | -------------------------------------------------------------------------------- /android/res/values/libs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://download.qt.io/ministro/android/qt5/qt-5.14 5 | 6 | 7 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/DataMath.h: -------------------------------------------------------------------------------- 1 | #ifndef DATAMATH_H 2 | #define DATAMATH_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Ui { 8 | class DataMath; 9 | } 10 | 11 | class DataMath : public QDialog 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | explicit DataMath(QStringList labelList,QStringList opList, QWidget *parent = nullptr); 17 | ~DataMath(); 18 | QStringList mathOperationsList; 19 | QStringList mathOps; 20 | 21 | private slots: 22 | void on_dataLabels_itemDoubleClicked(QListWidgetItem *item); 23 | 24 | void on_operatorList_itemDoubleClicked(QListWidgetItem *item); 25 | 26 | void on_clear_clicked(); 27 | 28 | void on_dataLabels_itemClicked(QListWidgetItem *item); 29 | 30 | void on_operatorList_itemClicked(QListWidgetItem *item); 31 | 32 | private: 33 | Ui::DataMath *ui; 34 | }; 35 | 36 | #endif // DATAMATH_H 37 | -------------------------------------------------------------------------------- /src/CustomFileDialog.h: -------------------------------------------------------------------------------- 1 | #ifndef CUSTOMFILEDIALOG_H 2 | #define CUSTOMFILEDIALOG_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Ui { 9 | class CustomFileDialog; 10 | } 11 | 12 | class CustomFileDialog : public QDialog 13 | { 14 | Q_OBJECT 15 | 16 | public: 17 | explicit CustomFileDialog(QWidget *parent, bool saveFile = false, QString defaultFile = QString("")); 18 | ~CustomFileDialog(); 19 | QString filePath; 20 | 21 | 22 | private: 23 | Ui::CustomFileDialog *ui; 24 | bool mSaveFile = false; 25 | QString mDefaultFileName; 26 | 27 | private slots: 28 | void on_listView_clicked(const QModelIndex &index); 29 | 30 | void on_cancelBtn_clicked(); 31 | 32 | void on_filePathEdit_returnPressed(); 33 | 34 | void on_okBtn_clicked(); 35 | 36 | void on_fileNameEdit_returnPressed(); 37 | 38 | private: 39 | QFileSystemModel *model; 40 | QFileInfo fi; 41 | }; 42 | 43 | #endif // CUSTOMFILEDIALOG_H 44 | -------------------------------------------------------------------------------- /icons.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/analyzing_icon.ico 4 | 5 | 6 | images/timer.png 7 | images/analyzing.png 8 | images/folder.png 9 | images/line-graph.png 10 | images/plotxy.png 11 | images/ploty.png 12 | images/zoomin.png 13 | images/zoomout.png 14 | images/zoomreset.png 15 | images/function.png 16 | images/save.png 17 | images/timer-opaque.png 18 | images/map.png 19 | images/gasoline-pump.png 20 | images/trim.png 21 | images/speed.png 22 | images/rpm.png 23 | images/height.png 24 | images/mountain.png 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/CsvFileProcessor.h: -------------------------------------------------------------------------------- 1 | #ifndef CSVFILEPROCESSOR_H 2 | #define CSVFILEPROCESSOR_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | 14 | class CsvFileProcessor : public QObject 15 | { 16 | Q_OBJECT 17 | public: 18 | explicit CsvFileProcessor(QObject *parent = nullptr); 19 | void setFilePath(QString filePath); 20 | QStringList getCsvFileLabels(); 21 | QStringList getSampleValuesForLabels(); 22 | QVector getDataByName(QString dataName); 23 | QStringList getRawDataByName(QString dataName); 24 | bool file2DataModel(QStandardItemModel *mdl); 25 | bool file2TableWidget(QTableWidget *tw); 26 | 27 | // variables 28 | QString valueSeperator = QString(","); 29 | 30 | public slots: 31 | 32 | signals: 33 | 34 | private: 35 | QFile m_file; 36 | QString m_filePath; 37 | QStringList m_valueNames; 38 | QVector values; 39 | QByteArray readLineFromCSV(QFile *file, uint16_t maxLen = 16384); 40 | }; 41 | 42 | #endif // CSVFILEPROCESSOR_H 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSV-Analyzer 2 | Multi Platform CSV Log Analyzer Written in C++ w/Qt Framework (Qt 5.14 & QTCreator 4.11) and QCustomPlot 3 | 4 | It can plot value vs line number/ time value (for only known log formats), and value vs another value scatter graphs. 5 | Although this application is mainly focused to analyze log files generated by Torque Mobile App by Ian Hawkins, it can also be used for analyzing other csv log files too. 6 | 7 | This application supports Windows, Linux and Android platforms. App is and will be tested on all these platforms by developer. 8 | 9 | Keywords: csv log analyzer, torque log viewer, torque log analyzer, csv, qt, qcustomplot, windows, linux, android 10 | 11 | Feel free to compile it for MacOS and iOS. Any help will be appreciated on these platforms. 12 | 13 | ## CSV Analyzer in action on Windows 10 PC 14 | ![SS1](https://user-images.githubusercontent.com/61709054/78828176-f6ea1480-79ec-11ea-9786-3ea15c63aa15.PNG) 15 | 16 | ![SS2](https://user-images.githubusercontent.com/61709054/78828186-f9e50500-79ec-11ea-9027-47386afdae08.PNG) 17 | 18 | ## CSV Analyzer in action on Android 4.4.2 with 480x800pix screen 19 | ![Screenshot_2020-04-08-19-33-44](https://user-images.githubusercontent.com/61709054/78828345-403a6400-79ed-11ea-828e-6879e58b298a.png) 20 | 21 | ![Screenshot_2020-04-08-19-34-37](https://user-images.githubusercontent.com/61709054/78828359-43cdeb00-79ed-11ea-9d1c-3c6c13c4f8aa.png) 22 | 23 | ## CSV Analyzer in action on Android 9.0 with 1080x2280pix screen 24 | ![Screenshot_2020-04-08-22-37-46-743_org myproject csvanalyzer](https://user-images.githubusercontent.com/61709054/78828442-652ed700-79ed-11ea-8a34-01011dca3013.jpg) 25 | 26 | ![Screenshot_2020-04-08-22-38-32-978_org myproject csvanalyzer](https://user-images.githubusercontent.com/61709054/78828456-6c55e500-79ed-11ea-84e3-7e0dba14754c.jpg) 27 | -------------------------------------------------------------------------------- /src/DataMath.cpp: -------------------------------------------------------------------------------- 1 | #include "DataMath.h" 2 | #include "ui_DataMath.h" 3 | 4 | DataMath::DataMath(QStringList labelList,QStringList opList, QWidget *parent) : 5 | QDialog(parent), 6 | ui(new Ui::DataMath) 7 | { 8 | mathOperationsList = opList; 9 | ui->setupUi(this); 10 | for(int i=0;idataLabels->addItem(labelList[i]); 12 | } 13 | for(int i=0;ioperatorList->addItem(opList[i]); 15 | } 16 | ui->operatorList->setEnabled(false); 17 | ui->dataLabels->setEnabled(true); 18 | } 19 | 20 | DataMath::~DataMath() 21 | { 22 | delete ui; 23 | } 24 | 25 | void DataMath::on_dataLabels_itemDoubleClicked(QListWidgetItem *item) 26 | { 27 | mathOps.append(item->text()); 28 | ui->dataMath->clear(); 29 | for (int i=0;idataMath->setText(ui->dataMath->text()+mathOps[i]); 31 | } 32 | if(mathOps.length()==1){ 33 | ui->operatorList->setEnabled(true); 34 | } 35 | } 36 | 37 | void DataMath::on_dataLabels_itemClicked(QListWidgetItem *item) 38 | { 39 | on_dataLabels_itemDoubleClicked(item); 40 | } 41 | 42 | void DataMath::on_operatorList_itemDoubleClicked(QListWidgetItem *item) 43 | { 44 | mathOps.append(item->text()); 45 | ui->dataMath->clear(); 46 | for (int i=0;idataMath->setText(ui->dataMath->text()+mathOps[i]); 48 | } 49 | 50 | } 51 | 52 | void DataMath::on_operatorList_itemClicked(QListWidgetItem *item) 53 | { 54 | on_operatorList_itemDoubleClicked(item); 55 | } 56 | 57 | void DataMath::on_clear_clicked() 58 | { 59 | if(mathOps.length()>0){ 60 | mathOps.removeLast(); 61 | ui->dataMath->clear(); 62 | for (int i=0;idataMath->setText(ui->dataMath->text()+mathOps[i]); 64 | } 65 | } 66 | } 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | jcenter() 5 | } 6 | 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:3.5.0' 9 | } 10 | } 11 | 12 | repositories { 13 | google() 14 | jcenter() 15 | } 16 | 17 | apply plugin: 'com.android.application' 18 | 19 | dependencies { 20 | implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) 21 | } 22 | 23 | android { 24 | /******************************************************* 25 | * The following variables: 26 | * - androidBuildToolsVersion, 27 | * - androidCompileSdkVersion 28 | * - qt5AndroidDir - holds the path to qt android files 29 | * needed to build any Qt application 30 | * on Android. 31 | * 32 | * are defined in gradle.properties file. This file is 33 | * updated by QtCreator and androiddeployqt tools. 34 | * Changing them manually might break the compilation! 35 | *******************************************************/ 36 | 37 | compileSdkVersion androidCompileSdkVersion.toInteger() 38 | 39 | buildToolsVersion '28.0.3' 40 | 41 | sourceSets { 42 | main { 43 | manifest.srcFile 'AndroidManifest.xml' 44 | java.srcDirs = [qt5AndroidDir + '/src', 'src', 'java'] 45 | aidl.srcDirs = [qt5AndroidDir + '/src', 'src', 'aidl'] 46 | res.srcDirs = [qt5AndroidDir + '/res', 'res'] 47 | resources.srcDirs = ['resources'] 48 | renderscript.srcDirs = ['src'] 49 | assets.srcDirs = ['assets'] 50 | jniLibs.srcDirs = ['libs'] 51 | } 52 | } 53 | 54 | lintOptions { 55 | abortOnError false 56 | } 57 | 58 | // Do not compress Qt binary resources file 59 | aaptOptions { 60 | noCompress 'rcc' 61 | } 62 | 63 | defaultConfig { 64 | resConfigs "en" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /CsvAnalyzer.pro: -------------------------------------------------------------------------------- 1 | 2 | QT += core gui printsupport opengl 3 | android: QT += androidextras 4 | windows: RC_ICONS += "images/analyzing_icon.ico" 5 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 6 | 7 | 8 | CONFIG += c++11 9 | 10 | # The following define makes your compiler emit warnings if you use 11 | # any Qt feature that has been marked deprecated (the exact warnings 12 | # depend on your compiler). Please consult the documentation of the 13 | # deprecated API in order to know how to port your code away from it. 14 | DEFINES += QT_DEPRECATED_WARNINGS 15 | #DEFINES += QCUSTOMPLOT_USE_OPENGL 16 | # You can also make your code fail to compile if it uses deprecated APIs. 17 | # In order to do so, uncomment the following line. 18 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 19 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 20 | 21 | SOURCES += \ 22 | src/CsvFileProcessor.cpp \ 23 | src/CustomFileDialog.cpp \ 24 | src/DataMath.cpp \ 25 | src/QCustomPlot/qcustomplot.cpp \ 26 | src/main.cpp \ 27 | src/SimpleCsvLogAnalyzer.cpp 28 | 29 | HEADERS += \ 30 | src/CsvFileProcessor.h \ 31 | src/CustomFileDialog.h \ 32 | src/DataMath.h \ 33 | src/QCustomPlot/qcustomplot.h \ 34 | src/SimpleCsvLogAnalyzer.h 35 | 36 | FORMS += \ 37 | src/CustomFileDialog.ui \ 38 | src/DataMath.ui \ 39 | src/SimpleCsvLogAnalyzer.ui 40 | 41 | # Default rules for deployment. 42 | qnx: target.path = /tmp/$${TARGET}/bin 43 | else: unix:!android: target.path = /opt/$${TARGET}/bin 44 | !isEmpty(target.path): INSTALLS += target 45 | 46 | RESOURCES += \ 47 | icons.qrc 48 | 49 | DISTFILES += \ 50 | android/AndroidManifest.xml \ 51 | android/build.gradle \ 52 | android/gradle/wrapper/gradle-wrapper.jar \ 53 | android/gradle/wrapper/gradle-wrapper.properties \ 54 | android/gradlew \ 55 | android/gradlew.bat \ 56 | android/res/values/libs.xml 57 | 58 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /src/CustomFileDialog.cpp: -------------------------------------------------------------------------------- 1 | #include "CustomFileDialog.h" 2 | #include "ui_CustomFileDialog.h" 3 | 4 | #include 5 | 6 | CustomFileDialog::CustomFileDialog(QWidget *parent, bool saveFile, QString defaultFile) : 7 | QDialog(parent), 8 | ui(new Ui::CustomFileDialog) 9 | { 10 | mSaveFile = saveFile; 11 | mDefaultFileName = defaultFile; 12 | ui->setupUi(this); 13 | 14 | if(mSaveFile){ 15 | ui->okBtn->setText("Save"); 16 | } 17 | ui->fileNameEdit->setText(mDefaultFileName); 18 | // Creates our new model and populate 19 | QString mPath = "/storage/emulated/0/"; 20 | 21 | // All entries 22 | model = new QFileSystemModel(this); 23 | model->setFilter(QDir::AllEntries | QDir::NoDot); 24 | model->setNameFilters(QStringList()<< "*.csv" << "*.jpg"); 25 | 26 | ui->listView->setModel(model); 27 | ui->listView->setRootIndex(model->setRootPath(mPath)); 28 | ui->filePathEdit->setText(model->rootPath()); 29 | fi.setFile(model->rootPath()); 30 | 31 | 32 | // qlineedits cannot effectively catch enter key event so it should be handled! 33 | // One can disable this behavior by setting setDefault() and setAutoDefault() on the button. To disable this on all buttons in your dialog add this snippet after you instantiated and initialized the ui from Designer: 34 | 35 | // @ 36 | // QList buttonList = findChildren(); 37 | // foreach(QPushButton *pb, buttonList) { 38 | // pb->setDefault( false ); 39 | // pb->setAutoDefault( false ); 40 | // } 41 | // @ 42 | 43 | QList buttonList = findChildren(); 44 | foreach(QPushButton *pb, buttonList) { 45 | pb->setDefault( false ); 46 | pb->setAutoDefault( false ); 47 | } 48 | 49 | } 50 | 51 | CustomFileDialog::~CustomFileDialog() 52 | { 53 | delete ui; 54 | } 55 | 56 | 57 | void CustomFileDialog::on_listView_clicked(const QModelIndex &index) 58 | { 59 | QString mPath = model->fileInfo(index).canonicalFilePath(); 60 | fi.setFile(mPath); 61 | if(fi.isDir()){ 62 | qDebug() << mPath << "is a directory"; 63 | ui->listView->setRootIndex(model->setRootPath(mPath)); 64 | if(!mSaveFile){ 65 | ui->fileNameEdit->clear(); 66 | } 67 | } else { 68 | qDebug() << mPath << "is a file"; 69 | ui->fileNameEdit->setText(fi.fileName()); 70 | } 71 | // qDebug() << "Path:" << fi.canonicalFilePath(); 72 | ui->filePathEdit->setText(fi.canonicalFilePath()); 73 | 74 | } 75 | 76 | void CustomFileDialog::on_cancelBtn_clicked() 77 | { 78 | filePath.clear(); 79 | this->reject(); 80 | 81 | } 82 | 83 | void CustomFileDialog::on_filePathEdit_returnPressed() 84 | { 85 | qDebug() << "return pressed!"; 86 | } 87 | 88 | void CustomFileDialog::on_okBtn_clicked() 89 | { 90 | qDebug() << "Selected:" << ui->fileNameEdit->text(); 91 | QFileInfo tfi; 92 | tfi.setFile(model->rootPath(),ui->fileNameEdit->text()); 93 | if(tfi.isDir()){ 94 | qDebug() << "Yes," << tfi.canonicalFilePath() << "is a directory"; 95 | ui->listView->setRootIndex(model->setRootPath(tfi.canonicalFilePath())); 96 | } else { 97 | qDebug() << "It is a file:" << tfi.absoluteFilePath(); 98 | filePath = tfi.absoluteFilePath(); 99 | this->accept(); 100 | } 101 | ui->fileNameEdit->clear(); 102 | 103 | 104 | } 105 | 106 | void CustomFileDialog::on_fileNameEdit_returnPressed() 107 | { 108 | // qDebug() << "return pressed!"; 109 | on_okBtn_clicked(); 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/CustomFileDialog.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | CustomFileDialog 4 | 5 | 6 | 7 | 0 8 | 0 9 | 400 10 | 378 11 | 12 | 13 | 14 | Dialog 15 | 16 | 17 | 18 | 15 19 | 20 | 21 | 10 22 | 23 | 24 | 15 25 | 26 | 27 | 10 28 | 29 | 30 | 31 | 32 | false 33 | 34 | 35 | true 36 | 37 | 38 | Qt::NoContextMenu 39 | 40 | 41 | false 42 | 43 | 44 | true 45 | 46 | 47 | 0 48 | 49 | 50 | true 51 | 52 | 53 | 54 | 55 | 56 | 57 | Qt::NoContextMenu 58 | 59 | 60 | QFrame::NoFrame 61 | 62 | 63 | QFrame::Plain 64 | 65 | 66 | 1 67 | 68 | 69 | Qt::ScrollBarAlwaysOff 70 | 71 | 72 | QAbstractItemView::NoEditTriggers 73 | 74 | 75 | false 76 | 77 | 78 | Qt::CopyAction 79 | 80 | 81 | QListView::SinglePass 82 | 83 | 84 | QListView::ListMode 85 | 86 | 87 | 0 88 | 89 | 90 | false 91 | 92 | 93 | 94 | 95 | 96 | 97 | false 98 | 99 | 100 | 101 | 102 | 103 | 104 | 0 105 | 106 | 107 | 0 108 | 109 | 110 | 111 | 112 | Cancel 113 | 114 | 115 | false 116 | 117 | 118 | 119 | 120 | 121 | 122 | Open 123 | 124 | 125 | false 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /ui_CustomFileDialog.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | ** Form generated from reading UI file 'CustomFileDialog.ui' 3 | ** 4 | ** Created by: Qt User Interface Compiler version 5.14.2 5 | ** 6 | ** WARNING! All changes made in this file will be lost when recompiling UI file! 7 | ********************************************************************************/ 8 | 9 | #ifndef UI_CUSTOMFILEDIALOG_H 10 | #define UI_CUSTOMFILEDIALOG_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | QT_BEGIN_NAMESPACE 22 | 23 | class Ui_CustomFileDialog 24 | { 25 | public: 26 | QVBoxLayout *verticalLayout; 27 | QLineEdit *filePathEdit; 28 | QListView *listView; 29 | QLineEdit *fileNameEdit; 30 | QHBoxLayout *horizontalLayout; 31 | QPushButton *cancelBtn; 32 | QPushButton *okBtn; 33 | 34 | void setupUi(QDialog *CustomFileDialog) 35 | { 36 | if (CustomFileDialog->objectName().isEmpty()) 37 | CustomFileDialog->setObjectName(QString::fromUtf8("CustomFileDialog")); 38 | CustomFileDialog->resize(400, 378); 39 | verticalLayout = new QVBoxLayout(CustomFileDialog); 40 | verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); 41 | verticalLayout->setContentsMargins(15, 10, 15, 10); 42 | filePathEdit = new QLineEdit(CustomFileDialog); 43 | filePathEdit->setObjectName(QString::fromUtf8("filePathEdit")); 44 | filePathEdit->setMouseTracking(false); 45 | filePathEdit->setTabletTracking(true); 46 | filePathEdit->setContextMenuPolicy(Qt::NoContextMenu); 47 | filePathEdit->setAcceptDrops(false); 48 | filePathEdit->setFrame(true); 49 | filePathEdit->setCursorPosition(0); 50 | filePathEdit->setReadOnly(true); 51 | 52 | verticalLayout->addWidget(filePathEdit); 53 | 54 | listView = new QListView(CustomFileDialog); 55 | listView->setObjectName(QString::fromUtf8("listView")); 56 | listView->setContextMenuPolicy(Qt::NoContextMenu); 57 | listView->setFrameShape(QFrame::NoFrame); 58 | listView->setFrameShadow(QFrame::Plain); 59 | listView->setLineWidth(1); 60 | listView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 61 | listView->setEditTriggers(QAbstractItemView::NoEditTriggers); 62 | listView->setProperty("showDropIndicator", QVariant(false)); 63 | listView->setDefaultDropAction(Qt::CopyAction); 64 | listView->setLayoutMode(QListView::SinglePass); 65 | listView->setViewMode(QListView::ListMode); 66 | listView->setModelColumn(0); 67 | listView->setUniformItemSizes(false); 68 | 69 | verticalLayout->addWidget(listView); 70 | 71 | fileNameEdit = new QLineEdit(CustomFileDialog); 72 | fileNameEdit->setObjectName(QString::fromUtf8("fileNameEdit")); 73 | fileNameEdit->setReadOnly(false); 74 | 75 | verticalLayout->addWidget(fileNameEdit); 76 | 77 | horizontalLayout = new QHBoxLayout(); 78 | horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); 79 | horizontalLayout->setContentsMargins(-1, 0, 0, -1); 80 | cancelBtn = new QPushButton(CustomFileDialog); 81 | cancelBtn->setObjectName(QString::fromUtf8("cancelBtn")); 82 | cancelBtn->setAutoDefault(false); 83 | 84 | horizontalLayout->addWidget(cancelBtn); 85 | 86 | okBtn = new QPushButton(CustomFileDialog); 87 | okBtn->setObjectName(QString::fromUtf8("okBtn")); 88 | okBtn->setAutoDefault(false); 89 | 90 | horizontalLayout->addWidget(okBtn); 91 | 92 | 93 | verticalLayout->addLayout(horizontalLayout); 94 | 95 | 96 | retranslateUi(CustomFileDialog); 97 | 98 | QMetaObject::connectSlotsByName(CustomFileDialog); 99 | } // setupUi 100 | 101 | void retranslateUi(QDialog *CustomFileDialog) 102 | { 103 | CustomFileDialog->setWindowTitle(QCoreApplication::translate("CustomFileDialog", "Dialog", nullptr)); 104 | cancelBtn->setText(QCoreApplication::translate("CustomFileDialog", "Cancel", nullptr)); 105 | okBtn->setText(QCoreApplication::translate("CustomFileDialog", "Open", nullptr)); 106 | } // retranslateUi 107 | 108 | }; 109 | 110 | namespace Ui { 111 | class CustomFileDialog: public Ui_CustomFileDialog {}; 112 | } // namespace Ui 113 | 114 | QT_END_NAMESPACE 115 | 116 | #endif // UI_CUSTOMFILEDIALOG_H 117 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /src/DataMath.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | DataMath 4 | 5 | 6 | 7 | 0 8 | 0 9 | 640 10 | 480 11 | 12 | 13 | 14 | 15 | 0 16 | 0 17 | 18 | 19 | 20 | 21 | Arial 22 | 9 23 | 24 | 25 | 26 | Create new derived data (Data Math) 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Arial 36 | 11 37 | 75 38 | true 39 | 40 | 41 | 42 | false 43 | 44 | 45 | false 46 | 47 | 48 | QAbstractItemView::NoDragDrop 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | Arial 57 | 11 58 | 75 59 | true 60 | 61 | 62 | 63 | false 64 | 65 | 66 | false 67 | 68 | 69 | QAbstractItemView::NoDragDrop 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Arial 80 | 10 81 | 75 82 | true 83 | 84 | 85 | 86 | Math operations are evaluated left to right. 87 | 88 | 89 | Qt::AlignCenter 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Arial 100 | 10 101 | 75 102 | true 103 | 104 | 105 | 106 | Data Math: 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | Arial 115 | 10 116 | 75 117 | true 118 | 119 | 120 | 121 | false 122 | 123 | 124 | A derived data element is a data element derived from other data elements using a mathematical, logical, or other type of transformation, e.g. arithmetic formula, composition, aggregation. 125 | 126 | 127 | 128 | 129 | 130 | true 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | Arial 139 | 10 140 | 75 141 | true 142 | 143 | 144 | 145 | Undo 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | Arial 156 | 10 157 | 75 158 | true 159 | 160 | 161 | 162 | Qt::Horizontal 163 | 164 | 165 | QDialogButtonBox::Cancel|QDialogButtonBox::Ok 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | buttonBox 175 | accepted() 176 | DataMath 177 | accept() 178 | 179 | 180 | 248 181 | 254 182 | 183 | 184 | 157 185 | 274 186 | 187 | 188 | 189 | 190 | buttonBox 191 | rejected() 192 | DataMath 193 | reject() 194 | 195 | 196 | 316 197 | 260 198 | 199 | 200 | 286 201 | 274 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /ui_DataMath.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | ** Form generated from reading UI file 'DataMath.ui' 3 | ** 4 | ** Created by: Qt User Interface Compiler version 5.14.2 5 | ** 6 | ** WARNING! All changes made in this file will be lost when recompiling UI file! 7 | ********************************************************************************/ 8 | 9 | #ifndef UI_DATAMATH_H 10 | #define UI_DATAMATH_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | QT_BEGIN_NAMESPACE 24 | 25 | class Ui_DataMath 26 | { 27 | public: 28 | QVBoxLayout *verticalLayout; 29 | QHBoxLayout *horizontalLayout; 30 | QListWidget *dataLabels; 31 | QListWidget *operatorList; 32 | QLabel *label_2; 33 | QHBoxLayout *horizontalLayout_2; 34 | QLabel *label; 35 | QLineEdit *dataMath; 36 | QPushButton *clear; 37 | QDialogButtonBox *buttonBox; 38 | 39 | void setupUi(QDialog *DataMath) 40 | { 41 | if (DataMath->objectName().isEmpty()) 42 | DataMath->setObjectName(QString::fromUtf8("DataMath")); 43 | DataMath->resize(640, 480); 44 | QSizePolicy sizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); 45 | sizePolicy.setHorizontalStretch(0); 46 | sizePolicy.setVerticalStretch(0); 47 | sizePolicy.setHeightForWidth(DataMath->sizePolicy().hasHeightForWidth()); 48 | DataMath->setSizePolicy(sizePolicy); 49 | QFont font; 50 | font.setFamily(QString::fromUtf8("Arial")); 51 | font.setPointSize(9); 52 | DataMath->setFont(font); 53 | verticalLayout = new QVBoxLayout(DataMath); 54 | verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); 55 | horizontalLayout = new QHBoxLayout(); 56 | horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); 57 | dataLabels = new QListWidget(DataMath); 58 | dataLabels->setObjectName(QString::fromUtf8("dataLabels")); 59 | QFont font1; 60 | font1.setFamily(QString::fromUtf8("Arial")); 61 | font1.setPointSize(11); 62 | font1.setBold(true); 63 | font1.setWeight(75); 64 | dataLabels->setFont(font1); 65 | dataLabels->setProperty("showDropIndicator", QVariant(false)); 66 | dataLabels->setDragEnabled(false); 67 | dataLabels->setDragDropMode(QAbstractItemView::NoDragDrop); 68 | 69 | horizontalLayout->addWidget(dataLabels); 70 | 71 | operatorList = new QListWidget(DataMath); 72 | operatorList->setObjectName(QString::fromUtf8("operatorList")); 73 | operatorList->setFont(font1); 74 | operatorList->setProperty("showDropIndicator", QVariant(false)); 75 | operatorList->setDragEnabled(false); 76 | operatorList->setDragDropMode(QAbstractItemView::NoDragDrop); 77 | 78 | horizontalLayout->addWidget(operatorList); 79 | 80 | 81 | verticalLayout->addLayout(horizontalLayout); 82 | 83 | label_2 = new QLabel(DataMath); 84 | label_2->setObjectName(QString::fromUtf8("label_2")); 85 | QFont font2; 86 | font2.setFamily(QString::fromUtf8("Arial")); 87 | font2.setPointSize(10); 88 | font2.setBold(true); 89 | font2.setWeight(75); 90 | label_2->setFont(font2); 91 | label_2->setAlignment(Qt::AlignCenter); 92 | 93 | verticalLayout->addWidget(label_2); 94 | 95 | horizontalLayout_2 = new QHBoxLayout(); 96 | horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2")); 97 | label = new QLabel(DataMath); 98 | label->setObjectName(QString::fromUtf8("label")); 99 | label->setFont(font2); 100 | 101 | horizontalLayout_2->addWidget(label); 102 | 103 | dataMath = new QLineEdit(DataMath); 104 | dataMath->setObjectName(QString::fromUtf8("dataMath")); 105 | dataMath->setFont(font2); 106 | dataMath->setAcceptDrops(false); 107 | dataMath->setReadOnly(true); 108 | 109 | horizontalLayout_2->addWidget(dataMath); 110 | 111 | clear = new QPushButton(DataMath); 112 | clear->setObjectName(QString::fromUtf8("clear")); 113 | clear->setFont(font2); 114 | 115 | horizontalLayout_2->addWidget(clear); 116 | 117 | 118 | verticalLayout->addLayout(horizontalLayout_2); 119 | 120 | buttonBox = new QDialogButtonBox(DataMath); 121 | buttonBox->setObjectName(QString::fromUtf8("buttonBox")); 122 | buttonBox->setFont(font2); 123 | buttonBox->setOrientation(Qt::Horizontal); 124 | buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); 125 | 126 | verticalLayout->addWidget(buttonBox); 127 | 128 | 129 | retranslateUi(DataMath); 130 | QObject::connect(buttonBox, SIGNAL(accepted()), DataMath, SLOT(accept())); 131 | QObject::connect(buttonBox, SIGNAL(rejected()), DataMath, SLOT(reject())); 132 | 133 | QMetaObject::connectSlotsByName(DataMath); 134 | } // setupUi 135 | 136 | void retranslateUi(QDialog *DataMath) 137 | { 138 | DataMath->setWindowTitle(QCoreApplication::translate("DataMath", "Create new derived data (Data Math)", nullptr)); 139 | label_2->setText(QCoreApplication::translate("DataMath", "Math operations are evaluated left to right.", nullptr)); 140 | label->setText(QCoreApplication::translate("DataMath", "Data Math:", nullptr)); 141 | #if QT_CONFIG(tooltip) 142 | dataMath->setToolTip(QCoreApplication::translate("DataMath", "A derived data element is a data element derived from other data elements using a mathematical, logical, or other type of transformation, e.g. arithmetic formula, composition, aggregation.", nullptr)); 143 | #endif // QT_CONFIG(tooltip) 144 | dataMath->setInputMask(QString()); 145 | clear->setText(QCoreApplication::translate("DataMath", "Undo", nullptr)); 146 | } // retranslateUi 147 | 148 | }; 149 | 150 | namespace Ui { 151 | class DataMath: public Ui_DataMath {}; 152 | } // namespace Ui 153 | 154 | QT_END_NAMESPACE 155 | 156 | #endif // UI_DATAMATH_H 157 | -------------------------------------------------------------------------------- /src/SimpleCsvLogAnalyzer.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMPLECSVLOGANALYZER_H 2 | #define SIMPLECSVLOGANALYZER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "QCustomPlot/qcustomplot.h" 13 | #include "CsvFileProcessor.h" 14 | #include "DataMath.h" 15 | #include "CustomFileDialog.h" 16 | #include 17 | 18 | #ifdef Q_OS_ANDROID 19 | #include 20 | #endif 21 | 22 | 23 | 24 | enum{ 25 | PLOT_NONE, 26 | PLOT_Y_VS_POINT_NUM, 27 | PLOT_Y_VS_X, 28 | PLOT_Y1_AND_Y2_VS_POINT_NUM, 29 | PLOT_Y1_Y2_VS_X 30 | }; 31 | 32 | typedef struct{ 33 | double min = 0; 34 | double max = 0; 35 | double span = 0; 36 | double average = 0; 37 | double median = 0; 38 | int length; 39 | }_statistics; 40 | 41 | typedef struct{ 42 | _statistics x; 43 | _statistics y; 44 | }statistics; 45 | 46 | QT_BEGIN_NAMESPACE 47 | namespace Ui { class SimpleCsvLogAnalyzer; } 48 | QT_END_NAMESPACE 49 | 50 | class SimpleCsvLogAnalyzer : public QMainWindow 51 | { 52 | Q_OBJECT 53 | 54 | public: 55 | // variables 56 | // methods 57 | SimpleCsvLogAnalyzer(QWidget *parent = nullptr); 58 | ~SimpleCsvLogAnalyzer(); 59 | 60 | void plotGraph(QString xName, QString yName); 61 | 62 | private slots: 63 | void on_actionExit_triggered(); 64 | void on_actionOpen_triggered(); 65 | void on_plotSelected_clicked(); 66 | void on_plotSelectedXY_clicked(); 67 | void tracerEvent(QMouseEvent * event); 68 | void moveRigthPressed(); 69 | void on_actionZoom_Reset_triggered(); 70 | void on_actionSave_Plot_Image_triggered(); 71 | void on_dataListY_currentRowChanged(int currentRow); 72 | void on_rightTabs_currentChanged(int index); 73 | void on_rightTabs_tabBarClicked(int index); 74 | // void on_dataTableWidget_customContextMenuRequested(const QPoint &pos); 75 | void on_dataListY_customContextMenuRequested(const QPoint &pos); 76 | void on_DataDerivator_clicked(); 77 | 78 | void on_actionData_Derivator_triggered(); 79 | 80 | void on_actionPlot_SelectedData_triggered(); 81 | 82 | void on_actionplot_SelectedDataVsSelectedData_triggered(); 83 | 84 | void on_actionZoom_In_triggered(); 85 | 86 | void on_actionZoom_Out_triggered(); 87 | 88 | void plotThisPredefinedQuickPlot(QString labelNameForY, QString labelNameForX); 89 | QString getProperLabelName(QString name); 90 | 91 | void on_predefinedPlot1_clicked(); 92 | 93 | void on_predefinedPlot2_clicked(); 94 | 95 | void on_predefinedPlot3_clicked(); 96 | 97 | void on_predefinedPlot4_clicked(); 98 | 99 | void on_predefinedPlot5_clicked(); 100 | 101 | void on_predefinedPlot7_clicked(); 102 | 103 | void on_predefinedPlot6_clicked(); 104 | 105 | void on_predefinedPlot8_clicked(); 106 | 107 | void on_predefinedPlot9_clicked(); 108 | 109 | void on_predefinedPlot10_clicked(); 110 | 111 | public slots: 112 | // Slots for data table view custom context menu options 113 | // void hideTableColumns_forTable(); 114 | // void showTableColumns_forTable(); 115 | // void restoreTableColumns_forTable(); 116 | // void plotThis_forTable(); 117 | // void statisticsForThis_forTable(); 118 | void plotThis_forList(); 119 | void plotThisVsAnotherDataLabel_forList(); 120 | void statisticsForThis_forList(); 121 | 122 | private: 123 | // variables 124 | Ui::SimpleCsvLogAnalyzer *ui; 125 | CsvFileProcessor csvFile; 126 | QCPItemTracer *tracer; 127 | QCPCurve *verticalLine; 128 | QShortcut *moveRight,*moveLeft; 129 | QSplashScreen *loadingSplash; 130 | QMenu *tableViewContextMenu; 131 | QMenu *labelListContextMenu; 132 | double mousePlotCoordX = 0; 133 | double mousePlotCoordY = 0; 134 | QVector xVals; 135 | QVector yVals; 136 | QVector> derivedDataVector; 137 | QVector derivedDataVectorLabels; 138 | statistics stats; 139 | QStringList mathOperatorsList = QStringList() << "+" << "-" << "*" << "/"; 140 | QString mathStringStart = QString("_drvd("); 141 | QString mathStringEnd = QString(")_"); 142 | QString torqueDeviceTimeFormat = QString("d-MMM-yyyy HH:mm:ss.zzz"); // e.g. 12-Jul-2015 22:15:00.473 143 | QLocale defaultEngLocale = QLocale(QLocale::English, QLocale::UnitedStates); 144 | QStringList m_labels,m_sampleValues; 145 | int plotType = PLOT_NONE; 146 | double zoomCursorCenter = 0; 147 | 148 | // Plots 149 | QCPGraph *valuePlot; 150 | QCPGraph *cursorPlot; 151 | 152 | #ifdef Q_OS_ANDROID 153 | #endif 154 | 155 | // methods 156 | void cleanUpAndExit(); 157 | void initPlot(); 158 | //void initDataTable(); 159 | void zoomReset(); 160 | QList calculateSlopeOfCurve(double keyValue); 161 | void clearPlotNDisableTracer(); 162 | void setupTracer(); 163 | statistics calculateStatisticalData(QVector x, QVector y, bool showReportMessage); 164 | void populateStatisticsLabels(); 165 | void clearStatisticsLabels(); 166 | void startBusy(); 167 | void stopBusy(); 168 | QString createDerivedDataLabel(QStringList formula); 169 | 170 | static void showMessage(QString test){ 171 | QMessageBox msgBox; 172 | msgBox.setText(test); 173 | msgBox.exec(); 174 | } 175 | 176 | enum { 177 | permissionDenied, 178 | alreadyGranted, 179 | granted 180 | }; 181 | 182 | static int getAndroidPermission(QString permissionName){ 183 | #if defined (Q_OS_ANDROID) 184 | int ret = permissionDenied; 185 | //Request requiered permissions at runtime 186 | auto result = QtAndroid::checkPermission(permissionName); 187 | if(result == QtAndroid::PermissionResult::Denied){ 188 | //showMessage("Permission has not given before!, Requesting now"); 189 | auto resultHash = QtAndroid::requestPermissionsSync(QStringList({permissionName})); 190 | if(resultHash[permissionName] == QtAndroid::PermissionResult::Denied){ 191 | showMessage("Permission denied to "+permissionName); 192 | int ret = permissionDenied; 193 | } else { 194 | showMessage("Permission granted to "+permissionName); 195 | ret = granted; 196 | } 197 | } else { 198 | ret = alreadyGranted; 199 | } 200 | return ret; 201 | #endif 202 | return -1; 203 | } 204 | 205 | }; 206 | #endif // 207 | -------------------------------------------------------------------------------- /android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | 8 | 9 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /src/CsvFileProcessor.cpp: -------------------------------------------------------------------------------- 1 | #include "CsvFileProcessor.h" 2 | 3 | #include 4 | 5 | 6 | CsvFileProcessor::CsvFileProcessor(QObject *parent) : QObject(parent) 7 | { 8 | 9 | } 10 | 11 | void CsvFileProcessor::setFilePath(QString filePath) 12 | { 13 | m_filePath = filePath; 14 | if(m_file.isOpen()){ 15 | m_file.close(); 16 | } 17 | m_file.setFileName(m_filePath); 18 | if(!m_file.open(QIODevice::ReadOnly)){ 19 | qDebug() << "File could not opened!"; 20 | } 21 | } 22 | 23 | QByteArray CsvFileProcessor::readLineFromCSV(QFile *file, uint16_t maxLen){ 24 | // QIODEvice::readLine support only \n line endings, 25 | // This method accepts either \n or \r line ending 26 | QByteArray result; 27 | if(!file->isOpen()){ 28 | qDebug() << "File is not opened!"; 29 | return result; 30 | } 31 | 32 | result.resize(maxLen); 33 | int readBytes = 0; 34 | char c = 0; 35 | bool readMore = true; 36 | while(readMore) { 37 | file->getChar(&c); 38 | result[readBytes] = c; 39 | ++readBytes; 40 | if((readBytes > (maxLen-2)) || (c == '\n') || (c == '\r')){ 41 | readMore = false; 42 | } 43 | } 44 | result[readBytes] = 0; 45 | // some csv files have \r\n line ending, e.g. my temp. Humidity logger. 46 | // check there is a following \n or \r in the read line 47 | // if true, skip it, if false rewind 48 | file->getChar(&c); 49 | if((c != '\n') || (c != '\r')){ 50 | file->seek(-1); 51 | } 52 | //qDebug() << "readBytes:" << readBytes; 53 | return result; 54 | } 55 | 56 | QStringList CsvFileProcessor::getCsvFileLabels() 57 | { 58 | if(!m_file.isOpen()){ 59 | qDebug() << "No csv file specified"; 60 | m_valueNames.clear(); 61 | return m_valueNames; 62 | } 63 | m_file.seek(0); // seek to start of the file 64 | // Get value field names from first line 65 | //QString str = QString::fromUtf8(m_file.readLine()); 66 | QString str = QString::fromUtf8(readLineFromCSV(&m_file)); 67 | //qDebug() << "Titles:" << str; 68 | m_valueNames = str.split(valueSeperator); 69 | for(int i=0;i CsvFileProcessor::getDataByName(QString dataName) 98 | { 99 | bool ok = false; 100 | double dVal; 101 | values.clear(); 102 | int index = m_valueNames.indexOf(dataName); 103 | if(index==-1){ 104 | qDebug() << "No matching data name"; 105 | return values; 106 | } 107 | //qDebug() << "Data index:" << index; 108 | // Gather values 109 | QString str; 110 | QStringList strList; 111 | m_file.seek(0); // seek to start of the file 112 | readLineFromCSV(&m_file); // skip labels 113 | str = QString::fromUtf8(readLineFromCSV(&m_file)); 114 | while(!str.isEmpty()){ 115 | strList = str.split(valueSeperator); 116 | dVal = strList.value(index).toDouble(&ok); 117 | //qDebug() << /*"Str:" << strList.value(index)*/ "StrList:" << strList << "value:" << dVal; 118 | if(!ok){ 119 | dVal = NAN; 120 | //qDebug() << "toDouble error. str:" << strList.value(index); 121 | //break; 122 | } 123 | values.append(dVal); 124 | str = QString::fromUtf8(readLineFromCSV(&m_file)); 125 | } 126 | if(values.isEmpty()){ 127 | qDebug() << "Values is empty"; 128 | } else { 129 | qDebug() << "str:" << str << "first val:" << values.first() << "last val:" << values.last() << "value count" << values.length(); 130 | } 131 | return values; 132 | } 133 | 134 | QStringList CsvFileProcessor::getRawDataByName(QString dataName) 135 | { 136 | QStringList vals; 137 | int index = m_valueNames.indexOf(dataName); 138 | if(index==-1){ 139 | qDebug() << "No matching data name"; 140 | return vals; 141 | } 142 | //qDebug() << "Data index:" << index; 143 | // Gather values 144 | QString str; 145 | QStringList strList; 146 | m_file.seek(0); // seek to start of the file 147 | readLineFromCSV(&m_file); // skip labels 148 | str = QString::fromUtf8(readLineFromCSV(&m_file)); 149 | while(!str.isEmpty()){ 150 | strList = str.split(valueSeperator); 151 | vals.append(strList.value(index)); 152 | str = QString::fromUtf8(readLineFromCSV(&m_file)); 153 | } 154 | if(vals.isEmpty()){ 155 | qDebug() << "Values is empty"; 156 | } else { 157 | qDebug() << "str:" << str << "first val:" << vals.first() << "last val:" << vals.last() << "value count" << vals.length(); 158 | } 159 | return vals; 160 | } 161 | 162 | bool CsvFileProcessor::file2TableWidget(QTableWidget *tw) 163 | { 164 | if(!m_file.isOpen()){ 165 | qDebug() << "No csv file specified"; 166 | return false; 167 | } 168 | QString str; 169 | QStringList values; 170 | values = getCsvFileLabels(); 171 | tw->clear(); 172 | tw->setRowCount(0); 173 | tw->setColumnCount(0); 174 | tw->setColumnCount(values.length()); 175 | tw->setHorizontalHeaderLabels(values); 176 | tw->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); 177 | 178 | 179 | m_file.seek(0); // seek to start of the file 180 | readLineFromCSV(&m_file); // skip labels 181 | str = QString::fromUtf8(readLineFromCSV(&m_file)); 182 | int rowNum = 0; 183 | while(!str.isEmpty()){ 184 | tw->insertRow(rowNum); 185 | values = str.split(valueSeperator); 186 | for(int i=0;isetItem(rowNum,i,newItem); 189 | } 190 | str = QString::fromUtf8(readLineFromCSV(&m_file)); 191 | ++rowNum; 192 | } 193 | 194 | 195 | return true; 196 | } 197 | 198 | bool CsvFileProcessor::file2DataModel(QStandardItemModel *mdl) 199 | { 200 | if(!m_file.isOpen()){ 201 | qDebug() << "No csv file specified"; 202 | return false; 203 | } 204 | if(mdl == nullptr){ 205 | qDebug() << "Model error!"; 206 | return false; 207 | } 208 | QString str; 209 | QStringList values; 210 | QModelIndex index; 211 | values = getCsvFileLabels(); 212 | mdl->clear(); 213 | mdl->setColumnCount(values.length()); 214 | mdl->setHorizontalHeaderLabels(values); 215 | 216 | m_file.seek(0); // seek to start of the file 217 | readLineFromCSV(&m_file); // skip labels 218 | str = QString::fromUtf8(readLineFromCSV(&m_file)); 219 | int rowNum = 0; 220 | while(!str.isEmpty()){ 221 | mdl->insertRow(rowNum); 222 | values = str.split(valueSeperator); 223 | for(int i=0;iindex(rowNum,i,QModelIndex()); 225 | mdl->setData(index,values.at(i).trimmed()); 226 | } 227 | str = QString::fromUtf8(readLineFromCSV(&m_file)); 228 | ++rowNum; 229 | //QApplication::processEvents(); 230 | } 231 | 232 | } 233 | 234 | //bool CsvFileProcessor::file2TableWidget(QTableWidget *tw) 235 | //{ 236 | // if(!m_file.isOpen()){ 237 | // qDebug() << "No csv file specified"; 238 | // return false; 239 | // } 240 | // QString str; 241 | // QStringList values; 242 | // values = getCsvFileLabels(); 243 | // tw->clear(); 244 | // tw->setRowCount(0); 245 | // tw->setColumnCount(0); 246 | // tw->setColumnCount(values.length()); 247 | // tw->setHorizontalHeaderLabels(values); 248 | // tw->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); 249 | 250 | // m_file.seek(0); // seek to start of the file 251 | // readLineFromCSV(&m_file); // skip labels 252 | // str = QString::fromUtf8(readLineFromCSV(&m_file)); 253 | // int rowNum = 0; 254 | // while(!str.isEmpty()){ 255 | // tw->insertRow(rowNum); 256 | // values = str.split(valueSeperator); 257 | // for(int i=0;isetItem(rowNum,i,newItem); 260 | // } 261 | // str = QString::fromUtf8(readLineFromCSV(&m_file)); 262 | // ++rowNum; 263 | // } 264 | // return true; 265 | //} 266 | 267 | -------------------------------------------------------------------------------- /ui_SimpleCsvLogAnalyzer.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************** 2 | ** Form generated from reading UI file 'SimpleCsvLogAnalyzer.ui' 3 | ** 4 | ** Created by: Qt User Interface Compiler version 5.14.2 5 | ** 6 | ** WARNING! All changes made in this file will be lost when recompiling UI file! 7 | ********************************************************************************/ 8 | 9 | #ifndef UI_SIMPLECSVLOGANALYZER_H 10 | #define UI_SIMPLECSVLOGANALYZER_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "src/QCustomPlot/qcustomplot.h" 29 | 30 | QT_BEGIN_NAMESPACE 31 | 32 | class Ui_SimpleCsvLogAnalyzer 33 | { 34 | public: 35 | QAction *actionOpen; 36 | QAction *actionExit; 37 | QAction *actionZoom_Reset; 38 | QAction *actionSave_Plot_Image; 39 | QAction *actionData_Derivator; 40 | QAction *actionPlot_SelectedData; 41 | QAction *actionplot_SelectedDataVsSelectedData; 42 | QAction *actionZoom_In; 43 | QAction *actionZoom_Out; 44 | QWidget *centralwidget; 45 | QGridLayout *gridLayout; 46 | QHBoxLayout *horizontalLayout_3; 47 | QLabel *minValueY; 48 | QFrame *line_5; 49 | QLabel *maxValueY; 50 | QFrame *line_6; 51 | QLabel *averageValueY; 52 | QFrame *line_7; 53 | QLabel *spanValueY; 54 | QHBoxLayout *horizontalLayout_4; 55 | QLabel *totalDataLength; 56 | QHBoxLayout *dataStatisticsLayout; 57 | QLabel *minValueX; 58 | QFrame *line_2; 59 | QLabel *maxValueX; 60 | QFrame *line_3; 61 | QLabel *averageValueX; 62 | QFrame *line_4; 63 | QLabel *spanValueX; 64 | QHBoxLayout *mainHorizontalLayout; 65 | QTabWidget *rightTabs; 66 | QWidget *plotTab; 67 | QVBoxLayout *verticalLayout_3; 68 | QCustomPlot *plot1; 69 | QVBoxLayout *verticalLayout_4; 70 | QWidget *dataTableViewTab; 71 | QVBoxLayout *verticalLayout_6; 72 | QHBoxLayout *horizontalLayout_2; 73 | QVBoxLayout *verticalLayout; 74 | QLabel *label_2; 75 | QListWidget *dataListY; 76 | QVBoxLayout *verticalLayout_5; 77 | QLabel *label_3; 78 | QListWidget *dataListX; 79 | QFrame *line_11; 80 | QHBoxLayout *horizontalLayout; 81 | QToolButton *plotSelected; 82 | QToolButton *plotSelectedXY; 83 | QToolButton *DataDerivator; 84 | QWidget *quickPlotPresets; 85 | QGridLayout *gridLayout_2; 86 | QToolButton *predefinedPlot1; 87 | QToolButton *predefinedPlot2; 88 | QToolButton *predefinedPlot9; 89 | QToolButton *predefinedPlot5; 90 | QToolButton *predefinedPlot7; 91 | QToolButton *predefinedPlot6; 92 | QToolButton *predefinedPlot3; 93 | QToolButton *predefinedPlot4; 94 | QToolButton *predefinedPlot8; 95 | QToolButton *predefinedPlot10; 96 | QStatusBar *statusbar; 97 | QToolBar *toolBar; 98 | 99 | void setupUi(QMainWindow *SimpleCsvLogAnalyzer) 100 | { 101 | if (SimpleCsvLogAnalyzer->objectName().isEmpty()) 102 | SimpleCsvLogAnalyzer->setObjectName(QString::fromUtf8("SimpleCsvLogAnalyzer")); 103 | SimpleCsvLogAnalyzer->resize(640, 721); 104 | QFont font; 105 | font.setFamily(QString::fromUtf8("Arial")); 106 | SimpleCsvLogAnalyzer->setFont(font); 107 | actionOpen = new QAction(SimpleCsvLogAnalyzer); 108 | actionOpen->setObjectName(QString::fromUtf8("actionOpen")); 109 | QIcon icon; 110 | icon.addFile(QString::fromUtf8(":/images/images/folder.png"), QSize(), QIcon::Normal, QIcon::Off); 111 | actionOpen->setIcon(icon); 112 | QFont font1; 113 | font1.setFamily(QString::fromUtf8("Arial")); 114 | font1.setPointSize(10); 115 | font1.setBold(true); 116 | font1.setWeight(75); 117 | actionOpen->setFont(font1); 118 | actionExit = new QAction(SimpleCsvLogAnalyzer); 119 | actionExit->setObjectName(QString::fromUtf8("actionExit")); 120 | actionZoom_Reset = new QAction(SimpleCsvLogAnalyzer); 121 | actionZoom_Reset->setObjectName(QString::fromUtf8("actionZoom_Reset")); 122 | QIcon icon1; 123 | icon1.addFile(QString::fromUtf8(":/images/images/zoomreset.png"), QSize(), QIcon::Normal, QIcon::Off); 124 | actionZoom_Reset->setIcon(icon1); 125 | actionZoom_Reset->setFont(font1); 126 | actionSave_Plot_Image = new QAction(SimpleCsvLogAnalyzer); 127 | actionSave_Plot_Image->setObjectName(QString::fromUtf8("actionSave_Plot_Image")); 128 | QIcon icon2; 129 | icon2.addFile(QString::fromUtf8(":/images/images/save.png"), QSize(), QIcon::Normal, QIcon::Off); 130 | actionSave_Plot_Image->setIcon(icon2); 131 | actionSave_Plot_Image->setFont(font1); 132 | actionData_Derivator = new QAction(SimpleCsvLogAnalyzer); 133 | actionData_Derivator->setObjectName(QString::fromUtf8("actionData_Derivator")); 134 | QIcon icon3; 135 | icon3.addFile(QString::fromUtf8(":/images/images/function.png"), QSize(), QIcon::Normal, QIcon::Off); 136 | actionData_Derivator->setIcon(icon3); 137 | actionData_Derivator->setFont(font1); 138 | actionPlot_SelectedData = new QAction(SimpleCsvLogAnalyzer); 139 | actionPlot_SelectedData->setObjectName(QString::fromUtf8("actionPlot_SelectedData")); 140 | QIcon icon4; 141 | icon4.addFile(QString::fromUtf8(":/images/images/ploty.png"), QSize(), QIcon::Normal, QIcon::Off); 142 | actionPlot_SelectedData->setIcon(icon4); 143 | actionPlot_SelectedData->setFont(font1); 144 | actionplot_SelectedDataVsSelectedData = new QAction(SimpleCsvLogAnalyzer); 145 | actionplot_SelectedDataVsSelectedData->setObjectName(QString::fromUtf8("actionplot_SelectedDataVsSelectedData")); 146 | QIcon icon5; 147 | icon5.addFile(QString::fromUtf8(":/images/images/plotxy.png"), QSize(), QIcon::Normal, QIcon::Off); 148 | actionplot_SelectedDataVsSelectedData->setIcon(icon5); 149 | actionplot_SelectedDataVsSelectedData->setFont(font1); 150 | actionZoom_In = new QAction(SimpleCsvLogAnalyzer); 151 | actionZoom_In->setObjectName(QString::fromUtf8("actionZoom_In")); 152 | QIcon icon6; 153 | icon6.addFile(QString::fromUtf8(":/images/images/zoomin.png"), QSize(), QIcon::Normal, QIcon::Off); 154 | actionZoom_In->setIcon(icon6); 155 | actionZoom_In->setFont(font1); 156 | actionZoom_Out = new QAction(SimpleCsvLogAnalyzer); 157 | actionZoom_Out->setObjectName(QString::fromUtf8("actionZoom_Out")); 158 | QIcon icon7; 159 | icon7.addFile(QString::fromUtf8(":/images/images/zoomout.png"), QSize(), QIcon::Normal, QIcon::Off); 160 | actionZoom_Out->setIcon(icon7); 161 | actionZoom_Out->setFont(font1); 162 | centralwidget = new QWidget(SimpleCsvLogAnalyzer); 163 | centralwidget->setObjectName(QString::fromUtf8("centralwidget")); 164 | gridLayout = new QGridLayout(centralwidget); 165 | gridLayout->setObjectName(QString::fromUtf8("gridLayout")); 166 | horizontalLayout_3 = new QHBoxLayout(); 167 | horizontalLayout_3->setObjectName(QString::fromUtf8("horizontalLayout_3")); 168 | horizontalLayout_3->setContentsMargins(0, 0, 0, -1); 169 | minValueY = new QLabel(centralwidget); 170 | minValueY->setObjectName(QString::fromUtf8("minValueY")); 171 | QFont font2; 172 | font2.setFamily(QString::fromUtf8("Arial")); 173 | font2.setPointSize(10); 174 | minValueY->setFont(font2); 175 | minValueY->setAlignment(Qt::AlignCenter); 176 | 177 | horizontalLayout_3->addWidget(minValueY); 178 | 179 | line_5 = new QFrame(centralwidget); 180 | line_5->setObjectName(QString::fromUtf8("line_5")); 181 | QFont font3; 182 | font3.setFamily(QString::fromUtf8("Arial")); 183 | font3.setPointSize(7); 184 | line_5->setFont(font3); 185 | line_5->setFrameShape(QFrame::VLine); 186 | line_5->setFrameShadow(QFrame::Sunken); 187 | 188 | horizontalLayout_3->addWidget(line_5); 189 | 190 | maxValueY = new QLabel(centralwidget); 191 | maxValueY->setObjectName(QString::fromUtf8("maxValueY")); 192 | maxValueY->setFont(font2); 193 | maxValueY->setAlignment(Qt::AlignCenter); 194 | 195 | horizontalLayout_3->addWidget(maxValueY); 196 | 197 | line_6 = new QFrame(centralwidget); 198 | line_6->setObjectName(QString::fromUtf8("line_6")); 199 | line_6->setFont(font3); 200 | line_6->setFrameShape(QFrame::VLine); 201 | line_6->setFrameShadow(QFrame::Sunken); 202 | 203 | horizontalLayout_3->addWidget(line_6); 204 | 205 | averageValueY = new QLabel(centralwidget); 206 | averageValueY->setObjectName(QString::fromUtf8("averageValueY")); 207 | averageValueY->setFont(font2); 208 | averageValueY->setAlignment(Qt::AlignCenter); 209 | 210 | horizontalLayout_3->addWidget(averageValueY); 211 | 212 | line_7 = new QFrame(centralwidget); 213 | line_7->setObjectName(QString::fromUtf8("line_7")); 214 | line_7->setFont(font3); 215 | line_7->setFrameShape(QFrame::VLine); 216 | line_7->setFrameShadow(QFrame::Sunken); 217 | 218 | horizontalLayout_3->addWidget(line_7); 219 | 220 | spanValueY = new QLabel(centralwidget); 221 | spanValueY->setObjectName(QString::fromUtf8("spanValueY")); 222 | spanValueY->setFont(font2); 223 | spanValueY->setAlignment(Qt::AlignCenter); 224 | 225 | horizontalLayout_3->addWidget(spanValueY); 226 | 227 | 228 | gridLayout->addLayout(horizontalLayout_3, 2, 0, 1, 1); 229 | 230 | horizontalLayout_4 = new QHBoxLayout(); 231 | horizontalLayout_4->setObjectName(QString::fromUtf8("horizontalLayout_4")); 232 | totalDataLength = new QLabel(centralwidget); 233 | totalDataLength->setObjectName(QString::fromUtf8("totalDataLength")); 234 | QFont font4; 235 | font4.setFamily(QString::fromUtf8("Arial")); 236 | font4.setPointSize(8); 237 | totalDataLength->setFont(font4); 238 | 239 | horizontalLayout_4->addWidget(totalDataLength); 240 | 241 | 242 | gridLayout->addLayout(horizontalLayout_4, 3, 0, 1, 1); 243 | 244 | dataStatisticsLayout = new QHBoxLayout(); 245 | dataStatisticsLayout->setSpacing(5); 246 | dataStatisticsLayout->setObjectName(QString::fromUtf8("dataStatisticsLayout")); 247 | dataStatisticsLayout->setContentsMargins(0, 0, 0, -1); 248 | minValueX = new QLabel(centralwidget); 249 | minValueX->setObjectName(QString::fromUtf8("minValueX")); 250 | minValueX->setFont(font2); 251 | minValueX->setAlignment(Qt::AlignCenter); 252 | 253 | dataStatisticsLayout->addWidget(minValueX); 254 | 255 | line_2 = new QFrame(centralwidget); 256 | line_2->setObjectName(QString::fromUtf8("line_2")); 257 | line_2->setFont(font3); 258 | line_2->setFrameShape(QFrame::VLine); 259 | line_2->setFrameShadow(QFrame::Sunken); 260 | 261 | dataStatisticsLayout->addWidget(line_2); 262 | 263 | maxValueX = new QLabel(centralwidget); 264 | maxValueX->setObjectName(QString::fromUtf8("maxValueX")); 265 | maxValueX->setFont(font2); 266 | maxValueX->setAlignment(Qt::AlignCenter); 267 | 268 | dataStatisticsLayout->addWidget(maxValueX); 269 | 270 | line_3 = new QFrame(centralwidget); 271 | line_3->setObjectName(QString::fromUtf8("line_3")); 272 | line_3->setFont(font3); 273 | line_3->setFrameShape(QFrame::VLine); 274 | line_3->setFrameShadow(QFrame::Sunken); 275 | 276 | dataStatisticsLayout->addWidget(line_3); 277 | 278 | averageValueX = new QLabel(centralwidget); 279 | averageValueX->setObjectName(QString::fromUtf8("averageValueX")); 280 | averageValueX->setFont(font2); 281 | averageValueX->setAlignment(Qt::AlignCenter); 282 | 283 | dataStatisticsLayout->addWidget(averageValueX); 284 | 285 | line_4 = new QFrame(centralwidget); 286 | line_4->setObjectName(QString::fromUtf8("line_4")); 287 | line_4->setFont(font3); 288 | line_4->setFrameShape(QFrame::VLine); 289 | line_4->setFrameShadow(QFrame::Sunken); 290 | 291 | dataStatisticsLayout->addWidget(line_4); 292 | 293 | spanValueX = new QLabel(centralwidget); 294 | spanValueX->setObjectName(QString::fromUtf8("spanValueX")); 295 | spanValueX->setFont(font2); 296 | spanValueX->setAlignment(Qt::AlignCenter); 297 | 298 | dataStatisticsLayout->addWidget(spanValueX); 299 | 300 | 301 | gridLayout->addLayout(dataStatisticsLayout, 1, 0, 1, 1); 302 | 303 | mainHorizontalLayout = new QHBoxLayout(); 304 | mainHorizontalLayout->setObjectName(QString::fromUtf8("mainHorizontalLayout")); 305 | rightTabs = new QTabWidget(centralwidget); 306 | rightTabs->setObjectName(QString::fromUtf8("rightTabs")); 307 | rightTabs->setFont(font1); 308 | plotTab = new QWidget(); 309 | plotTab->setObjectName(QString::fromUtf8("plotTab")); 310 | verticalLayout_3 = new QVBoxLayout(plotTab); 311 | verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3")); 312 | plot1 = new QCustomPlot(plotTab); 313 | plot1->setObjectName(QString::fromUtf8("plot1")); 314 | QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 315 | sizePolicy.setHorizontalStretch(0); 316 | sizePolicy.setVerticalStretch(0); 317 | sizePolicy.setHeightForWidth(plot1->sizePolicy().hasHeightForWidth()); 318 | plot1->setSizePolicy(sizePolicy); 319 | QFont font5; 320 | font5.setFamily(QString::fromUtf8("Arial")); 321 | font5.setPointSize(7); 322 | font5.setBold(true); 323 | font5.setWeight(75); 324 | plot1->setFont(font5); 325 | verticalLayout_4 = new QVBoxLayout(plot1); 326 | verticalLayout_4->setObjectName(QString::fromUtf8("verticalLayout_4")); 327 | 328 | verticalLayout_3->addWidget(plot1); 329 | 330 | rightTabs->addTab(plotTab, QString()); 331 | dataTableViewTab = new QWidget(); 332 | dataTableViewTab->setObjectName(QString::fromUtf8("dataTableViewTab")); 333 | verticalLayout_6 = new QVBoxLayout(dataTableViewTab); 334 | verticalLayout_6->setObjectName(QString::fromUtf8("verticalLayout_6")); 335 | horizontalLayout_2 = new QHBoxLayout(); 336 | horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2")); 337 | verticalLayout = new QVBoxLayout(); 338 | verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); 339 | label_2 = new QLabel(dataTableViewTab); 340 | label_2->setObjectName(QString::fromUtf8("label_2")); 341 | QSizePolicy sizePolicy1(QSizePolicy::Preferred, QSizePolicy::Maximum); 342 | sizePolicy1.setHorizontalStretch(0); 343 | sizePolicy1.setVerticalStretch(0); 344 | sizePolicy1.setHeightForWidth(label_2->sizePolicy().hasHeightForWidth()); 345 | label_2->setSizePolicy(sizePolicy1); 346 | label_2->setMaximumSize(QSize(16777215, 16777215)); 347 | QFont font6; 348 | font6.setFamily(QString::fromUtf8("Arial")); 349 | font6.setPointSize(9); 350 | font6.setBold(true); 351 | font6.setWeight(75); 352 | label_2->setFont(font6); 353 | 354 | verticalLayout->addWidget(label_2); 355 | 356 | dataListY = new QListWidget(dataTableViewTab); 357 | dataListY->setObjectName(QString::fromUtf8("dataListY")); 358 | sizePolicy.setHeightForWidth(dataListY->sizePolicy().hasHeightForWidth()); 359 | dataListY->setSizePolicy(sizePolicy); 360 | QFont font7; 361 | font7.setFamily(QString::fromUtf8("Arial")); 362 | font7.setPointSize(11); 363 | font7.setBold(true); 364 | font7.setWeight(75); 365 | dataListY->setFont(font7); 366 | dataListY->setContextMenuPolicy(Qt::CustomContextMenu); 367 | dataListY->setEditTriggers(QAbstractItemView::NoEditTriggers); 368 | dataListY->setProperty("showDropIndicator", QVariant(false)); 369 | dataListY->setDragEnabled(false); 370 | dataListY->setDragDropOverwriteMode(false); 371 | dataListY->setDragDropMode(QAbstractItemView::NoDragDrop); 372 | dataListY->setDefaultDropAction(Qt::IgnoreAction); 373 | 374 | verticalLayout->addWidget(dataListY); 375 | 376 | 377 | horizontalLayout_2->addLayout(verticalLayout); 378 | 379 | verticalLayout_5 = new QVBoxLayout(); 380 | verticalLayout_5->setObjectName(QString::fromUtf8("verticalLayout_5")); 381 | label_3 = new QLabel(dataTableViewTab); 382 | label_3->setObjectName(QString::fromUtf8("label_3")); 383 | sizePolicy1.setHeightForWidth(label_3->sizePolicy().hasHeightForWidth()); 384 | label_3->setSizePolicy(sizePolicy1); 385 | label_3->setMaximumSize(QSize(16777215, 16777215)); 386 | label_3->setFont(font6); 387 | 388 | verticalLayout_5->addWidget(label_3); 389 | 390 | dataListX = new QListWidget(dataTableViewTab); 391 | dataListX->setObjectName(QString::fromUtf8("dataListX")); 392 | sizePolicy.setHeightForWidth(dataListX->sizePolicy().hasHeightForWidth()); 393 | dataListX->setSizePolicy(sizePolicy); 394 | dataListX->setFont(font7); 395 | dataListX->setEditTriggers(QAbstractItemView::DoubleClicked); 396 | dataListX->setProperty("showDropIndicator", QVariant(false)); 397 | dataListX->setDragDropMode(QAbstractItemView::NoDragDrop); 398 | dataListX->setDefaultDropAction(Qt::IgnoreAction); 399 | dataListX->setSelectionMode(QAbstractItemView::SingleSelection); 400 | 401 | verticalLayout_5->addWidget(dataListX); 402 | 403 | 404 | horizontalLayout_2->addLayout(verticalLayout_5); 405 | 406 | 407 | verticalLayout_6->addLayout(horizontalLayout_2); 408 | 409 | line_11 = new QFrame(dataTableViewTab); 410 | line_11->setObjectName(QString::fromUtf8("line_11")); 411 | line_11->setFont(font5); 412 | line_11->setFrameShape(QFrame::HLine); 413 | line_11->setFrameShadow(QFrame::Sunken); 414 | 415 | verticalLayout_6->addWidget(line_11); 416 | 417 | horizontalLayout = new QHBoxLayout(); 418 | horizontalLayout->setSpacing(16); 419 | horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); 420 | plotSelected = new QToolButton(dataTableViewTab); 421 | plotSelected->setObjectName(QString::fromUtf8("plotSelected")); 422 | plotSelected->setMaximumSize(QSize(16777215, 16777215)); 423 | plotSelected->setFont(font6); 424 | plotSelected->setIcon(icon4); 425 | plotSelected->setIconSize(QSize(48, 48)); 426 | plotSelected->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 427 | 428 | horizontalLayout->addWidget(plotSelected); 429 | 430 | plotSelectedXY = new QToolButton(dataTableViewTab); 431 | plotSelectedXY->setObjectName(QString::fromUtf8("plotSelectedXY")); 432 | plotSelectedXY->setMaximumSize(QSize(16777215, 16777215)); 433 | plotSelectedXY->setFont(font6); 434 | plotSelectedXY->setIcon(icon5); 435 | plotSelectedXY->setIconSize(QSize(48, 48)); 436 | plotSelectedXY->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 437 | 438 | horizontalLayout->addWidget(plotSelectedXY); 439 | 440 | DataDerivator = new QToolButton(dataTableViewTab); 441 | DataDerivator->setObjectName(QString::fromUtf8("DataDerivator")); 442 | DataDerivator->setMaximumSize(QSize(16777215, 16777215)); 443 | DataDerivator->setFont(font6); 444 | DataDerivator->setIcon(icon3); 445 | DataDerivator->setIconSize(QSize(48, 48)); 446 | DataDerivator->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 447 | 448 | horizontalLayout->addWidget(DataDerivator); 449 | 450 | 451 | verticalLayout_6->addLayout(horizontalLayout); 452 | 453 | rightTabs->addTab(dataTableViewTab, QString()); 454 | quickPlotPresets = new QWidget(); 455 | quickPlotPresets->setObjectName(QString::fromUtf8("quickPlotPresets")); 456 | quickPlotPresets->setLayoutDirection(Qt::LeftToRight); 457 | gridLayout_2 = new QGridLayout(quickPlotPresets); 458 | gridLayout_2->setObjectName(QString::fromUtf8("gridLayout_2")); 459 | predefinedPlot1 = new QToolButton(quickPlotPresets); 460 | predefinedPlot1->setObjectName(QString::fromUtf8("predefinedPlot1")); 461 | sizePolicy.setHeightForWidth(predefinedPlot1->sizePolicy().hasHeightForWidth()); 462 | predefinedPlot1->setSizePolicy(sizePolicy); 463 | QFont font8; 464 | font8.setPointSize(11); 465 | predefinedPlot1->setFont(font8); 466 | predefinedPlot1->setLayoutDirection(Qt::LeftToRight); 467 | predefinedPlot1->setAutoFillBackground(false); 468 | QIcon icon8; 469 | icon8.addFile(QString::fromUtf8(":/images/images/line-graph.png"), QSize(), QIcon::Normal, QIcon::Off); 470 | predefinedPlot1->setIcon(icon8); 471 | predefinedPlot1->setIconSize(QSize(64, 64)); 472 | predefinedPlot1->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 473 | predefinedPlot1->setAutoRaise(false); 474 | 475 | gridLayout_2->addWidget(predefinedPlot1, 0, 0, 1, 1); 476 | 477 | predefinedPlot2 = new QToolButton(quickPlotPresets); 478 | predefinedPlot2->setObjectName(QString::fromUtf8("predefinedPlot2")); 479 | sizePolicy.setHeightForWidth(predefinedPlot2->sizePolicy().hasHeightForWidth()); 480 | predefinedPlot2->setSizePolicy(sizePolicy); 481 | predefinedPlot2->setFont(font8); 482 | predefinedPlot2->setLayoutDirection(Qt::LeftToRight); 483 | predefinedPlot2->setAutoFillBackground(false); 484 | predefinedPlot2->setIcon(icon8); 485 | predefinedPlot2->setIconSize(QSize(64, 64)); 486 | predefinedPlot2->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 487 | predefinedPlot2->setAutoRaise(false); 488 | 489 | gridLayout_2->addWidget(predefinedPlot2, 0, 1, 1, 1); 490 | 491 | predefinedPlot9 = new QToolButton(quickPlotPresets); 492 | predefinedPlot9->setObjectName(QString::fromUtf8("predefinedPlot9")); 493 | sizePolicy.setHeightForWidth(predefinedPlot9->sizePolicy().hasHeightForWidth()); 494 | predefinedPlot9->setSizePolicy(sizePolicy); 495 | predefinedPlot9->setFont(font8); 496 | predefinedPlot9->setLayoutDirection(Qt::LeftToRight); 497 | predefinedPlot9->setAutoFillBackground(false); 498 | predefinedPlot9->setIcon(icon8); 499 | predefinedPlot9->setIconSize(QSize(64, 64)); 500 | predefinedPlot9->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 501 | predefinedPlot9->setAutoRaise(false); 502 | 503 | gridLayout_2->addWidget(predefinedPlot9, 1, 0, 1, 1); 504 | 505 | predefinedPlot5 = new QToolButton(quickPlotPresets); 506 | predefinedPlot5->setObjectName(QString::fromUtf8("predefinedPlot5")); 507 | sizePolicy.setHeightForWidth(predefinedPlot5->sizePolicy().hasHeightForWidth()); 508 | predefinedPlot5->setSizePolicy(sizePolicy); 509 | predefinedPlot5->setFont(font8); 510 | predefinedPlot5->setLayoutDirection(Qt::LeftToRight); 511 | predefinedPlot5->setAutoFillBackground(false); 512 | predefinedPlot5->setIcon(icon8); 513 | predefinedPlot5->setIconSize(QSize(64, 64)); 514 | predefinedPlot5->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 515 | predefinedPlot5->setAutoRaise(false); 516 | 517 | gridLayout_2->addWidget(predefinedPlot5, 4, 0, 1, 1); 518 | 519 | predefinedPlot7 = new QToolButton(quickPlotPresets); 520 | predefinedPlot7->setObjectName(QString::fromUtf8("predefinedPlot7")); 521 | sizePolicy.setHeightForWidth(predefinedPlot7->sizePolicy().hasHeightForWidth()); 522 | predefinedPlot7->setSizePolicy(sizePolicy); 523 | predefinedPlot7->setFont(font8); 524 | predefinedPlot7->setLayoutDirection(Qt::LeftToRight); 525 | predefinedPlot7->setAutoFillBackground(false); 526 | predefinedPlot7->setIcon(icon8); 527 | predefinedPlot7->setIconSize(QSize(64, 64)); 528 | predefinedPlot7->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 529 | predefinedPlot7->setAutoRaise(false); 530 | 531 | gridLayout_2->addWidget(predefinedPlot7, 4, 1, 1, 1); 532 | 533 | predefinedPlot6 = new QToolButton(quickPlotPresets); 534 | predefinedPlot6->setObjectName(QString::fromUtf8("predefinedPlot6")); 535 | sizePolicy.setHeightForWidth(predefinedPlot6->sizePolicy().hasHeightForWidth()); 536 | predefinedPlot6->setSizePolicy(sizePolicy); 537 | predefinedPlot6->setFont(font8); 538 | predefinedPlot6->setLayoutDirection(Qt::LeftToRight); 539 | predefinedPlot6->setAutoFillBackground(false); 540 | predefinedPlot6->setIcon(icon8); 541 | predefinedPlot6->setIconSize(QSize(64, 64)); 542 | predefinedPlot6->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 543 | predefinedPlot6->setAutoRaise(false); 544 | 545 | gridLayout_2->addWidget(predefinedPlot6, 6, 0, 1, 1); 546 | 547 | predefinedPlot3 = new QToolButton(quickPlotPresets); 548 | predefinedPlot3->setObjectName(QString::fromUtf8("predefinedPlot3")); 549 | sizePolicy.setHeightForWidth(predefinedPlot3->sizePolicy().hasHeightForWidth()); 550 | predefinedPlot3->setSizePolicy(sizePolicy); 551 | predefinedPlot3->setFont(font8); 552 | predefinedPlot3->setLayoutDirection(Qt::LeftToRight); 553 | predefinedPlot3->setAutoFillBackground(false); 554 | predefinedPlot3->setIcon(icon8); 555 | predefinedPlot3->setIconSize(QSize(64, 64)); 556 | predefinedPlot3->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 557 | predefinedPlot3->setAutoRaise(false); 558 | 559 | gridLayout_2->addWidget(predefinedPlot3, 1, 1, 1, 1); 560 | 561 | predefinedPlot4 = new QToolButton(quickPlotPresets); 562 | predefinedPlot4->setObjectName(QString::fromUtf8("predefinedPlot4")); 563 | sizePolicy.setHeightForWidth(predefinedPlot4->sizePolicy().hasHeightForWidth()); 564 | predefinedPlot4->setSizePolicy(sizePolicy); 565 | predefinedPlot4->setFont(font8); 566 | predefinedPlot4->setLayoutDirection(Qt::LeftToRight); 567 | predefinedPlot4->setAutoFillBackground(false); 568 | predefinedPlot4->setIcon(icon8); 569 | predefinedPlot4->setIconSize(QSize(64, 64)); 570 | predefinedPlot4->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 571 | predefinedPlot4->setAutoRaise(false); 572 | 573 | gridLayout_2->addWidget(predefinedPlot4, 2, 0, 1, 1); 574 | 575 | predefinedPlot8 = new QToolButton(quickPlotPresets); 576 | predefinedPlot8->setObjectName(QString::fromUtf8("predefinedPlot8")); 577 | sizePolicy.setHeightForWidth(predefinedPlot8->sizePolicy().hasHeightForWidth()); 578 | predefinedPlot8->setSizePolicy(sizePolicy); 579 | predefinedPlot8->setFont(font8); 580 | predefinedPlot8->setLayoutDirection(Qt::LeftToRight); 581 | predefinedPlot8->setAutoFillBackground(false); 582 | predefinedPlot8->setIcon(icon8); 583 | predefinedPlot8->setIconSize(QSize(64, 64)); 584 | predefinedPlot8->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 585 | predefinedPlot8->setAutoRaise(false); 586 | 587 | gridLayout_2->addWidget(predefinedPlot8, 2, 1, 1, 1); 588 | 589 | predefinedPlot10 = new QToolButton(quickPlotPresets); 590 | predefinedPlot10->setObjectName(QString::fromUtf8("predefinedPlot10")); 591 | sizePolicy.setHeightForWidth(predefinedPlot10->sizePolicy().hasHeightForWidth()); 592 | predefinedPlot10->setSizePolicy(sizePolicy); 593 | predefinedPlot10->setFont(font8); 594 | predefinedPlot10->setLayoutDirection(Qt::LeftToRight); 595 | predefinedPlot10->setAutoFillBackground(false); 596 | predefinedPlot10->setIcon(icon8); 597 | predefinedPlot10->setIconSize(QSize(64, 64)); 598 | predefinedPlot10->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 599 | predefinedPlot10->setAutoRaise(false); 600 | 601 | gridLayout_2->addWidget(predefinedPlot10, 6, 1, 1, 1); 602 | 603 | rightTabs->addTab(quickPlotPresets, QString()); 604 | 605 | mainHorizontalLayout->addWidget(rightTabs); 606 | 607 | 608 | gridLayout->addLayout(mainHorizontalLayout, 0, 0, 1, 1); 609 | 610 | SimpleCsvLogAnalyzer->setCentralWidget(centralwidget); 611 | statusbar = new QStatusBar(SimpleCsvLogAnalyzer); 612 | statusbar->setObjectName(QString::fromUtf8("statusbar")); 613 | statusbar->setFont(font6); 614 | SimpleCsvLogAnalyzer->setStatusBar(statusbar); 615 | toolBar = new QToolBar(SimpleCsvLogAnalyzer); 616 | toolBar->setObjectName(QString::fromUtf8("toolBar")); 617 | toolBar->setFont(font3); 618 | toolBar->setIconSize(QSize(50, 50)); 619 | toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); 620 | SimpleCsvLogAnalyzer->addToolBar(Qt::TopToolBarArea, toolBar); 621 | 622 | toolBar->addAction(actionOpen); 623 | toolBar->addAction(actionZoom_In); 624 | toolBar->addAction(actionZoom_Out); 625 | toolBar->addAction(actionZoom_Reset); 626 | toolBar->addAction(actionSave_Plot_Image); 627 | toolBar->addAction(actionData_Derivator); 628 | toolBar->addAction(actionPlot_SelectedData); 629 | toolBar->addAction(actionplot_SelectedDataVsSelectedData); 630 | 631 | retranslateUi(SimpleCsvLogAnalyzer); 632 | 633 | rightTabs->setCurrentIndex(0); 634 | 635 | 636 | QMetaObject::connectSlotsByName(SimpleCsvLogAnalyzer); 637 | } // setupUi 638 | 639 | void retranslateUi(QMainWindow *SimpleCsvLogAnalyzer) 640 | { 641 | SimpleCsvLogAnalyzer->setWindowTitle(QCoreApplication::translate("SimpleCsvLogAnalyzer", "SimpleCsvLogAnalyzer", nullptr)); 642 | actionOpen->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Open File", nullptr)); 643 | actionExit->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Exit", nullptr)); 644 | #if QT_CONFIG(shortcut) 645 | actionExit->setShortcut(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Ctrl+Q", nullptr)); 646 | #endif // QT_CONFIG(shortcut) 647 | actionZoom_Reset->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Zoom Reset", nullptr)); 648 | #if QT_CONFIG(shortcut) 649 | actionZoom_Reset->setShortcut(QCoreApplication::translate("SimpleCsvLogAnalyzer", "0", nullptr)); 650 | #endif // QT_CONFIG(shortcut) 651 | actionSave_Plot_Image->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Save Plot", nullptr)); 652 | #if QT_CONFIG(shortcut) 653 | actionSave_Plot_Image->setShortcut(QCoreApplication::translate("SimpleCsvLogAnalyzer", "S", nullptr)); 654 | #endif // QT_CONFIG(shortcut) 655 | actionData_Derivator->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Data Derivator", nullptr)); 656 | actionPlot_SelectedData->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Plot Y", nullptr)); 657 | actionplot_SelectedDataVsSelectedData->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "plot Y-X", nullptr)); 658 | actionZoom_In->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Zoom In", nullptr)); 659 | actionZoom_Out->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Zoom Out", nullptr)); 660 | minValueY->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Min Y: nan", nullptr)); 661 | maxValueY->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Max Y: nan", nullptr)); 662 | averageValueY->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Average Y: nan", nullptr)); 663 | spanValueY->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Span Y: nan", nullptr)); 664 | totalDataLength->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Data Length: nan", nullptr)); 665 | minValueX->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Min X: nan", nullptr)); 666 | maxValueX->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Max X: nan", nullptr)); 667 | averageValueX->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Average X: nan", nullptr)); 668 | spanValueX->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Span X: nan", nullptr)); 669 | rightTabs->setTabText(rightTabs->indexOf(plotTab), QCoreApplication::translate("SimpleCsvLogAnalyzer", "Plot", nullptr)); 670 | label_2->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Y Axis Data List", nullptr)); 671 | label_3->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "X Axis Data List", nullptr)); 672 | plotSelected->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Plot Selected Data vs Index", nullptr)); 673 | plotSelectedXY->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Plot Selected Y-X Data", nullptr)); 674 | DataDerivator->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Data Derivator", nullptr)); 675 | rightTabs->setTabText(rightTabs->indexOf(dataTableViewTab), QCoreApplication::translate("SimpleCsvLogAnalyzer", "Data Labels", nullptr)); 676 | predefinedPlot1->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Speed (OBD) vs Time", nullptr)); 677 | predefinedPlot2->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Speed (GPS) vs Time", nullptr)); 678 | predefinedPlot9->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "RPM vs Time", nullptr)); 679 | predefinedPlot5->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "LTFT1 vs Time", nullptr)); 680 | predefinedPlot7->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "STFT1 vs Time", nullptr)); 681 | predefinedPlot6->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "LTFT1+STFT1 vs RPM", nullptr)); 682 | predefinedPlot3->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Altitude vs Time", nullptr)); 683 | predefinedPlot4->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Avg. Consumption vs Time", nullptr)); 684 | predefinedPlot8->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "Speed (OBD) / RPM vs Time", nullptr)); 685 | predefinedPlot10->setText(QCoreApplication::translate("SimpleCsvLogAnalyzer", "LTFT1+STFT1 vs Time", nullptr)); 686 | rightTabs->setTabText(rightTabs->indexOf(quickPlotPresets), QCoreApplication::translate("SimpleCsvLogAnalyzer", "Quick Plots", nullptr)); 687 | toolBar->setWindowTitle(QCoreApplication::translate("SimpleCsvLogAnalyzer", "toolBar", nullptr)); 688 | } // retranslateUi 689 | 690 | }; 691 | 692 | namespace Ui { 693 | class SimpleCsvLogAnalyzer: public Ui_SimpleCsvLogAnalyzer {}; 694 | } // namespace Ui 695 | 696 | QT_END_NAMESPACE 697 | 698 | #endif // UI_SIMPLECSVLOGANALYZER_H 699 | -------------------------------------------------------------------------------- /src/SimpleCsvLogAnalyzer.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | SimpleCsvLogAnalyzer 4 | 5 | 6 | 7 | 0 8 | 0 9 | 640 10 | 721 11 | 12 | 13 | 14 | 15 | Arial 16 | 17 | 18 | 19 | SimpleCsvLogAnalyzer 20 | 21 | 22 | 23 | 24 | 25 | 26 | 0 27 | 28 | 29 | 0 30 | 31 | 32 | 0 33 | 34 | 35 | 36 | 37 | 38 | Arial 39 | 10 40 | 41 | 42 | 43 | Min Y: nan 44 | 45 | 46 | Qt::AlignCenter 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Arial 55 | 7 56 | 57 | 58 | 59 | Qt::Vertical 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Arial 68 | 10 69 | 70 | 71 | 72 | Max Y: nan 73 | 74 | 75 | Qt::AlignCenter 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | Arial 84 | 7 85 | 86 | 87 | 88 | Qt::Vertical 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | Arial 97 | 10 98 | 99 | 100 | 101 | Average Y: nan 102 | 103 | 104 | Qt::AlignCenter 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | Arial 113 | 7 114 | 115 | 116 | 117 | Qt::Vertical 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | Arial 126 | 10 127 | 128 | 129 | 130 | Span Y: nan 131 | 132 | 133 | Qt::AlignCenter 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | Arial 146 | 8 147 | 148 | 149 | 150 | Data Length: nan 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 5 160 | 161 | 162 | 0 163 | 164 | 165 | 0 166 | 167 | 168 | 0 169 | 170 | 171 | 172 | 173 | 174 | Arial 175 | 10 176 | 177 | 178 | 179 | Min X: nan 180 | 181 | 182 | Qt::AlignCenter 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | Arial 191 | 7 192 | 193 | 194 | 195 | Qt::Vertical 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | Arial 204 | 10 205 | 206 | 207 | 208 | Max X: nan 209 | 210 | 211 | Qt::AlignCenter 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | Arial 220 | 7 221 | 222 | 223 | 224 | Qt::Vertical 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | Arial 233 | 10 234 | 235 | 236 | 237 | Average X: nan 238 | 239 | 240 | Qt::AlignCenter 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | Arial 249 | 7 250 | 251 | 252 | 253 | Qt::Vertical 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | Arial 262 | 10 263 | 264 | 265 | 266 | Span X: nan 267 | 268 | 269 | Qt::AlignCenter 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | Arial 282 | 10 283 | 75 284 | true 285 | 286 | 287 | 288 | 0 289 | 290 | 291 | 292 | Plot 293 | 294 | 295 | 296 | 297 | 298 | 299 | 0 300 | 0 301 | 302 | 303 | 304 | 305 | Arial 306 | 7 307 | 75 308 | true 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | Data Labels 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 0 330 | 0 331 | 332 | 333 | 334 | 335 | 16777215 336 | 16777215 337 | 338 | 339 | 340 | 341 | Arial 342 | 9 343 | 75 344 | true 345 | 346 | 347 | 348 | Y Axis Data List 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 0 357 | 0 358 | 359 | 360 | 361 | 362 | Arial 363 | 11 364 | 75 365 | true 366 | 367 | 368 | 369 | Qt::CustomContextMenu 370 | 371 | 372 | QAbstractItemView::NoEditTriggers 373 | 374 | 375 | false 376 | 377 | 378 | false 379 | 380 | 381 | false 382 | 383 | 384 | QAbstractItemView::NoDragDrop 385 | 386 | 387 | Qt::IgnoreAction 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 0 400 | 0 401 | 402 | 403 | 404 | 405 | 16777215 406 | 16777215 407 | 408 | 409 | 410 | 411 | Arial 412 | 9 413 | 75 414 | true 415 | 416 | 417 | 418 | X Axis Data List 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 0 427 | 0 428 | 429 | 430 | 431 | 432 | Arial 433 | 11 434 | 75 435 | true 436 | 437 | 438 | 439 | QAbstractItemView::DoubleClicked 440 | 441 | 442 | false 443 | 444 | 445 | QAbstractItemView::NoDragDrop 446 | 447 | 448 | Qt::IgnoreAction 449 | 450 | 451 | QAbstractItemView::SingleSelection 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | Arial 464 | 7 465 | 75 466 | true 467 | 468 | 469 | 470 | Qt::Horizontal 471 | 472 | 473 | 474 | 475 | 476 | 477 | 16 478 | 479 | 480 | 481 | 482 | 483 | 16777215 484 | 16777215 485 | 486 | 487 | 488 | 489 | Arial 490 | 9 491 | 75 492 | true 493 | 494 | 495 | 496 | Plot Selected Data vs Index 497 | 498 | 499 | 500 | :/images/images/ploty.png:/images/images/ploty.png 501 | 502 | 503 | 504 | 48 505 | 48 506 | 507 | 508 | 509 | Qt::ToolButtonTextUnderIcon 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 16777215 518 | 16777215 519 | 520 | 521 | 522 | 523 | Arial 524 | 9 525 | 75 526 | true 527 | 528 | 529 | 530 | Plot Selected Y-X Data 531 | 532 | 533 | 534 | :/images/images/plotxy.png:/images/images/plotxy.png 535 | 536 | 537 | 538 | 48 539 | 48 540 | 541 | 542 | 543 | Qt::ToolButtonTextUnderIcon 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 16777215 552 | 16777215 553 | 554 | 555 | 556 | 557 | Arial 558 | 9 559 | 75 560 | true 561 | 562 | 563 | 564 | Data Derivator 565 | 566 | 567 | 568 | :/images/images/function.png:/images/images/function.png 569 | 570 | 571 | 572 | 48 573 | 48 574 | 575 | 576 | 577 | Qt::ToolButtonTextUnderIcon 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | Qt::LeftToRight 588 | 589 | 590 | Quick Plots 591 | 592 | 593 | 594 | 595 | 596 | 597 | 0 598 | 0 599 | 600 | 601 | 602 | 603 | 11 604 | 605 | 606 | 607 | Qt::LeftToRight 608 | 609 | 610 | false 611 | 612 | 613 | Speed (OBD) vs Time 614 | 615 | 616 | 617 | :/images/images/line-graph.png:/images/images/line-graph.png 618 | 619 | 620 | 621 | 64 622 | 64 623 | 624 | 625 | 626 | Qt::ToolButtonTextUnderIcon 627 | 628 | 629 | false 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 0 638 | 0 639 | 640 | 641 | 642 | 643 | 11 644 | 645 | 646 | 647 | Qt::LeftToRight 648 | 649 | 650 | false 651 | 652 | 653 | Speed (GPS) vs Time 654 | 655 | 656 | 657 | :/images/images/line-graph.png:/images/images/line-graph.png 658 | 659 | 660 | 661 | 64 662 | 64 663 | 664 | 665 | 666 | Qt::ToolButtonTextUnderIcon 667 | 668 | 669 | false 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 0 678 | 0 679 | 680 | 681 | 682 | 683 | 11 684 | 685 | 686 | 687 | Qt::LeftToRight 688 | 689 | 690 | false 691 | 692 | 693 | RPM vs Time 694 | 695 | 696 | 697 | :/images/images/line-graph.png:/images/images/line-graph.png 698 | 699 | 700 | 701 | 64 702 | 64 703 | 704 | 705 | 706 | Qt::ToolButtonTextUnderIcon 707 | 708 | 709 | false 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 0 718 | 0 719 | 720 | 721 | 722 | 723 | 11 724 | 725 | 726 | 727 | Qt::LeftToRight 728 | 729 | 730 | false 731 | 732 | 733 | LTFT1 vs Time 734 | 735 | 736 | 737 | :/images/images/line-graph.png:/images/images/line-graph.png 738 | 739 | 740 | 741 | 64 742 | 64 743 | 744 | 745 | 746 | Qt::ToolButtonTextUnderIcon 747 | 748 | 749 | false 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 0 758 | 0 759 | 760 | 761 | 762 | 763 | 11 764 | 765 | 766 | 767 | Qt::LeftToRight 768 | 769 | 770 | false 771 | 772 | 773 | STFT1 vs Time 774 | 775 | 776 | 777 | :/images/images/line-graph.png:/images/images/line-graph.png 778 | 779 | 780 | 781 | 64 782 | 64 783 | 784 | 785 | 786 | Qt::ToolButtonTextUnderIcon 787 | 788 | 789 | false 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 0 798 | 0 799 | 800 | 801 | 802 | 803 | 11 804 | 805 | 806 | 807 | Qt::LeftToRight 808 | 809 | 810 | false 811 | 812 | 813 | LTFT1+STFT1 vs RPM 814 | 815 | 816 | 817 | :/images/images/line-graph.png:/images/images/line-graph.png 818 | 819 | 820 | 821 | 64 822 | 64 823 | 824 | 825 | 826 | Qt::ToolButtonTextUnderIcon 827 | 828 | 829 | false 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 0 838 | 0 839 | 840 | 841 | 842 | 843 | 11 844 | 845 | 846 | 847 | Qt::LeftToRight 848 | 849 | 850 | false 851 | 852 | 853 | Altitude vs Time 854 | 855 | 856 | 857 | :/images/images/line-graph.png:/images/images/line-graph.png 858 | 859 | 860 | 861 | 64 862 | 64 863 | 864 | 865 | 866 | Qt::ToolButtonTextUnderIcon 867 | 868 | 869 | false 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 0 878 | 0 879 | 880 | 881 | 882 | 883 | 11 884 | 885 | 886 | 887 | Qt::LeftToRight 888 | 889 | 890 | false 891 | 892 | 893 | Avg. Consumption vs Time 894 | 895 | 896 | 897 | :/images/images/line-graph.png:/images/images/line-graph.png 898 | 899 | 900 | 901 | 64 902 | 64 903 | 904 | 905 | 906 | Qt::ToolButtonTextUnderIcon 907 | 908 | 909 | false 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 0 918 | 0 919 | 920 | 921 | 922 | 923 | 11 924 | 925 | 926 | 927 | Qt::LeftToRight 928 | 929 | 930 | false 931 | 932 | 933 | Speed (OBD) / RPM vs Time 934 | 935 | 936 | 937 | :/images/images/line-graph.png:/images/images/line-graph.png 938 | 939 | 940 | 941 | 64 942 | 64 943 | 944 | 945 | 946 | Qt::ToolButtonTextUnderIcon 947 | 948 | 949 | false 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 0 958 | 0 959 | 960 | 961 | 962 | 963 | 11 964 | 965 | 966 | 967 | Qt::LeftToRight 968 | 969 | 970 | false 971 | 972 | 973 | LTFT1+STFT1 vs Time 974 | 975 | 976 | 977 | :/images/images/line-graph.png:/images/images/line-graph.png 978 | 979 | 980 | 981 | 64 982 | 64 983 | 984 | 985 | 986 | Qt::ToolButtonTextUnderIcon 987 | 988 | 989 | false 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | Arial 1005 | 9 1006 | 75 1007 | true 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | Arial 1015 | 7 1016 | 1017 | 1018 | 1019 | toolBar 1020 | 1021 | 1022 | 1023 | 50 1024 | 50 1025 | 1026 | 1027 | 1028 | Qt::ToolButtonTextUnderIcon 1029 | 1030 | 1031 | TopToolBarArea 1032 | 1033 | 1034 | false 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | :/images/images/folder.png:/images/images/folder.png 1049 | 1050 | 1051 | Open File 1052 | 1053 | 1054 | 1055 | Arial 1056 | 10 1057 | 75 1058 | true 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | Exit 1065 | 1066 | 1067 | Ctrl+Q 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | :/images/images/zoomreset.png:/images/images/zoomreset.png 1074 | 1075 | 1076 | Zoom Reset 1077 | 1078 | 1079 | 1080 | Arial 1081 | 10 1082 | 75 1083 | true 1084 | 1085 | 1086 | 1087 | 0 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | :/images/images/save.png:/images/images/save.png 1094 | 1095 | 1096 | Save Plot 1097 | 1098 | 1099 | 1100 | Arial 1101 | 10 1102 | 75 1103 | true 1104 | 1105 | 1106 | 1107 | S 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | :/images/images/function.png:/images/images/function.png 1114 | 1115 | 1116 | Data Derivator 1117 | 1118 | 1119 | 1120 | Arial 1121 | 10 1122 | 75 1123 | true 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | :/images/images/ploty.png:/images/images/ploty.png 1131 | 1132 | 1133 | Plot Y 1134 | 1135 | 1136 | 1137 | Arial 1138 | 10 1139 | 75 1140 | true 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | :/images/images/plotxy.png:/images/images/plotxy.png 1148 | 1149 | 1150 | plot Y-X 1151 | 1152 | 1153 | 1154 | Arial 1155 | 10 1156 | 75 1157 | true 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | :/images/images/zoomin.png:/images/images/zoomin.png 1165 | 1166 | 1167 | Zoom In 1168 | 1169 | 1170 | 1171 | Arial 1172 | 10 1173 | 75 1174 | true 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | :/images/images/zoomout.png:/images/images/zoomout.png 1182 | 1183 | 1184 | Zoom Out 1185 | 1186 | 1187 | 1188 | Arial 1189 | 10 1190 | 75 1191 | true 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | QCustomPlot 1199 | QWidget 1200 |
src/QCustomPlot/qcustomplot.h
1201 | 1 1202 |
1203 |
1204 | 1205 | 1206 | 1207 | 1208 |
1209 | -------------------------------------------------------------------------------- /src/SimpleCsvLogAnalyzer.cpp: -------------------------------------------------------------------------------- 1 | #include "SimpleCsvLogAnalyzer.h" 2 | #include "ui_SimpleCsvLogAnalyzer.h" 3 | 4 | #include 5 | //handle log files that have labels between data lines 6 | SimpleCsvLogAnalyzer::SimpleCsvLogAnalyzer(QWidget *parent) 7 | : QMainWindow(parent) 8 | , ui(new Ui::SimpleCsvLogAnalyzer) 9 | { 10 | ui->setupUi(this); 11 | qApp->processEvents(); 12 | getAndroidPermission("android.permission.WRITE_EXTERNAL_STORAGE"); 13 | getAndroidPermission("android.permission.READ_EXTERNAL_STORAGE"); 14 | // setup some shortcuts 15 | moveRight = new QShortcut(this); 16 | moveRight->setKey(Qt::Key_Right); 17 | connect(moveRight,SIGNAL(activated()),this,SLOT(moveRigthPressed())); 18 | 19 | QPixmap pixmap(":/images/images/timer-opaque.png"); 20 | loadingSplash = new QSplashScreen(pixmap,Qt::SplashScreen); 21 | 22 | // init dataTableView custom context menu 23 | // tableViewContextMenu = new QMenu(); 24 | // tableViewContextMenu->addAction("Plot",this,SLOT(plotThis_forTable())); 25 | // tableViewContextMenu->addAction("Statistics",this,SLOT(statisticsForThis_forTable())); 26 | // tableViewContextMenu->addAction("Hide Selected Columns",this,SLOT(hideTableColumns_forTable())); 27 | // tableViewContextMenu->addAction("Show Selected Columns Only",this,SLOT(showTableColumns_forTable())); 28 | // tableViewContextMenu->addAction("Show All Columns",this,SLOT(restoreTableColumns_forTable())); 29 | 30 | // init dataTableView custom context menu 31 | labelListContextMenu = new QMenu(); 32 | labelListContextMenu->addAction("Plot vs Record Number",this,SLOT(plotThis_forList())); 33 | labelListContextMenu->addAction("Plot vs Another Data Label",this,SLOT(plotThisVsAnotherDataLabel_forList())); 34 | labelListContextMenu->addAction("Statistics",this,SLOT(statisticsForThis_forList())); 35 | 36 | //initDataTable(); 37 | 38 | initPlot(); 39 | ui->totalDataLength->hide(); 40 | 41 | #ifdef Q_OS_ANDROID 42 | this->showMaximized(); 43 | #endif 44 | qApp->processEvents(); 45 | //ui->plot1->setMaximumSize(ui->plot1->size()); 46 | 47 | } 48 | 49 | SimpleCsvLogAnalyzer::~SimpleCsvLogAnalyzer() 50 | { 51 | delete ui; 52 | } 53 | 54 | void SimpleCsvLogAnalyzer::on_actionExit_triggered() 55 | { 56 | cleanUpAndExit(); 57 | exit(0); 58 | } 59 | 60 | void SimpleCsvLogAnalyzer::cleanUpAndExit() 61 | { 62 | // TDB 63 | } 64 | 65 | void SimpleCsvLogAnalyzer::initPlot(){ 66 | 67 | // Clear graph etc. 68 | //ui->plot1->setOpenGl(true); 69 | disconnect(ui->plot1, &QCustomPlot::mouseMove, this, &SimpleCsvLogAnalyzer::tracerEvent); 70 | ui->plot1->clearGraphs(); 71 | QFont f = ui->plot1->font(); 72 | f.setPointSizeF(8); 73 | ui->plot1->xAxis->setTickLabelFont(f); 74 | ui->plot1->yAxis->setTickLabelFont(f); 75 | ui->plot1->xAxis->setLabelFont(f); 76 | ui->plot1->yAxis->setLabelFont(f); 77 | // 78 | 79 | // Create value and cursor plot 80 | valuePlot = ui->plot1->addGraph(); 81 | //cursorPlot = ui->plot1->addGraph(); 82 | 83 | 84 | 85 | // Allow draggingplot in X axis only (horizontal) 86 | ui->plot1->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); 87 | ui->plot1->axisRect()->setRangeDrag(Qt::Horizontal); 88 | ui->plot1->axisRect()->setRangeZoom(Qt::Horizontal); 89 | 90 | // setup tracer 91 | verticalLine = new QCPCurve(ui->plot1->xAxis, ui->plot1->yAxis); 92 | QVector x(2) , y(2); 93 | x[0] = 0; 94 | y[0] = 0; 95 | x[1] = 0; 96 | y[1] = 0; 97 | 98 | verticalLine->setName("Vertical"); 99 | verticalLine->setData(x, y); 100 | tracer = new QCPItemTracer(ui->plot1); 101 | 102 | tracer->setStyle(QCPItemTracer::tsCrosshair); 103 | tracer->setPen(QPen(Qt::darkGray)); 104 | 105 | #ifdef Q_OS_ANDROID 106 | connect(ui->plot1, &QCustomPlot::mouseRelease, this, &SimpleCsvLogAnalyzer::tracerEvent); 107 | #else 108 | connect(ui->plot1, &QCustomPlot::mouseMove, this, &SimpleCsvLogAnalyzer::tracerEvent); 109 | #endif 110 | } 111 | 112 | //void SimpleCsvLogAnalyzer::initDataTable() 113 | //{ 114 | // // Auto adjust horizontal header labels 115 | // ui->dataTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); 116 | //} 117 | 118 | void SimpleCsvLogAnalyzer::clearPlotNDisableTracer(){ 119 | xVals.clear(); 120 | yVals.clear(); 121 | valuePlot->setData(xVals,yVals); 122 | tracer->setGraph(nullptr); 123 | ui->plot1->replot(); 124 | } 125 | 126 | void SimpleCsvLogAnalyzer::setupTracer() 127 | { 128 | tracer->setGraph(valuePlot); 129 | } 130 | 131 | void SimpleCsvLogAnalyzer::zoomReset(){ 132 | // Rescales X axis using default method (min and max of x values) 133 | // rescales Y axis using min and max of Y axis values, with a margin of 1/10th of the span 134 | // to provide better visibilty for peaks and valleys in plot curve 135 | valuePlot->rescaleKeyAxis(); 136 | double span = stats.y.span; 137 | if(span==0){ 138 | span = 10; 139 | } 140 | ui->plot1->yAxis->setRange(stats.y.min-0.1*span,stats.y.max+0.1*span); 141 | ui->plot1->replot(); 142 | qApp->processEvents(); 143 | 144 | #ifdef Q_OS_ANDROID 145 | this->showMaximized(); 146 | #endif 147 | // this->showMaximized(); 148 | } 149 | 150 | QList SimpleCsvLogAnalyzer::calculateSlopeOfCurve(double keyValue){ 151 | QList ret; 152 | ret.append(NAN); 153 | ret.append(NAN); 154 | int valueIndex = xVals.indexOf(keyValue); 155 | if( ((valueIndex+1) < yVals.length()) && ((valueIndex)>0) ){ 156 | ret[0] = (yVals[valueIndex] - yVals[valueIndex-1])/(xVals[valueIndex]-xVals[valueIndex-1]); // left slope 157 | ret[1] = (yVals[valueIndex+1] - yVals[valueIndex])/(xVals[valueIndex+1]-xVals[valueIndex]); // right slope 158 | } 159 | return ret; 160 | } 161 | 162 | statistics SimpleCsvLogAnalyzer::calculateStatisticalData(QVector x, QVector y, bool showReportMessage){ 163 | statistics ret; 164 | ret.x.min = std::numeric_limits::max(); 165 | ret.x.max = std::numeric_limits::min(); 166 | ret.x.span = 0; 167 | ret.x.average = 0; 168 | int averageArrayLen = x.length(); 169 | if(x.length()>0){ 170 | double accu = 0; 171 | double tmp; 172 | for(int i=0; iret.x.max){ 183 | ret.x.max = tmp; 184 | } 185 | } 186 | ret.x.average = accu/averageArrayLen; 187 | ret.x.span = ret.x.max - ret.x.min; 188 | if((ret.x.min == std::numeric_limits::max()) | (ret.x.max == std::numeric_limits::min())){ 189 | ret.x.min = NAN; 190 | ret.x.max = NAN; 191 | ret.x.span = NAN; 192 | ret.x.average = NAN; 193 | } 194 | } else { 195 | qDebug() << "No data in array!"; 196 | ret.x.min = NAN; 197 | ret.x.max = NAN; 198 | ret.x.span = NAN; 199 | ret.x.average = NAN; 200 | } 201 | ret.x.length = x.length(); 202 | 203 | 204 | ret.y.min = std::numeric_limits::max(); 205 | ret.y.max = std::numeric_limits::min(); 206 | ret.y.span = 0; 207 | ret.y.average = 0; 208 | averageArrayLen = y.length(); 209 | if(y.length()>0){ 210 | double accu = 0; 211 | double tmp; 212 | for(int i=0; iret.y.max){ 223 | ret.y.max = tmp; 224 | } 225 | } 226 | ret.y.average = accu/averageArrayLen; 227 | ret.y.span = ret.y.max - ret.y.min; 228 | if((ret.y.min == std::numeric_limits::max()) | (ret.y.max == std::numeric_limits::min())){ 229 | ret.y.min = NAN; 230 | ret.y.max = NAN; 231 | ret.y.span = NAN; 232 | ret.y.average = NAN; 233 | } 234 | } else { 235 | qDebug() << "No data in array!"; 236 | ret.y.min = NAN; 237 | ret.y.max = NAN; 238 | ret.y.span = NAN; 239 | ret.y.average = NAN; 240 | } 241 | ret.y.length = y.length(); 242 | if(showReportMessage){ 243 | QString s = QString("Statistics for selected data\n" 244 | "Min:%1\n" 245 | "Max:%2\n" 246 | "Average:%3\n" 247 | "Span:%4\n" 248 | "Length:%5") 249 | .arg(ret.y.min) 250 | .arg(ret.y.max) 251 | .arg(ret.y.average) 252 | .arg(ret.y.span) 253 | .arg(ret.y.length); 254 | QMessageBox msg; 255 | msg.setText(s); 256 | msg.exec(); 257 | } 258 | return ret; 259 | } 260 | 261 | void SimpleCsvLogAnalyzer::populateStatisticsLabels(){ 262 | // X Axis 263 | ui->minValueX->setText("Min X: " + QString::number(stats.x.min,'f',2)); 264 | ui->maxValueX->setText("Max X: " + QString::number(stats.x.max,'f',2)); 265 | ui->spanValueX->setText("Span X: " + QString::number(stats.x.span,'f',2)); 266 | ui->averageValueX->setText("Average X: " + QString::number(stats.x.average,'f',2)); 267 | // Y Axis 268 | ui->minValueY->setText("Min Y: " + QString::number(stats.y.min,'f',2)); 269 | ui->maxValueY->setText("Max Y: " + QString::number(stats.y.max,'f',2)); 270 | ui->spanValueY->setText("Span Y: " + QString::number(stats.y.span,'f',2)); 271 | ui->averageValueY->setText("Average Y: " + QString::number(stats.y.average,'f',2)); 272 | //Data length 273 | ui->totalDataLength->setText(QString("Data Length: %1").arg(stats.y.length)); 274 | 275 | } 276 | 277 | void SimpleCsvLogAnalyzer::clearStatisticsLabels() 278 | { 279 | // X Axis 280 | ui->minValueX->setText("Min X: nan"); 281 | ui->maxValueX->setText("Max X: nan"); 282 | ui->spanValueX->setText("Span X: nan"); 283 | ui->averageValueX->setText("Average X: nan"); 284 | // Y Axis 285 | ui->minValueY->setText("Min Y: nan"); 286 | ui->maxValueY->setText("Max Y: nan"); 287 | ui->spanValueY->setText("Span Y: nan"); 288 | ui->averageValueY->setText("Average Y: nan"); 289 | //Data length 290 | ui->totalDataLength->setText(QString("Data Length: N/A")); 291 | } 292 | 293 | void SimpleCsvLogAnalyzer::startBusy() 294 | { 295 | loadingSplash->move(this->x()+this->width()/2,this->y()+this->height()/2); 296 | loadingSplash->show(); 297 | qApp->processEvents(); 298 | } 299 | 300 | void SimpleCsvLogAnalyzer::stopBusy() 301 | { 302 | qApp->processEvents(); 303 | loadingSplash->close(); 304 | } 305 | 306 | QString SimpleCsvLogAnalyzer::createDerivedDataLabel(QStringList formula) 307 | { 308 | QString derivedDataLabel; 309 | QVector dd,tmp; 310 | if(formula.isEmpty()){ 311 | ui->statusbar->showMessage("Empty formula for derived data!"); 312 | showMessage("Empty formula for derived data!"); 313 | return derivedDataLabel; 314 | } 315 | qDebug() << "Formula:" << formula; 316 | if(mathOperatorsList.contains(formula[0])){ 317 | ui->statusbar->showMessage("Illegal formula for derived data!"); 318 | showMessage("Illegal formula for derived data!"); 319 | return derivedDataLabel; 320 | } 321 | QStringList labelList; 322 | for(int i=0;idataListY->count();++i){ 323 | labelList << ui->dataListY->item(i)->text(); 324 | } 325 | // Derive data using formula 326 | for (int i=0;i::infinity())||(dd[i] == -1*std::numeric_limits::infinity())){ 381 | dd[i] = NAN; 382 | } 383 | } 384 | break; 385 | } 386 | 387 | } else if (labelList.contains(formula[i])){ 388 | qDebug() << "We got value label:" << formula[i]; 389 | tmp = csvFile.getDataByName(formula[i]); 390 | if(i==0){ 391 | dd.append(tmp); 392 | } 393 | } 394 | } 395 | 396 | derivedDataLabel += mathStringStart; 397 | for (int i=0;idataListY->addItem(derivedDataLabel); 402 | ui->dataListX->addItem(derivedDataLabel); 403 | qDebug() << "Derived data name:" << derivedDataLabel << "data length:" << dd.length(); 404 | derivedDataVector.append(dd); 405 | derivedDataVectorLabels.append(derivedDataLabel); 406 | return derivedDataLabel; 407 | } 408 | 409 | 410 | void SimpleCsvLogAnalyzer::on_actionOpen_triggered() 411 | { 412 | QString filePath; 413 | #ifdef Q_OS_ANDROID 414 | CustomFileDialog *dlg = new CustomFileDialog(this); 415 | dlg->showMaximized(); 416 | int ret = dlg->exec(); 417 | if(ret){ 418 | filePath = dlg->filePath; 419 | } else { 420 | filePath.clear(); 421 | } 422 | dlg->deleteLater(); 423 | #else 424 | filePath = QFileDialog::getOpenFileName(this,"Select a file...","","*.csv"); 425 | #endif 426 | 427 | 428 | //QString filePath = QFileDialog::getOpenFileName(this,"Select a file...","","*.csv"); 429 | qDebug() << "filePath:" << filePath; 430 | if(filePath.isEmpty()){ 431 | qDebug() << "No file specified!"; 432 | showMessage("No file specified!"); 433 | return; 434 | } 435 | ui->rightTabs->setCurrentIndex(0); 436 | startBusy(); 437 | 438 | derivedDataVector.clear(); 439 | derivedDataVectorLabels.clear(); 440 | 441 | ui->dataListX->clear(); 442 | ui->dataListY->clear(); 443 | 444 | clearPlotNDisableTracer(); 445 | clearStatisticsLabels(); 446 | qApp->processEvents(); 447 | 448 | csvFile.setFilePath(filePath); 449 | m_labels = csvFile.getCsvFileLabels(); 450 | m_sampleValues = csvFile.getSampleValuesForLabels(); 451 | ui->dataListY->addItems(m_labels); 452 | ui->dataListX->addItems(m_labels); 453 | // csvFile.file2TableWidget(ui->dataTableWidget); 454 | 455 | // Get real time data from "Device Time" label than convert it to msecFromEpoch 456 | QStringList timeStr = csvFile.getRawDataByName("Device Time"); 457 | if(timeStr.isEmpty()){ 458 | showMessage("Device time values could not be read from log file!\n" 459 | "All Y plots will be plotted with respect to file record(sample) number!\n" 460 | "If labels are not uniformly sampled in time, resulting plots cannot be used for qualitative analysis!"); 461 | } else { 462 | QVector timeMSecSinceEpoch; 463 | QVector timeSecsSinceStart; 464 | qint64 startOfLog = 0; 465 | QDateTime tmp; 466 | bool started = false; 467 | for (int i=0;idataListY->addItem(derivedDataLabel); 486 | ui->dataListX->addItem(derivedDataLabel); 487 | qDebug() << "Derived data name:" << derivedDataLabel << "data length:" << timeMSecSinceEpoch.length(); 488 | derivedDataVector.append(timeMSecSinceEpoch); 489 | derivedDataVectorLabels.append(derivedDataLabel); 490 | } else { 491 | showMessage("mSecSinceEpoch derivation error!\n" 492 | "Check log file and make sure \"Device Time\ has a format like" + torqueDeviceTimeFormat); 493 | } 494 | 495 | // Add time: seconds since log file started 496 | if(!timeSecsSinceStart.isEmpty()){ 497 | derivedDataLabel.clear(); 498 | derivedDataLabel += mathStringStart; 499 | derivedDataLabel += "Time Since Start (s)"; 500 | derivedDataLabel += mathStringEnd; 501 | ui->dataListY->addItem(derivedDataLabel); 502 | ui->dataListX->addItem(derivedDataLabel); 503 | qDebug() << "Derived data name:" << derivedDataLabel << "data length:" << timeSecsSinceStart.length(); 504 | derivedDataVector.append(timeSecsSinceStart); 505 | derivedDataVectorLabels.append(derivedDataLabel); 506 | } else { 507 | showMessage("Time Since Start (s) derivation error!\n" 508 | "Check log file and make sure \"Device Time\ has a format like" + torqueDeviceTimeFormat); 509 | } 510 | } 511 | stopBusy(); 512 | 513 | } 514 | 515 | void SimpleCsvLogAnalyzer::plotGraph(QString xName, QString yName) 516 | { 517 | if(xName.isEmpty() && yName.isEmpty()){ 518 | qDebug() << "Select label(s) before plotting..."; 519 | return; 520 | } 521 | startBusy(); 522 | clearPlotNDisableTracer(); 523 | 524 | if(xName.isEmpty()){ 525 | // Plot Y labels vs time, if no time info than plot versus data point number 526 | if(yName.startsWith(mathStringStart)){ 527 | qDebug() << "We got derived data here, name:" << yName; 528 | qDebug() << "Available derived data labels:" << derivedDataVectorLabels; 529 | qDebug() << yName << "index in derivedDataVectorLabels" << derivedDataVectorLabels.indexOf(yName); 530 | // Get derived data from buffer 531 | if(derivedDataVectorLabels.indexOf(yName)>=0){ 532 | qDebug() << "We have label for " << yName; 533 | if(derivedDataVector.length()>derivedDataVectorLabels.indexOf(yName)){ 534 | qDebug() << "We have data for " << yName; 535 | yVals = derivedDataVector[derivedDataVectorLabels.indexOf(yName)]; 536 | } 537 | } 538 | } else { 539 | yVals = csvFile.getDataByName(yName); 540 | } 541 | if(yVals.isEmpty()){ 542 | ui->statusbar->showMessage("No Y axis data to plot!"); 543 | showMessage("No Y axis data to plot!"); 544 | return; 545 | } 546 | plotType = PLOT_Y_VS_POINT_NUM; 547 | // Get X Label values 548 | xName = QString("%1%2%3").arg(mathStringStart) 549 | .arg("Time Since Start (s)") 550 | .arg(mathStringEnd); 551 | if(derivedDataVectorLabels.contains(xName)){ 552 | qDebug() << "We have real time info"; 553 | qDebug() << xName << "index in derivedDataVectorLabels" << derivedDataVectorLabels.indexOf(xName); 554 | // Get derived data from buffer 555 | if(derivedDataVectorLabels.indexOf(xName)>=0){ 556 | qDebug() << "We have label for " << xName; 557 | if(derivedDataVector.length()>derivedDataVectorLabels.indexOf(xName)){ 558 | qDebug() << "We have data for " << xName; 559 | xVals = derivedDataVector[derivedDataVectorLabels.indexOf(xName)]; 560 | xName = "Time Since Start (s)"; 561 | } 562 | } 563 | } 564 | 565 | if(xVals.isEmpty()){ 566 | xName = "Sample Number"; 567 | xVals.resize(yVals.length()); 568 | for(int i=0;iplot1->xAxis->setLabel(xName); 574 | ui->plot1->yAxis->setLabel(yName); 575 | // configure plot style 576 | valuePlot->setLineStyle(QCPGraph::lsLine); 577 | valuePlot->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDot, 1)); 578 | valuePlot->setData(xVals,yVals); 579 | QPen pen = valuePlot->pen(); 580 | pen.setColor(Qt::blue); 581 | valuePlot->setPen(pen); 582 | } else { 583 | // Plot Y labels vs Selected X label 584 | // Get Y Label values 585 | if(yName.startsWith(mathStringStart)){ 586 | qDebug() << "We got derived data here, name:" << yName; 587 | qDebug() << "Available derived data labels:" << derivedDataVectorLabels; 588 | qDebug() << yName << "index in derivedDataVectorLabels" << derivedDataVectorLabels.indexOf(yName); 589 | // Get derived data from buffer 590 | if(derivedDataVectorLabels.indexOf(yName)>=0){ 591 | qDebug() << "We have label for " << yName; 592 | if(derivedDataVector.length()>derivedDataVectorLabels.indexOf(yName)){ 593 | qDebug() << "We have data for " << yName; 594 | yVals = derivedDataVector[derivedDataVectorLabels.indexOf(yName)]; 595 | } 596 | } 597 | } else { 598 | yVals = csvFile.getDataByName(yName); 599 | } 600 | if(yVals.isEmpty()){ 601 | ui->statusbar->showMessage("No Y axis data to plot!"); 602 | showMessage("No Y axis data to plot!"); 603 | return; 604 | } 605 | // Get X Label values 606 | if(xName.startsWith(mathStringStart)){ 607 | qDebug() << "We got derived data here, name:" << xName; 608 | qDebug() << "Available derived data labels:" << derivedDataVectorLabels; 609 | qDebug() << xName << "index in derivedDataVectorLabels" << derivedDataVectorLabels.indexOf(xName); 610 | // Get derived data from buffer 611 | if(derivedDataVectorLabels.indexOf(xName)>=0){ 612 | qDebug() << "We have label for " << xName; 613 | if(derivedDataVector.length()>derivedDataVectorLabels.indexOf(xName)){ 614 | qDebug() << "We have data for " << xName; 615 | xVals = derivedDataVector[derivedDataVectorLabels.indexOf(xName)]; 616 | } 617 | } 618 | } else { 619 | xVals = csvFile.getDataByName(xName); 620 | } 621 | if(xVals.isEmpty()){ 622 | ui->statusbar->showMessage("No X axis data to plot!"); 623 | showMessage("No X axis data to plot!"); 624 | return; 625 | } 626 | plotType = PLOT_Y_VS_X; 627 | ui->plot1->xAxis->setLabel(xName); 628 | ui->plot1->yAxis->setLabel(yName); 629 | // configure plot style 630 | valuePlot->setLineStyle(QCPGraph::lsLine); 631 | valuePlot->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDot, 3)); 632 | valuePlot->setData(xVals,yVals); 633 | QPen pen = valuePlot->pen(); 634 | pen.setColor(Qt::red); 635 | valuePlot->setPen(pen); 636 | } 637 | 638 | qDebug() << xVals.length() << yVals.length(); 639 | valuePlot->setData(xVals,yVals); 640 | 641 | setupTracer(); 642 | stats = calculateStatisticalData(xVals,yVals,false); 643 | populateStatisticsLabels(); 644 | zoomReset(); 645 | ui->rightTabs->setCurrentIndex(0); 646 | stopBusy(); 647 | 648 | } 649 | 650 | void SimpleCsvLogAnalyzer::on_plotSelected_clicked() 651 | { 652 | // Plots values of selected data name versus recorda/data point 653 | if(ui->dataListY->selectedItems().isEmpty()){ 654 | ui->statusbar->showMessage("Select a proper data for y axis!"); 655 | showMessage("Select a proper data for y axis!"); 656 | return; 657 | } 658 | 659 | QString name = ui->dataListY->selectedItems().first()->text(); 660 | 661 | plotGraph("",name); 662 | 663 | } 664 | 665 | void SimpleCsvLogAnalyzer::on_plotSelectedXY_clicked() 666 | { 667 | // Plots values of selected data name versus selected another data field 668 | if(ui->dataListY->selectedItems().isEmpty() | ui->dataListX->selectedItems().isEmpty()){ 669 | ui->statusbar->showMessage("Select a proper data for both x and y axis!"); 670 | showMessage("Select a proper data for both x and y axis!"); 671 | return; 672 | } 673 | 674 | QString nameY = ui->dataListY->selectedItems().first()->text(); 675 | QString nameX = ui->dataListX->selectedItems().first()->text(); 676 | 677 | plotGraph(nameX,nameY); 678 | } 679 | 680 | void SimpleCsvLogAnalyzer::tracerEvent(QMouseEvent *event) 681 | { 682 | if(plotType == PLOT_NONE){ 683 | return; 684 | } 685 | 686 | // Find corresponding graph value for both y and x 687 | mousePlotCoordX = ui->plot1->xAxis->pixelToCoord(event->pos().x()); 688 | mousePlotCoordY = ui->plot1->yAxis->pixelToCoord(event->pos().y()); 689 | //qDebug() << "Mouse plot coordinates. X:" << mousePlotCoordX << "Y:" << mousePlotCoordY; 690 | 691 | QVector x(2), y(2); 692 | x[0] = mousePlotCoordX; 693 | y[0] = 0; 694 | x[1] = mousePlotCoordX; 695 | y[1] = 0; 696 | verticalLine->setData(x, y); 697 | QList ret; 698 | tracer->setGraphKey(mousePlotCoordX); 699 | ui->plot1->replot(); 700 | zoomCursorCenter = tracer->position->key(); 701 | //qDebug() << "Slope of curve at:" << mousePlotCoordX << "is:" << calculateSlopeOfCurve(mousePlotCoordX); 702 | switch (plotType) { 703 | case PLOT_Y_VS_POINT_NUM: 704 | ret = calculateSlopeOfCurve(tracer->position->key()); 705 | ui->statusbar->showMessage(QString("%1: %2, %3: %4, Left Slope: %5, Right Slope:%6") 706 | .arg(ui->plot1->xAxis->label()) 707 | .arg(QString::number(tracer->position->key(),'f',2)) 708 | .arg(ui->plot1->yAxis->label()) 709 | .arg(QString::number(tracer->position->value(),'f',2)) 710 | .arg(QString::number(ret[0],'f',2)) 711 | .arg(QString::number(ret[1],'f',2))); 712 | break; 713 | case PLOT_Y_VS_X: 714 | ui->statusbar->showMessage(QString("%1: %2, %3: %4, Y/X: %5, Y/X of Mouse: %6").arg(ui->plot1->xAxis->label()) 715 | .arg(QString::number(tracer->position->key(),'f',4)) 716 | .arg(ui->plot1->yAxis->label()) 717 | .arg(QString::number(tracer->position->value(),'f',4)) 718 | .arg(QString::number(tracer->position->value()/tracer->position->key(),'f',4)) 719 | .arg(QString::number(mousePlotCoordY/mousePlotCoordX,'f',4))); 720 | break; 721 | case PLOT_Y1_AND_Y2_VS_POINT_NUM: 722 | 723 | break; 724 | case PLOT_Y1_Y2_VS_X: 725 | 726 | break; 727 | default: 728 | break; 729 | } 730 | 731 | 732 | } 733 | 734 | void SimpleCsvLogAnalyzer::moveRigthPressed() 735 | { 736 | qDebug() << "moveRigthPressed"; 737 | } 738 | 739 | void SimpleCsvLogAnalyzer::on_actionZoom_Reset_triggered() 740 | { 741 | zoomReset(); 742 | } 743 | 744 | void SimpleCsvLogAnalyzer::on_actionZoom_In_triggered() 745 | { 746 | QCPRange xRange = ui->plot1->xAxis->range(); 747 | // use zoomCursorCenter for zooming centered at last traced point, 748 | // overwrite it with low + span/2 to zoom at plot center 749 | zoomCursorCenter = xRange.lower + (xRange.upper-xRange.lower)/2; 750 | double newSpan = (xRange.upper-xRange.lower)*0.9; 751 | xRange.lower = zoomCursorCenter - (newSpan/2); 752 | xRange.upper = zoomCursorCenter + (newSpan/2); 753 | ui->plot1->xAxis->setRange(xRange); 754 | ui->plot1->replot(); 755 | } 756 | 757 | void SimpleCsvLogAnalyzer::on_actionZoom_Out_triggered() 758 | { 759 | QCPRange xRange = ui->plot1->xAxis->range(); 760 | // use zoomCursorCenter for zooming centered at last traced point, 761 | // overwrite it with low + span/2 to zoom at plot center 762 | zoomCursorCenter = xRange.lower + (xRange.upper-xRange.lower)/2; 763 | double newSpan = (xRange.upper-xRange.lower)*1.1111111; 764 | xRange.lower = zoomCursorCenter - (newSpan/2); 765 | xRange.upper = zoomCursorCenter + (newSpan/2); 766 | ui->plot1->xAxis->setRange(xRange); 767 | ui->plot1->replot(); 768 | } 769 | 770 | 771 | 772 | void SimpleCsvLogAnalyzer::on_actionSave_Plot_Image_triggered() 773 | { 774 | // Ask user to enter image name to save plot 775 | // It is covenient to generate a date-time and data field name based dafault file name for lazy users 776 | QString filePath; 777 | #ifdef Q_OS_ANDROID 778 | QString defaultFileName = QString("plot_capture_%1_vs_%2_%3.jpg") 779 | .arg(ui->plot1->xAxis->label().remove(QRegExp("[^a-zA-Z\\d\\s]"))) 780 | .arg(ui->plot1->yAxis->label().remove(QRegExp("[^a-zA-Z\\d\\s]"))) 781 | .arg(QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss")); 782 | CustomFileDialog *dlg = new CustomFileDialog(this,true,defaultFileName); 783 | dlg->showMaximized(); 784 | int ret = dlg->exec(); 785 | if(ret){ 786 | filePath = dlg->filePath; 787 | } else { 788 | filePath.clear(); 789 | } 790 | dlg->deleteLater(); 791 | if(!filePath.endsWith(".jpg")){ 792 | filePath.append(".jpg"); 793 | } 794 | #else 795 | filePath = QFileDialog::getSaveFileName(this,"Select a file...", 796 | QString("plot_capture_%1_vs_%2_%3.jpg") 797 | .arg(ui->plot1->xAxis->label().remove(QRegExp("[^a-zA-Z\\d\\s]"))) 798 | .arg(ui->plot1->yAxis->label().remove(QRegExp("[^a-zA-Z\\d\\s]"))) 799 | .arg(QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss")), 800 | "*.jpg"); 801 | #endif 802 | 803 | startBusy(); 804 | qDebug() << "filePath:" << filePath; 805 | if(filePath.isEmpty()){ 806 | qDebug() << "Dosya seçilmedi"; 807 | stopBusy(); 808 | return; 809 | } 810 | // Hide tracer, before saving plot as image 811 | tracer->setVisible(false); 812 | ui->plot1->replot(); 813 | ui->plot1->saveJpg(filePath,0,0,1,98); 814 | // Bring back tracer line 815 | tracer->setVisible(true); 816 | ui->plot1->replot(); 817 | 818 | stopBusy(); 819 | } 820 | 821 | 822 | void SimpleCsvLogAnalyzer::on_dataListY_currentRowChanged(int currentRow) 823 | { 824 | if(currentRow<0){ 825 | return; 826 | } 827 | QString s; 828 | if(currentRow>=m_sampleValues.length()){ 829 | s = QString("No sample value for %1").arg(ui->dataListY->item(currentRow)->text()); 830 | } else { 831 | s = QString("Sample value for %1 is %2").arg(ui->dataListY->item(currentRow)->text()) 832 | .arg(m_sampleValues.at(currentRow)); 833 | } 834 | ui->statusbar->showMessage(s); 835 | } 836 | 837 | 838 | void SimpleCsvLogAnalyzer::on_rightTabs_currentChanged(int index) 839 | { 840 | // Close loading indicator 841 | stopBusy(); 842 | } 843 | 844 | void SimpleCsvLogAnalyzer::on_rightTabs_tabBarClicked(int index) 845 | { 846 | startBusy(); 847 | } 848 | 849 | //void SimpleCsvLogAnalyzer::on_dataTableWidget_customContextMenuRequested(const QPoint &pos) 850 | //{ 851 | // Q_UNUSED(pos) 852 | // tableViewContextMenu->exec(QCursor::pos()); 853 | //} 854 | 855 | //void SimpleCsvLogAnalyzer::hideTableColumns_forTable() 856 | //{ 857 | // QItemSelectionModel *select = ui->dataTableWidget->selectionModel(); 858 | 859 | // if(!select->hasSelection()){ //check if has selection 860 | // qDebug() << "no selection"; 861 | // return; 862 | // } 863 | // startBusy(); 864 | // QModelIndexList indexList = select->selectedColumns(); // return selected column(s) 865 | 866 | // qDebug() << "Selected columns length:" << indexList.length(); 867 | // for(int i=0; idataTableWidget->hideColumn(indexList[i].column()); 870 | // } 871 | // ui->dataTableWidget->clearSelection(); 872 | // stopBusy(); 873 | //} 874 | 875 | //void SimpleCsvLogAnalyzer::showTableColumns_forTable() 876 | //{ 877 | // QItemSelectionModel *select = ui->dataTableWidget->selectionModel(); 878 | 879 | // if(!select->hasSelection()){ //check if has selection 880 | // qDebug() << "no selection"; 881 | // return; 882 | // } 883 | // startBusy(); 884 | // QModelIndexList indexList = select->selectedColumns(); // return selected column(s) 885 | 886 | // // Hide all 887 | // for (int i=0; idataTableWidget->columnCount(); ++i) { 888 | // ui->dataTableWidget->hideColumn(i); 889 | // } 890 | // ui->dataTableWidget->clearSelection(); 891 | // // Show selected columns 892 | // qDebug() << "Selected columns length:" << indexList.length(); 893 | // for(int i=0; idataTableWidget->showColumn(indexList[i].column()); 896 | // } 897 | // stopBusy(); 898 | //} 899 | 900 | //void SimpleCsvLogAnalyzer::restoreTableColumns_forTable() 901 | //{ 902 | // startBusy(); 903 | // for (int i=0; idataTableWidget->columnCount(); ++i) { 904 | // ui->dataTableWidget->showColumn(i); 905 | // } 906 | // ui->dataTableWidget->clearSelection(); 907 | // stopBusy(); 908 | //} 909 | 910 | //void SimpleCsvLogAnalyzer::plotThis_forTable() 911 | //{ 912 | // QItemSelectionModel *select = ui->dataTableWidget->selectionModel(); 913 | 914 | // if(!select->hasSelection()){ //check if has selection 915 | // qDebug() << "no selection"; 916 | // return; 917 | // } 918 | // startBusy(); 919 | // QModelIndexList indexList = select->selectedColumns(); // return selected column(s) 920 | // qDebug() << "Plot: Selected column:" << indexList.first().column() 921 | // << "name:" << ui->dataTableWidget->horizontalHeaderItem(indexList.first().column())->text(); 922 | // plotGraph("",ui->dataTableWidget->horizontalHeaderItem(indexList.first().column())->text()); 923 | // ui->dataTableWidget->clearSelection(); 924 | // stopBusy(); 925 | //} 926 | 927 | //void SimpleCsvLogAnalyzer::statisticsForThis_forTable() 928 | //{ 929 | // QItemSelectionModel *select = ui->dataTableWidget->selectionModel(); 930 | 931 | // if(!select->hasSelection()){ //check if has selection 932 | // qDebug() << "no selection"; 933 | // return; 934 | // } 935 | // startBusy(); 936 | // QModelIndexList indexList = select->selectedColumns(); // return selected column(s) 937 | // qDebug() << "Statistics: Selected column:" << indexList.first().column() 938 | // << "name:" << ui->dataTableWidget->horizontalHeaderItem(indexList.first().column())->text(); 939 | // calculateStatisticalData(QVector(),csvFile.getDataByName(ui->dataTableWidget->horizontalHeaderItem(indexList.first().column())->text()),true); 940 | // stopBusy(); 941 | // ui->dataTableWidget->clearSelection(); 942 | //} 943 | 944 | void SimpleCsvLogAnalyzer::plotThis_forList() 945 | { 946 | QItemSelectionModel *select = ui->dataListY->selectionModel(); 947 | 948 | if(!select->hasSelection()){ //check if has selection 949 | qDebug() << "no selection"; 950 | return; 951 | } 952 | startBusy(); 953 | QModelIndexList indexList = select->selectedRows(); // return selected column(s) 954 | qDebug() << "Plot: Selected column:" << indexList.first().row() 955 | << "name:" << ui->dataListY->item(indexList.first().row())->text(); 956 | plotGraph("",ui->dataListY->item(indexList.first().row())->text()); 957 | // ui->dataTableWidget->clearSelection(); 958 | stopBusy(); 959 | } 960 | 961 | void SimpleCsvLogAnalyzer::plotThisVsAnotherDataLabel_forList() 962 | { 963 | QItemSelectionModel *select = ui->dataListY->selectionModel(); 964 | 965 | if(!select->hasSelection()){ //check if has selection 966 | qDebug() << "no selection"; 967 | return; 968 | } 969 | QStringList labelList; 970 | for(int i=0;idataListY->count();++i){ 971 | labelList << ui->dataListY->item(i)->text(); 972 | } 973 | QString selectedXAxisLabel = QInputDialog::getItem(this,"Select data label for X axis","X axis data label:",labelList,0); 974 | startBusy(); 975 | QModelIndexList indexList = select->selectedRows(); // return selected column(s) 976 | qDebug() << "Plot: Selected column:" << indexList.first().row() 977 | << "name:" << ui->dataListY->item(indexList.first().row())->text(); 978 | plotGraph(selectedXAxisLabel,ui->dataListY->item(indexList.first().row())->text()); 979 | // ui->dataTableWidget->clearSelection(); 980 | stopBusy(); 981 | } 982 | 983 | void SimpleCsvLogAnalyzer::statisticsForThis_forList() 984 | { 985 | QItemSelectionModel *select = ui->dataListY->selectionModel(); 986 | 987 | if(!select->hasSelection()){ //check if has selection 988 | qDebug() << "no selection"; 989 | return; 990 | } 991 | startBusy(); 992 | QModelIndexList indexList = select->selectedRows(); // return selected column(s) 993 | qDebug() << "Statistics: Selected column:" << indexList.first().row() 994 | << "name:" << ui->dataListY->item(indexList.first().row())->text(); 995 | calculateStatisticalData(QVector(),csvFile.getDataByName(ui->dataListY->item(indexList.first().row())->text()),true); 996 | stopBusy(); 997 | // ui->dataTableWidget->clearSelection(); 998 | } 999 | 1000 | 1001 | void SimpleCsvLogAnalyzer::on_dataListY_customContextMenuRequested(const QPoint &pos) 1002 | { 1003 | Q_UNUSED(pos) 1004 | labelListContextMenu->exec(QCursor::pos()); 1005 | } 1006 | 1007 | void SimpleCsvLogAnalyzer::on_DataDerivator_clicked() 1008 | { 1009 | 1010 | // QMessageBox msgBox; 1011 | // msgBox.setText(QString("Screen Resolution: W:%1, H:%2") 1012 | // .arg(qApp->desktop()->width()) 1013 | // .arg(qApp->desktop()->height())); 1014 | // msgBox.exec(); 1015 | QStringList labelList; 1016 | for(int i=0;idataListY->count();++i){ 1017 | if(!ui->dataListY->item(i)->text().startsWith(mathStringStart)){ 1018 | labelList << ui->dataListY->item(i)->text(); 1019 | } 1020 | } 1021 | DataMath *math = new DataMath(labelList,mathOperatorsList); 1022 | #ifdef Q_OS_ANDROID 1023 | math->showMaximized(); 1024 | #endif 1025 | // math->showMaximized(); 1026 | int ret = math->exec(); 1027 | 1028 | //connect(math,SIGNAL()) 1029 | //qDebug() << "Return:" << ret; 1030 | qDebug() << "Math ops: " << math->mathOps; 1031 | 1032 | if(ret){ 1033 | if(math->mathOps.isEmpty()){ 1034 | ui->statusbar->showMessage("Empty formula for derived data!"); 1035 | showMessage("Empty formula for derived data!"); 1036 | } else { 1037 | createDerivedDataLabel(math->mathOps); 1038 | // QString derivedDataLabel; 1039 | // derivedDataLabel += mathStringStart; 1040 | // for (int i=0;imathOps.length();++i) { 1041 | // derivedDataLabel += math->mathOps[i]; 1042 | // } 1043 | // derivedDataLabel += mathStringEnd; 1044 | // ui->dataListY->addItem(derivedDataLabel); 1045 | // ui->dataListX->addItem(derivedDataLabel); 1046 | // QVector values = createDerivedDataLabel(math->mathOps); 1047 | // qDebug() << "Derived data name:" << derivedDataLabel << "data length:" << values.length(); 1048 | // derivedDataVector.append(values); 1049 | // derivedDataVectorLabels.append(derivedDataLabel); 1050 | } 1051 | } 1052 | 1053 | math->deleteLater(); 1054 | } 1055 | 1056 | void SimpleCsvLogAnalyzer::on_actionData_Derivator_triggered() 1057 | { 1058 | on_DataDerivator_clicked(); 1059 | } 1060 | 1061 | void SimpleCsvLogAnalyzer::on_actionPlot_SelectedData_triggered() 1062 | { 1063 | on_plotSelected_clicked(); 1064 | } 1065 | 1066 | void SimpleCsvLogAnalyzer::on_actionplot_SelectedDataVsSelectedData_triggered() 1067 | { 1068 | on_plotSelectedXY_clicked(); 1069 | } 1070 | 1071 | void SimpleCsvLogAnalyzer::plotThisPredefinedQuickPlot(QString labelNameForY, QString labelNameForX) 1072 | { 1073 | // if(!labelNameForX.isEmpty()){ 1074 | // // Check if the labels list is empty 1075 | // if(ui->dataListY->count() ==0){ 1076 | // showMessage("Open a log file before creating a new plot"); 1077 | // return; 1078 | // } 1079 | // // Check if the selected label is derived 1080 | // if(labelfo) 1081 | // QList items = ui->dataListY->findItems(labelNameForY,Qt::MatchContains); 1082 | // if(!items.isEmpty()){ 1083 | // plotGraph("",items.first()->text()); 1084 | // } else { 1085 | // showMessage("Cannot find selected label!\nAdd selected label(s) to \"what to log\" list " 1086 | // "in your Torque app to favor this type of plot\n" 1087 | // "Or retry with another log file that contains selected label"); 1088 | // return; 1089 | // } 1090 | // } 1091 | 1092 | // if(ui->dataListY->count() ==0){ 1093 | // showMessage("Open a log file before creating a new plot"); 1094 | // return; 1095 | // } 1096 | // QList items = ui->dataListY->findItems(labelNameForY,Qt::MatchContains); 1097 | // if(!items.isEmpty()){ 1098 | // plotGraph("",items.first()->text()); 1099 | // } else { 1100 | // showMessage("Cannot find selected label!\nAdd Speed (OBD) label to \"what to log\" list " 1101 | // "in your Torque app to favor this type of plot\n" 1102 | // "Or retry with another log file that contains selected label"); 1103 | // return; 1104 | // } 1105 | } 1106 | 1107 | QString SimpleCsvLogAnalyzer::getProperLabelName(QString name) 1108 | { 1109 | QString s; 1110 | if(ui->dataListY->count() ==0){ 1111 | showMessage("Open a log file before creating a new plot"); 1112 | return s; 1113 | } 1114 | QList items = ui->dataListY->findItems(name,Qt::MatchContains); 1115 | if(!items.isEmpty()){ 1116 | s = items.first()->text(); 1117 | } 1118 | return s; 1119 | } 1120 | 1121 | void SimpleCsvLogAnalyzer::on_predefinedPlot1_clicked() 1122 | { 1123 | // Speed (OBD) vs Time 1124 | QString properName = getProperLabelName("Speed (OBD)"); 1125 | 1126 | if(properName.isEmpty()){ 1127 | showMessage("Cannot find or derive selected label!\nAdd selected label(s) to \"what to log\" list " 1128 | "in your Torque app to favor this type of plot\n" 1129 | "Or retry with another log file that contains selected label"); 1130 | } else { 1131 | // add time info for x axis 1132 | plotGraph("",properName); 1133 | } 1134 | 1135 | } 1136 | 1137 | void SimpleCsvLogAnalyzer::on_predefinedPlot2_clicked() 1138 | { 1139 | // Speed (GPS) vs Time 1140 | QString properName = getProperLabelName("Speed (GPS)"); 1141 | 1142 | if(properName.isEmpty()){ 1143 | showMessage("Cannot find or derive selected label!\nAdd selected label(s) to \"what to log\" list " 1144 | "in your Torque app to favor this type of plot or retry with another log file that contains selected label"); 1145 | } else { 1146 | // add time info for x axis 1147 | plotGraph("",properName); 1148 | } 1149 | } 1150 | 1151 | void SimpleCsvLogAnalyzer::on_predefinedPlot3_clicked() 1152 | { 1153 | // Altitude vs Time 1154 | QString properName = getProperLabelName("Altitude"); 1155 | 1156 | if(properName.isEmpty()){ 1157 | showMessage("Cannot find or derive selected label!\nAdd selected label(s) to \"what to log\" list " 1158 | "in your Torque app to favor this type of plot or retry with another log file that contains selected label"); 1159 | } else { 1160 | // add time info for x axis 1161 | plotGraph("",properName); 1162 | } 1163 | } 1164 | 1165 | void SimpleCsvLogAnalyzer::on_predefinedPlot4_clicked() 1166 | { 1167 | // Avg. Consumption vs Time 1168 | QString properName = getProperLabelName("Trip average"); 1169 | 1170 | if(properName.isEmpty()){ 1171 | showMessage("Cannot find or derive selected label!\nAdd selected label(s) to \"what to log\" list " 1172 | "in your Torque app to favor this type of plot or retry with another log file that contains selected label"); 1173 | } else { 1174 | // add time info for x axis 1175 | plotGraph("",properName); 1176 | } 1177 | } 1178 | 1179 | void SimpleCsvLogAnalyzer::on_predefinedPlot5_clicked() 1180 | { 1181 | // LTFT vs Time 1182 | QString properName = getProperLabelName("Fuel Trim Bank 1 Long Term"); 1183 | 1184 | if(properName.isEmpty()){ 1185 | showMessage("Cannot find or derive selected label!\nAdd selected label(s) to \"what to log\" list " 1186 | "in your Torque app to favor this type of plot or retry with another log file that contains selected label"); 1187 | } else { 1188 | // add time info for x axis 1189 | plotGraph("",properName); 1190 | } 1191 | } 1192 | 1193 | void SimpleCsvLogAnalyzer::on_predefinedPlot7_clicked() 1194 | { 1195 | // STFT1 vs Time 1196 | QString properName = getProperLabelName("Fuel Trim Bank 1 Short Term"); 1197 | 1198 | if(properName.isEmpty()){ 1199 | showMessage("Cannot find or derive selected label!\nAdd selected label(s) to \"what to log\" list " 1200 | "in your Torque app to favor this type of plot or retry with another log file that contains selected label"); 1201 | } else { 1202 | // add time info for x axis 1203 | plotGraph("",properName); 1204 | } 1205 | } 1206 | 1207 | void SimpleCsvLogAnalyzer::on_predefinedPlot6_clicked() 1208 | { 1209 | // LTFT+STFT vs RPM 1210 | QString ltft = getProperLabelName("Fuel Trim Bank 1 Long Term"); 1211 | QString stft = getProperLabelName("Fuel Trim Bank 1 Short Term"); 1212 | QString rpm = getProperLabelName("Engine RPM"); 1213 | 1214 | if(ltft.isEmpty() | stft.isEmpty() | rpm.isEmpty()){ 1215 | showMessage("Cannot find or derive selected label!\nAdd selected label(s) to \"what to log\" list " 1216 | "in your Torque app to favor this type of plot or retry with another log file that contains selected label"); 1217 | } else { 1218 | // Check if there is already a neccessary derived data 1219 | QStringList formula; 1220 | QString ddLabel; 1221 | formula.append(ltft); 1222 | formula.append("+"); 1223 | formula.append(stft); 1224 | ddLabel += mathStringStart; 1225 | for (int i=0;i