[PATCH 1/4] Add support for importing o2 sensors from CSV file

Anton Lundin glance at acc.umu.se
Sat Jun 27 14:38:10 PDT 2015


This adds support for importing individual o2 sensors from a csv file,
eg a APD log viewer file.

Signed-off-by: Anton Lundin <glance at acc.umu.se>
---

Dam, this code is clunky. We should really rework how that field-thingie
works.

I want to pry my eyes out every time i touch that code.

How many places do you need to touch to add a field to the csv-importer?
 - To many!

 dive.h                        |  4 ++--
 file.c                        | 33 ++++++++++++++++++++++++---------
 qt-ui/divelogimportdialog.cpp | 38 +++++++++++++++++++++++++++-----------
 qt-ui/divelogimportdialog.h   |  3 +++
 xslt/csv2xml.xslt             | 30 ++++++++++++++++++++++++++++++
 5 files changed, 86 insertions(+), 22 deletions(-)

diff --git a/dive.h b/dive.h
index 318f822..f7044fb 100644
--- a/dive.h
+++ b/dive.h
@@ -653,8 +653,8 @@ extern int parse_cobalt_buffer(sqlite3 *handle, const char *url, const char *buf
 extern int parse_dlf_buffer(unsigned char *buffer, size_t size);
 
 extern int parse_file(const char *filename);
-extern int parse_csv_file(const char *filename, int time, int depth, int temp, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int units);
-extern int parse_seabear_csv_file(const char *filename, int time, int depth, int temp, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int units, const char *delta);
+extern int parse_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int o2Sensor1f, int o2Sensor2f, int o2Sensor3f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx);
+extern int parse_seabear_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int o2Sensor1f, int o2Sensor2f, int o2Sensor3f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx, const char *delta);
 extern int parse_txt_file(const char *filename, const char *csv);
 extern int parse_manual_file(const char *filename, int separator_index, int units, int dateformat, int durationformat, int number, int date, int time, int duration, int location, int gps, int maxdepth, int meandepth, int divemaster, int buddy, int suit, int notes, int weight, int tags, int cylsizef, int startpresf, int endpresf, int o2f, int hef, int airtempf, int watertempf);
 
diff --git a/file.c b/file.c
index 7b6f09a..816002e 100644
--- a/file.c
+++ b/file.c
@@ -819,7 +819,7 @@ int parse_txt_file(const char *filename, const char *csv)
 #define MAXCOLS 100
 #define DATESTR 9
 #define TIMESTR 6
-void init_csv_file_parsing(char **params, char *timebuf, char *depthbuf, char *tempbuf, char *po2buf, char *cnsbuf, char *ndlbuf, char *ttsbuf, char *stopdepthbuf, char *pressurebuf, char *unitbuf, char *separator_index, time_t *now, struct tm *timep, char *curdate, char *curtime, int timef, int depthf, int tempf, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx)
+void init_csv_file_parsing(char **params, char *timebuf, char *depthbuf, char *tempbuf, char *po2buf, char *o2sensor1buf, char *o2sensor2buf, char *o2sensor3buf, char *cnsbuf, char *ndlbuf, char *ttsbuf, char *stopdepthbuf, char *pressurebuf, char *unitbuf, char *separator_index, time_t *now, struct tm *timep, char *curdate, char *curtime, int timef, int depthf, int tempf, int po2f, int o2sensor1f, int o2sensor2f, int o2sensor3f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx)
 {
 	int pnr = 0;
 
@@ -827,6 +827,9 @@ void init_csv_file_parsing(char **params, char *timebuf, char *depthbuf, char *t
 	snprintf(depthbuf, MAXCOLDIGITS, "%d", depthf);
 	snprintf(tempbuf, MAXCOLDIGITS, "%d", tempf);
 	snprintf(po2buf, MAXCOLDIGITS, "%d", po2f);
+	snprintf(o2sensor1buf, MAXCOLDIGITS, "%d", o2sensor1f);
+	snprintf(o2sensor2buf, MAXCOLDIGITS, "%d", o2sensor2f);
+	snprintf(o2sensor3buf, MAXCOLDIGITS, "%d", o2sensor3f);
 	snprintf(cnsbuf, MAXCOLDIGITS, "%d", cnsf);
 	snprintf(ndlbuf, MAXCOLDIGITS, "%d", ndlf);
 	snprintf(ttsbuf, MAXCOLDIGITS, "%d", ttsf);
@@ -850,6 +853,12 @@ void init_csv_file_parsing(char **params, char *timebuf, char *depthbuf, char *t
 	params[pnr++] = tempbuf;
 	params[pnr++] = "po2Field";
 	params[pnr++] = po2buf;
+	params[pnr++] = "o2sensor1Field";
+	params[pnr++] = o2sensor1buf;
+	params[pnr++] = "o2sensor2Field";
+	params[pnr++] = o2sensor2buf;
+	params[pnr++] = "o2sensor3Field";
+	params[pnr++] = o2sensor3buf;
 	params[pnr++] = "cnsField";
 	params[pnr++] = cnsbuf;
 	params[pnr++] = "ndlField";
@@ -871,15 +880,18 @@ void init_csv_file_parsing(char **params, char *timebuf, char *depthbuf, char *t
 	params[pnr++] = NULL;
 }
 
-int parse_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx)
+int parse_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int o2sensor1f, int o2sensor2f, int o2sensor3f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx)
 {
 	int ret;
 	struct memblock mem;
-	char *params[27];
+	char *params[33];
 	char timebuf[MAXCOLDIGITS];
 	char depthbuf[MAXCOLDIGITS];
 	char tempbuf[MAXCOLDIGITS];
 	char po2buf[MAXCOLDIGITS];
+	char o2sensor1buf[MAXCOLDIGITS];
+	char o2sensor2buf[MAXCOLDIGITS];
+	char o2sensor3buf[MAXCOLDIGITS];
 	char cnsbuf[MAXCOLDIGITS];
 	char ndlbuf[MAXCOLDIGITS];
 	char ttsbuf[MAXCOLDIGITS];
@@ -900,10 +912,10 @@ int parse_csv_file(const char *filename, int timef, int depthf, int tempf, int p
 	xsltMaxVars = 150000;
 #endif
 
-	if (timef >= MAXCOLS || depthf >= MAXCOLS || tempf >= MAXCOLS || po2f >= MAXCOLS || cnsf >= MAXCOLS || ndlf >= MAXCOLS || cnsf >= MAXCOLS || stopdepthf >= MAXCOLS || pressuref >= MAXCOLS)
+	if (timef >= MAXCOLS || depthf >= MAXCOLS || tempf >= MAXCOLS || po2f >= MAXCOLS || o2sensor1f >= MAXCOLS || o2sensor2f >= MAXCOLS || o2sensor3f >= MAXCOLS || cnsf >= MAXCOLS || ndlf >= MAXCOLS || cnsf >= MAXCOLS || stopdepthf >= MAXCOLS || pressuref >= MAXCOLS)
 		return report_error(translate("gettextFromC", "Maximum number of supported columns on CSV import is %d"), MAXCOLS);
 
-	init_csv_file_parsing(params, timebuf, depthbuf, tempbuf, po2buf, cnsbuf,ndlbuf, ttsbuf, stopdepthbuf, pressurebuf, unitbuf, separator_index, &now, timep, curdate, curtime, timef, depthf, tempf, po2f, cnsf, ndlf, ttsf, stopdepthf, pressuref, sepidx, csvtemplate, unitidx);
+	init_csv_file_parsing(params, timebuf, depthbuf, tempbuf, po2buf, o2sensor1buf, o2sensor2buf, o2sensor3buf, cnsbuf, ndlbuf, ttsbuf, stopdepthbuf, pressurebuf, unitbuf, separator_index, &now, timep, curdate, curtime, timef, depthf, tempf, po2f, o2sensor1f, o2sensor2f, o2sensor3f, cnsf, ndlf, ttsf, stopdepthf, pressuref, sepidx, csvtemplate, unitidx);
 
 	if (filename == NULL)
 		return report_error("No CSV filename");
@@ -924,8 +936,8 @@ int parse_csv_file(const char *filename, int timef, int depthf, int tempf, int p
 	return ret;
 }
 
-#define SBPARAMS 29
-int parse_seabear_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx, const char *delta)
+#define SBPARAMS 35
+int parse_seabear_csv_file(const char *filename, int timef, int depthf, int tempf, int po2f, int o2sensor1f, int o2sensor2f, int o2sensor3f, int cnsf, int ndlf, int ttsf, int stopdepthf, int pressuref, int sepidx, const char *csvtemplate, int unitidx, const char *delta)
 {
 	int ret;
 	struct memblock mem;
@@ -934,6 +946,9 @@ int parse_seabear_csv_file(const char *filename, int timef, int depthf, int temp
 	char depthbuf[MAXCOLDIGITS];
 	char tempbuf[MAXCOLDIGITS];
 	char po2buf[MAXCOLDIGITS];
+	char o2sensor1buf[MAXCOLDIGITS];
+	char o2sensor2buf[MAXCOLDIGITS];
+	char o2sensor3buf[MAXCOLDIGITS];
 	char cnsbuf[MAXCOLDIGITS];
 	char ndlbuf[MAXCOLDIGITS];
 	char ttsbuf[MAXCOLDIGITS];
@@ -949,10 +964,10 @@ int parse_seabear_csv_file(const char *filename, int timef, int depthf, int temp
 	char *ptr, *ptr_old = NULL;
 	char *NL = NULL;
 
-	if (timef >= MAXCOLS || depthf >= MAXCOLS || tempf >= MAXCOLS || po2f >= MAXCOLS || cnsf >= MAXCOLS || ndlf >= MAXCOLS || cnsf >= MAXCOLS || stopdepthf >= MAXCOLS || pressuref >= MAXCOLS)
+	if (timef >= MAXCOLS || depthf >= MAXCOLS || tempf >= MAXCOLS || po2f >= MAXCOLS || o2sensor1f >= MAXCOLS || o2sensor2f >= MAXCOLS || o2sensor3f >= MAXCOLS || cnsf >= MAXCOLS || ndlf >= MAXCOLS || cnsf >= MAXCOLS || stopdepthf >= MAXCOLS || pressuref >= MAXCOLS)
 		return report_error(translate("gettextFromC", "Maximum number of supported columns on CSV import is %d"), MAXCOLS);
 
-	init_csv_file_parsing(params, timebuf, depthbuf, tempbuf, po2buf, cnsbuf,ndlbuf, ttsbuf, stopdepthbuf, pressurebuf, unitbuf, separator_index, &now, timep, curdate, curtime, timef, depthf, tempf, po2f, cnsf, ndlf, ttsf, stopdepthf, pressuref, sepidx, csvtemplate, unitidx);
+	init_csv_file_parsing(params, timebuf, depthbuf, tempbuf, po2buf, o2sensor1buf, o2sensor2buf, o2sensor3buf, cnsbuf, ndlbuf, ttsbuf, stopdepthbuf, pressurebuf, unitbuf, separator_index, &now, timep, curdate, curtime, timef, depthf, tempf, po2f, o2sensor1f, o2sensor2f, o2sensor3f, cnsf, ndlf, ttsf, stopdepthf, pressuref, sepidx, csvtemplate, unitidx);
 
 	if (filename == NULL)
 		return report_error("No CSV filename");
diff --git a/qt-ui/divelogimportdialog.cpp b/qt-ui/divelogimportdialog.cpp
index d3bb5e7..64f67fa 100644
--- a/qt-ui/divelogimportdialog.cpp
+++ b/qt-ui/divelogimportdialog.cpp
@@ -10,14 +10,14 @@ static QString subsurface_mimedata = "subsurface/csvcolumns";
 static QString subsurface_index = "subsurface/csvindex";
 
 const DiveLogImportDialog::CSVAppConfig DiveLogImportDialog::CSVApps[CSVAPPS] = {
-	// time, depth, temperature, po2, cns, ndl, tts, stopdepth, pressure
+	// time, depth, temperature, po2, sensor1, sensor2, sensor3, cns, ndl, tts, stopdepth, pressure
 	// indices are 0 based, -1 means the column doesn't exist
 	{ "Manual import", },
-	{ "APD Log Viewer", 0, 1, 15, 6, 17, -1, -1, 18, -1, "Tab" },
-	{ "XP5", 0, 1, 9, -1, -1, -1, -1, -1, -1, "Tab" },
-	{ "SensusCSV", 9, 10, -1, -1, -1, -1, -1, -1, -1, "," },
-	{ "Seabear CSV", 0, 1, 5, -1, -1, 2, 3, 4, 6, ";" },
-	{ "SubsurfaceCSV", -1, -1, -1, -1, -1, -1, -1, -1, -1, "Tab" },
+	{ "APD Log Viewer", 0, 1, 15, 6, 3, 4, 5, 17, -1, -1, 18, -1, "Tab" },
+	{ "XP5", 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Tab" },
+	{ "SensusCSV", 9, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "," },
+	{ "Seabear CSV", 0, 1, 5, -1, -1, -1, -1, -1, 2, 3, 4, 6, ";" },
+	{ "SubsurfaceCSV", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Tab" },
 	{ NULL, }
 };
 
@@ -26,7 +26,8 @@ ColumnNameProvider::ColumnNameProvider(QObject *parent) : QAbstractListModel(par
 	columnNames << tr("Dive #") << tr("Date") << tr("Time") << tr("Duration") << tr("Location") << tr("GPS") << tr("Weight") << tr("Cyl. size") << tr("Start pressure") <<
 		       tr("End pressure") << tr("Max. depth") << tr("Avg. depth") << tr("Divemaster") << tr("Buddy") << tr("Suit") << tr("Notes") << tr("Tags") << tr("Air temp.") << tr("Water temp.") <<
 		       tr("O₂") << tr("He") << tr("Sample time") << tr("Sample depth") << tr("Sample temperature") << tr("Sample pO₂") << tr("Sample CNS") << tr("Sample NDL") <<
-		       tr("Sample TTS") << tr("Sample stopdepth") << tr("Sample pressure");
+		       tr("Sample TTS") << tr("Sample stopdepth") << tr("Sample pressure") <<
+			   tr("Sample sensor1 pO₂") << tr("Sample sensor2 pO₂") << tr("Sample sensor3 pO₂");
 }
 
 bool ColumnNameProvider::insertRows(int row, int count, const QModelIndex &parent)
@@ -390,7 +391,6 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
 
 		/*
 		 * Parse CSV fields
-		 * The pO2 values from CCR diving are ignored later on.
 		 */
 
 		firstLine = f.readLine().trimmed();
@@ -408,11 +408,11 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
 			} else if (columnText == "TTS") {
 				headers.append("Sample TTS");
 			} else if (columnText == "pO2_1") {
-				headers.append("Sample pO2_1");
+				headers.append("Sample sensor1 pO₂");
 			} else if (columnText == "pO2_2") {
-				headers.append("Sample pO2_2");
+				headers.append("Sample sensor2 pO₂");
 			} else if (columnText == "pO2_3") {
-				headers.append("Sample pO2_3");
+				headers.append("Sample sensor3 pO₂");
 			} else if (columnText == "Ceiling") {
 				headers.append("Sample ceiling");
 			} else {
@@ -529,6 +529,12 @@ void DiveLogImportDialog::loadFileContents(int value, whatChanged triggeredBy)
 			headers.replace(CSVApps[value].temperature, tr("Sample temperature"));
 		if (CSVApps[value].po2 > -1 && CSVApps[value].po2 < currColumns.count())
 			headers.replace(CSVApps[value].po2, tr("Sample pO₂"));
+		if (CSVApps[value].po2 > -1 && CSVApps[value].po2 < currColumns.count())
+			headers.replace(CSVApps[value].sensor1, tr("Sample sensor1 pO₂"));
+		if (CSVApps[value].po2 > -1 && CSVApps[value].po2 < currColumns.count())
+			headers.replace(CSVApps[value].sensor2, tr("Sample sensor2 pO₂"));
+		if (CSVApps[value].po2 > -1 && CSVApps[value].po2 < currColumns.count())
+			headers.replace(CSVApps[value].sensor3, tr("Sample sensor3 pO₂"));
 		if (CSVApps[value].cns > -1 && CSVApps[value].cns < currColumns.count())
 			headers.replace(CSVApps[value].cns, tr("Sample CNS"));
 		if (CSVApps[value].ndl > -1 && CSVApps[value].ndl < currColumns.count())
@@ -583,6 +589,9 @@ void DiveLogImportDialog::on_buttonBox_accepted()
 						       r.indexOf(tr("Sample depth")),
 						       r.indexOf(tr("Sample temperature")),
 						       r.indexOf(tr("Sample pO₂")),
+						       r.indexOf(tr("Sample sensor1 pO₂")),
+						       r.indexOf(tr("Sample sensor2 pO₂")),
+						       r.indexOf(tr("Sample sensor3 pO₂")),
 						       r.indexOf(tr("Sample CNS")),
 						       r.indexOf(tr("Sample NDL")),
 						       r.indexOf(tr("Sample TTS")),
@@ -608,6 +617,9 @@ void DiveLogImportDialog::on_buttonBox_accepted()
 					       r.indexOf(tr("Sample depth")),
 					       r.indexOf(tr("Sample temperature")),
 					       r.indexOf(tr("Sample pO₂")),
+					       r.indexOf(tr("Sample sensor1 pO₂")),
+					       r.indexOf(tr("Sample sensor2 pO₂")),
+					       r.indexOf(tr("Sample sensor3 pO₂")),
 					       r.indexOf(tr("Sample CNS")),
 					       r.indexOf(tr("Sample NDL")),
 					       r.indexOf(tr("Sample TTS")),
@@ -655,6 +667,9 @@ void DiveLogImportDialog::on_buttonBox_accepted()
 					       r.indexOf(tr("Sample depth")),
 					       r.indexOf(tr("Sample temperature")),
 					       r.indexOf(tr("Sample pO₂")),
+					       r.indexOf(tr("Sample sensor1 pO₂")),
+					       r.indexOf(tr("Sample sensor2 pO₂")),
+					       r.indexOf(tr("Sample sensor3 pO₂")),
 					       r.indexOf(tr("Sample CNS")),
 					       r.indexOf(tr("Sample NDL")),
 					       r.indexOf(tr("Sample TTS")),
@@ -666,6 +681,7 @@ void DiveLogImportDialog::on_buttonBox_accepted()
 					       );
 		}
 	}
+
 	process_dives(true, false);
 	MainWindow::instance()->refreshDisplay();
 }
diff --git a/qt-ui/divelogimportdialog.h b/qt-ui/divelogimportdialog.h
index 3be267f..a78d30f 100644
--- a/qt-ui/divelogimportdialog.h
+++ b/qt-ui/divelogimportdialog.h
@@ -102,6 +102,9 @@ private:
 		int depth;
 		int temperature;
 		int po2;
+		int sensor1;
+		int sensor2;
+		int sensor3;
 		int cns;
 		int ndl;
 		int tts;
diff --git a/xslt/csv2xml.xslt b/xslt/csv2xml.xslt
index 05f9e23..29ebbce 100644
--- a/xslt/csv2xml.xslt
+++ b/xslt/csv2xml.xslt
@@ -6,6 +6,9 @@
   <xsl:param name="depthField" select="depthField"/>
   <xsl:param name="tempField" select="tempField"/>
   <xsl:param name="po2Field" select="po2Field"/>
+  <xsl:param name="o2sensor1Field" select="o2sensor1Field"/>
+  <xsl:param name="o2sensor2Field" select="o2sensor2Field"/>
+  <xsl:param name="o2sensor3Field" select="o2sensor3Field"/>
   <xsl:param name="cnsField" select="cnsField"/>
   <xsl:param name="otuField" select="otuField"/>
   <xsl:param name="ndlField" select="ndlField"/>
@@ -199,6 +202,33 @@
           </xsl:attribute>
         </xsl:if>
 
+        <xsl:if test="$o2sensor1Field >= 0">
+          <xsl:attribute name="sensor1">
+            <xsl:call-template name="getFieldByIndex">
+              <xsl:with-param name="index" select="$o2sensor1Field"/>
+              <xsl:with-param name="line" select="$line"/>
+            </xsl:call-template>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="$o2sensor2Field >= 0">
+          <xsl:attribute name="sensor2">
+            <xsl:call-template name="getFieldByIndex">
+              <xsl:with-param name="index" select="$o2sensor2Field"/>
+              <xsl:with-param name="line" select="$line"/>
+            </xsl:call-template>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="$o2sensor3Field >= 0">
+          <xsl:attribute name="sensor3">
+            <xsl:call-template name="getFieldByIndex">
+              <xsl:with-param name="index" select="$o2sensor3Field"/>
+              <xsl:with-param name="line" select="$line"/>
+            </xsl:call-template>
+          </xsl:attribute>
+        </xsl:if>
+
         <xsl:if test="$cnsField >= 0">
           <xsl:attribute name="cns">
             <xsl:call-template name="getFieldByIndex">
-- 
2.1.4



More information about the subsurface mailing list