bool FormattedTouchstone::ReadRow(FormattedNetworkData &network, QTextStream &snpFile, FormattedComplexMatrix2D &dataRow, double &frequencyPoint) { // Begin to read data values double wordsToRead = pow(double(network.numberOfPorts()), 2) * 2 + 1; QStringList allWords; while (wordsToRead > 0 && !snpFile.atEnd()) { QStringList words; ReadLine(snpFile, words); wordsToRead -= words.size(); allWords.append(words); } // Check to see if all data was read if (wordsToRead != 0) return false; // Process data frequencyPoint = allWords[0].toDouble(); QStringList::iterator wordIndex = allWords.begin() + 1; dataRow.resize(network.numberOfPorts()); for (FormattedComplexMatrix2D::iterator rowIndex = dataRow.begin(); rowIndex != dataRow.end(); rowIndex++) { (*rowIndex).resize(network.numberOfPorts()); FormattedComplexRowVector::iterator columnIndex = (*rowIndex).begin(); for (; columnIndex != (*rowIndex).end(); columnIndex++) { *columnIndex = (*ReadDatum)(wordIndex->toDouble(), (wordIndex + 1)->toDouble()); wordIndex += 2; } } return true; }
QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri ) : QgsVectorDataProvider( uri ), mXFieldIndex( -1 ), mYFieldIndex( -1 ), mShowInvalidLines( true ) { // Get the file name and mDelimiter out of the uri mFileName = uri.left( uri.indexOf( "?" ) ); // split the string up on & to get the individual parameters QStringList parameters = uri.mid( uri.indexOf( "?" ) ).split( "&", QString::SkipEmptyParts ); QgsDebugMsg( "Parameter count after split on &" + QString::number( parameters.size() ) ); // get the individual parameters and assign values QStringList temp = parameters.filter( "delimiter=" ); mDelimiter = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; temp = parameters.filter( "delimiterType=" ); mDelimiterType = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; temp = parameters.filter( "xField=" ); QString xField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; temp = parameters.filter( "yField=" ); QString yField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; // Decode the parts of the uri. Good if someone entered '=' as a delimiter, for instance. mFileName = QUrl::fromPercentEncoding( mFileName.toUtf8() ); mDelimiter = QUrl::fromPercentEncoding( mDelimiter.toUtf8() ); mDelimiterType = QUrl::fromPercentEncoding( mDelimiterType.toUtf8() ); xField = QUrl::fromPercentEncoding( xField.toUtf8() ); yField = QUrl::fromPercentEncoding( yField.toUtf8() ); QgsDebugMsg( "Data source uri is " + uri ); QgsDebugMsg( "Delimited text file is: " + mFileName ); QgsDebugMsg( "Delimiter is: " + mDelimiter ); QgsDebugMsg( "Delimiter type is: " + mDelimiterType ); QgsDebugMsg( "xField is: " + xField ); QgsDebugMsg( "yField is: " + yField ); // if delimiter contains some special characters, convert them if ( mDelimiterType == "regexp" ) mDelimiterRegexp = QRegExp( mDelimiter ); else mDelimiter.replace( "\\t", "\t" ); // replace "\t" with a real tabulator // Set the selection rectangle to null mSelectionRectangle = QgsRectangle(); // assume the layer is invalid until proven otherwise mValid = false; if ( mFileName.isEmpty() || mDelimiter.isEmpty() || xField.isEmpty() || yField.isEmpty() ) { // uri is invalid so the layer must be too... QString( "Data source is invalid" ); return; } // check to see that the file exists and perform some sanity checks if ( !QFile::exists( mFileName ) ) { QgsDebugMsg( "Data source " + dataSourceUri() + " doesn't exist" ); return; } // Open the file and get number of rows, etc. We assume that the // file has a header row and process accordingly. Caller should make // sure the the delimited file is properly formed. mFile = new QFile( mFileName ); if ( !mFile->open( QIODevice::ReadOnly ) ) { QgsDebugMsg( "Data source " + dataSourceUri() + " could not be opened" ); delete mFile; return; } // now we have the file opened and ready for parsing // set the initial extent mExtent = QgsRectangle(); QMap<int, bool> couldBeInt; QMap<int, bool> couldBeDouble; mStream = new QTextStream( mFile ); QString line; mNumberFeatures = 0; int lineNumber = 0; bool firstPoint = true; bool hasFields = false; while ( !mStream->atEnd() ) { lineNumber++; line = mStream->readLine(); // line of text excluding '\n', default local 8 bit encoding. if ( !hasFields ) { // Get the fields from the header row and store them in the // fields vector QgsDebugMsg( "Attempting to split the input line: " + line + " using delimiter " + mDelimiter ); QStringList fieldList; if ( mDelimiterType == "regexp" ) fieldList = line.split( mDelimiterRegexp ); else fieldList = line.split( mDelimiter ); QgsDebugMsg( "Split line into " + QString::number( fieldList.size() ) + " parts" ); // We don't know anything about a text based field other // than its name. All fields are assumed to be text int fieldPos = 0; for ( QStringList::Iterator it = fieldList.begin(); it != fieldList.end(); ++it ) { QString field = *it; if ( field.length() > 0 ) { // for now, let's set field type as text attributeFields[fieldPos] = QgsField( *it, QVariant::String, "Text" ); // check to see if this field matches either the x or y field if ( xField == *it ) { QgsDebugMsg( "Found x field: " + ( *it ) ); mXFieldIndex = fieldPos; } else if ( yField == *it ) { QgsDebugMsg( "Found y field: " + ( *it ) ); mYFieldIndex = fieldPos; } QgsDebugMsg( "Adding field: " + ( *it ) ); // assume that the field could be integer or double couldBeInt.insert( fieldPos, true ); couldBeDouble.insert( fieldPos, true ); fieldPos++; } } QgsDebugMsg( "Field count for the delimited text file is " + QString::number( attributeFields.size() ) ); hasFields = true; } else if ( mXFieldIndex != -1 && mYFieldIndex != -1 ) { mNumberFeatures++; // split the line on the delimiter QStringList parts; if ( mDelimiterType == "regexp" ) parts = line.split( mDelimiterRegexp ); else parts = line.split( mDelimiter ); // Skip malformed lines silently. Report line number with nextFeature() if ( attributeFields.size() != parts.size() ) { continue; } // Get the x and y values, first checking to make sure they // aren't null. QString sX = parts[mXFieldIndex]; QString sY = parts[mYFieldIndex]; bool xOk = true; bool yOk = true; double x = sX.toDouble( &xOk ); double y = sY.toDouble( &yOk ); if ( xOk && yOk ) { if ( !firstPoint ) { mExtent.combineExtentWith( x, y ); } else { // Extent for the first point is just the first point mExtent.set( x, y, x, y ); firstPoint = false; } } int i = 0; for ( QStringList::iterator it = parts.begin(); it != parts.end(); ++it, ++i ) { // try to convert attribute values to integer and double if ( couldBeInt[i] ) { it->toInt( &couldBeInt[i] ); } if ( couldBeDouble[i] ) { it->toDouble( &couldBeDouble[i] ); } } } } // now it's time to decide the types for the fields for ( QgsFieldMap::iterator it = attributeFields.begin(); it != attributeFields.end(); ++it ) { if ( couldBeInt[it.key()] ) { it->setType( QVariant::Int ); it->setTypeName( "integer" ); } else if ( couldBeDouble[it.key()] ) { it->setType( QVariant::Double ); it->setTypeName( "double" ); } } if ( mXFieldIndex != -1 && mYFieldIndex != -1 ) { QgsDebugMsg( "Data store is valid" ); QgsDebugMsg( "Number of features " + QString::number( mNumberFeatures ) ); QgsDebugMsg( "Extents " + mExtent.toString() ); mValid = true; } else { QgsDebugMsg( "Data store is invalid. Specified x,y fields do not match those in the database" ); } QgsDebugMsg( "Done checking validity" ); }