[Kst] branches/work/kst/portto4/kst/src/datasources/ascii

Nicolas Brisset nicolas.brisset at eurocopter.com
Sat Feb 5 01:54:54 CET 2011


SVN commit 1218854 by brisset:

Add units to the ASCII datasource. It seems to work (as the units are picked up automatically in the bottom and left labels), but I'd be very happy 
to have some code review on what I did, because in the end it was much more changes than I had planned.
One thing I don't really like is that units can be completely off, e.g. if one is missing all the subsequent ones will be wrong, because field 
names and units are in 2 separate lists and connected by the index. But hopefully it should not crash too easily.
And I don't actually see any way to avoid that - we can't always work around stupid files (or users!)...


 M  +55 -20    asciiconfig.ui  
 M  +84 -26    asciisource.cpp  
 M  +3 -0      asciisource.h  


--- branches/work/kst/portto4/kst/src/datasources/ascii/asciiconfig.ui #1218853:1218854
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>357</width>
-    <height>532</height>
+    <height>545</height>
    </rect>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
@@ -192,6 +192,9 @@
       </item>
       <item row="2" column="0">
        <widget class="QCheckBox" name="_readUnits">
+        <property name="enabled">
+         <bool>false</bool>
+        </property>
         <property name="text">
          <string>Read units from line:</string>
         </property>
@@ -398,12 +401,12 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>20</x>
-     <y>20</y>
+     <x>34</x>
+     <y>342</y>
     </hint>
     <hint type="destinationlabel">
-     <x>20</x>
-     <y>20</y>
+     <x>243</x>
+     <y>341</y>
     </hint>
    </hints>
   </connection>
@@ -414,46 +417,78 @@
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>20</x>
-     <y>20</y>
+     <x>33</x>
+     <y>171</y>
     </hint>
     <hint type="destinationlabel">
-     <x>20</x>
-     <y>20</y>
+     <x>233</x>
+     <y>171</y>
     </hint>
    </hints>
   </connection>
   <connection>
-   <sender>_custom</sender>
+   <sender>_readUnits</sender>
    <signal>toggled(bool)</signal>
-   <receiver>_columnDelimiter</receiver>
+   <receiver>_unitsLine</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>20</x>
-     <y>20</y>
+     <x>95</x>
+     <y>191</y>
     </hint>
     <hint type="destinationlabel">
-     <x>20</x>
-     <y>20</y>
+     <x>234</x>
+     <y>189</y>
     </hint>
    </hints>
   </connection>
   <connection>
-   <sender>_readUnits</sender>
+   <sender>_readFields</sender>
    <signal>toggled(bool)</signal>
+   <receiver>_readUnits</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>62</x>
+     <y>162</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>65</x>
+     <y>186</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>_readFields</sender>
+   <signal>toggled(bool)</signal>
    <receiver>_unitsLine</receiver>
    <slot>setEnabled(bool)</slot>
    <hints>
     <hint type="sourcelabel">
-     <x>112</x>
-     <y>175</y>
+     <x>100</x>
+     <y>162</y>
     </hint>
     <hint type="destinationlabel">
-     <x>273</x>
-     <y>175</y>
+     <x>331</x>
+     <y>192</y>
     </hint>
    </hints>
   </connection>
+  <connection>
+   <sender>_custom</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>_columnDelimiter</receiver>
+   <slot>setEnabled(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>34</x>
+     <y>312</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>158</x>
+     <y>311</y>
+    </hint>
+   </hints>
+  </connection>
  </connections>
 </ui>
--- branches/work/kst/portto4/kst/src/datasources/ascii/asciisource.cpp #1218853:1218854
@@ -65,7 +65,7 @@
 
   // meta data
   QMap<QString, double> metaScalars(const QString&);
-  QMap<QString, QString> metaStrings(const QString&) { return QMap<QString, QString>(); }
+  QMap<QString, QString> metaStrings(const QString&);
 
 
   AsciiSource& ascii;
@@ -98,8 +98,15 @@
   return m;
 }
 
+QMap<QString, QString> DataInterfaceAsciiVector::metaStrings(const QString& field)
+{
+  QMap<QString, QString> m;
+  m["units"]=ascii._fieldUnits[field];
+  return m;
+}
 
 
+
 //
 // String interface
 //
@@ -317,6 +324,16 @@
     }
     // Re-update the field list since we have one now
     _fieldList = fieldListFor(_filename, &_config);
+    QStringList units;
+    if (_config._readUnits) {
+      units += unitListFor(_filename, &_config);
+      for (int index = 0; index < _fieldList.size(); ++index) {
+        if (index >= units.size()) {
+          break; // Missing units => the user's fault, but at least don't crash
+        }
+        _fieldUnits[_fieldList[index]] = units[index];
+      }
+    }
     _fieldListComplete = _fieldList.count() > 1;
 
     // Re-update the scalar list since we have one now
@@ -673,47 +690,60 @@
 
 
 //-------------------------------------------------------------------------------------------
-QStringList AsciiSource::fieldListFor(const QString& filename, AsciiSourceConfig* cfg) 
+QStringList AsciiSource::splitHeaderLine(const QByteArray& line, AsciiSourceConfig* cfg)
 {
-  QStringList rc;
-  QFile file(filename);
-  if (!openFile(file)) {
-    return rc;
-  }
-
-  rc += "INDEX";
-
+  QStringList parts;
   const QString columnDelimiter = cfg->_columnDelimiter.value();
   const QRegExp regexColumnDelimiter(QString("[%1]").arg(QRegExp::escape(columnDelimiter)));
-  if (cfg->_readFields) {
-    int l = cfg->_fieldsLine;
-    while (!file.atEnd()) {
-      const QByteArray line = file.readLine();
-      int r = line.size();
-      if (l-- == 0) {
-        if (r >= 0) {
+
           if (cfg->_columnType == AsciiSourceConfig::Custom && !columnDelimiter.isEmpty()) {
-            rc += QString(line).trimmed().split(regexColumnDelimiter, QString::SkipEmptyParts);
+    parts += QString(line).trimmed().split(regexColumnDelimiter, QString::SkipEmptyParts);
           } else if (cfg->_columnType == AsciiSourceConfig::Fixed) {
             int cnt = line.length() / cfg->_columnWidth;
             for (int i = 0; i < cnt; ++i) {
               QString sub = line.mid(i * cfg->_columnWidth).left(cfg->_columnWidth);
-              rc += sub.trimmed();
+      parts += sub.trimmed();
             }
           } else {
-            rc += QString(line).trimmed().split(QRegExp("[\\s]"), QString::SkipEmptyParts);
+    parts += QString(line).trimmed().split(QRegExp("[\\s]"), QString::SkipEmptyParts);
           }
+  return parts;
         }
+
+
+//-------------------------------------------------------------------------------------------
+QStringList AsciiSource::fieldListFor(const QString& filename, AsciiSourceConfig* cfg) 
+{
+  QStringList fields;
+  QFile file(filename);
+  if (!openFile(file)) {
+    return fields;
+  }
+
+  fields += "INDEX";
+
+  if (cfg->_readFields) {
+    int fieldsLine = cfg->_fieldsLine;
+    int currentLine = 0; // Explicit line counter, to make the code easier to understand
+    while (currentLine < cfg->_dataLine) {
+      const QByteArray line = file.readLine();
+      int r = line.size();
+      if (currentLine == fieldsLine && r >= 0) {
+        fields += AsciiSource::splitHeaderLine(line, cfg);
         break;
       }
+      currentLine++;
     }
     QStringList trimmed;
-    foreach(const QString& str, rc) {
+    foreach(const QString& str, fields) {
       trimmed << str.trimmed();
     }
     return trimmed;
   }
 
+  const QString columnDelimiter = cfg->_columnDelimiter.value();
+  const QRegExp regexColumnDelimiter(QString("[%1]").arg(QRegExp::escape(columnDelimiter)));
+
   QRegExp regex;
   if (cfg->_columnType == AsciiSourceConfig::Custom && !columnDelimiter.isEmpty()) {
     regex.setPattern(QString("^[%1]*[%2].*").arg(QRegExp::escape(columnDelimiter)).arg(cfg->_delimiters));
@@ -744,7 +774,7 @@
     if (skip > 0) { //keep skipping until desired line
       --skip;
       if (r < 0) {
-        return rc;
+        return fields;
       }
       continue;
     }
@@ -763,7 +793,7 @@
             maxcnt = cnt;
           }
         } else if (r < 0) {
-          return rc;
+          return fields;
         }
         nextscan += nextscan + 1;
       }
@@ -781,18 +811,46 @@
       }
       done = true;
     } else if (r < 0) {
-      return rc;
+      return fields;
     }
   }
 
   for (int i = 1; i <= maxcnt; ++i) {
-    rc += i18n("Column %1").arg(i).trimmed();
+    fields += i18n("Column %1").arg(i).trimmed();
   }
 
-  return rc;
+  return fields;
 }
 
+QStringList AsciiSource::unitListFor(const QString& filename, AsciiSourceConfig* cfg)
+{
+  QStringList units;
+  QFile file(filename);
+  if (!openFile(file)) {
+    return units;
+  }
 
+  units += ""; // To go with INDEX
+
+  int unitsLine = cfg->_unitsLine;
+  int currentLine = 0;
+  while (currentLine < cfg->_dataLine) {
+    const QByteArray line = file.readLine();
+    int r = line.size();
+    if (currentLine == unitsLine && r >= 0) {
+      units += AsciiSource::splitHeaderLine(line, cfg);
+      break;
+    }
+    currentLine++;
+  }
+  QStringList trimmed;
+  foreach(const QString& str, units) {
+    trimmed << str.trimmed();
+  }
+  return trimmed;
+}
+
+
 //-------------------------------------------------------------------------------------------
 void AsciiSource::save(QXmlStreamWriter &s) 
 {
--- branches/work/kst/portto4/kst/src/datasources/ascii/asciisource.h #1218853:1218854
@@ -72,6 +72,7 @@
     static const QString asciiTypeKey();
 
     static QStringList fieldListFor(const QString& filename, AsciiSourceConfig *cfg);
+    static QStringList unitListFor(const QString& filename, AsciiSourceConfig* cfg);
     static QStringList scalarListFor(const QString& filename, AsciiSourceConfig *cfg);
     static QStringList stringListFor(const QString& filename, AsciiSourceConfig *cfg);
 
@@ -93,8 +94,10 @@
     QStringList _scalarList;
     QMap<QString, QString> _strings;
     QStringList _fieldList;
+    QMap<QString, QString> _fieldUnits;
 
     int columnOfField(const QString& field) const;
+    static QStringList splitHeaderLine(const QByteArray& line, AsciiSourceConfig* cfg);
 
     DataInterfaceAsciiString* is;
     DataInterfaceAsciiVector* iv;


More information about the Kst mailing list