GenericXYParser

GenericXYParser is the catch-all importer for two-column XY data files. It accepts CSV, TSV, space-delimited, and similar plain-text formats with the suffixes .csv, .tsv, .txt, .dat, .data, .xy, and .tab, returning the parsed point list as a GenericXYData value. The parser drives the Generic XY overlay type described in Overlays, where the user loads an arbitrary external trace and overlays it on the FT plot.

Auto-detection covers three things in turn: the delimiter (comma, tab, semicolon, or whitespace), the number of leading comment/header lines (using #, !, and % as comment markers), and whether the first non-comment line is a textual column-header row. The X and Y columns default to indices 0 and 1 and can be overridden in the GenericXYParser::ParseSettings argument that parseWithSettings() accepts. Lines that fail to parse as numbers are silently skipped so one malformed row does not abort the import.

The two helper structs define the import dialog’s contract with the parser. GenericXYParser::ParseSettings carries the resolved delimiter, header-line count, X/Y column indices, column names, and a flag indicating whether a column-header row is present; the dialog can edit it before calling parseWithSettings. GenericXYParser::ParsePreview is the result of generatePreview() and combines the auto-detected settings with a short slice of sample lines, a small set of parsed points for display, the total data-line count, and an error message when detection fails. GenericXYOverlayWidget uses the preview to render the import dialog’s sample table before the user commits to the full parse.

A per-instance file-analysis cache keyed by (filePath, lastModified) lets the canParse, generatePreview, and parseWithSettings paths share a single detection result so a single file does not get sniffed three separate times during one overlay-import session.

The parser is registered with FileParserRegistry during application startup. GenericXYParser derives directly from FileParser rather than from CatalogParser because its output is plain (x, y) data, not transitions with quantum numbers; consumers that need a generic XY parser select it through the registry’s templated FileParserRegistry::findParserOfType() helper.

API Reference

class GenericXYParser : public FileParser

Parser for generic two-column XY text files.

Public Functions

GenericXYParser()
virtual bool canParse(const QString &filePath, const QVariantMap &hints = QVariantMap()) const override

Recognize a file by suffix and a structural sniff of the first lines.

virtual QString formatName() const override

Returns "GenericXY".

virtual QString formatDescription() const override

Returns a one-line description of the format.

virtual QStringList fileExtensions() const override

Returns the list of recognized suffixes.

GenericXYData parse(const QString &filePath, const QVariantMap &hints = QVariantMap()) const

Parse a recognized file using auto-detected settings.

Equivalent to calling :cpp:func:parseWithSettings with the result of :cpp:func:autoDetectSettings.

ParseSettings autoDetectSettings(const QString &filePath) const

Sniff filePath and return the inferred parse settings.

ParsePreview generatePreview(const QString &filePath, const ParseSettings &settings) const

Generate a preview using the supplied settings.

ParsePreview generatePreview(const QString &filePath) const

Generate a preview using auto-detected settings.

GenericXYData parseWithSettings(const QString &filePath, const ParseSettings &settings) const

Parse a recognized file with explicit settings.

Overrides any auto-detection and uses the supplied :cpp:struct:ParseSettings verbatim.

inline QString detectDelimiterPublic(const QStringList &lines) const

Test-only delimiter-detection accessor.

inline int detectHeaderLinesPublic(const QStringList &lines) const

Test-only header-line-count accessor.

inline bool detectColumnHeadersPublic(const QString &line, const QString &delimiter) const

Test-only column-header detection accessor.

inline QStringList readSampleLinesPublic(const QString &filePath, int maxLines = 20) const

Test-only sample-line reader.

Private Functions

QString detectDelimiter(const QStringList &lines) const

Score the candidate delimiters and return the winner.

int detectHeaderLines(const QStringList &lines) const

Count consecutive comment/header lines at the top of the file.

bool detectColumnHeaders(const QString &line, const QString &delimiter) const

Decide whether line looks like a textual column-header row.

QStringList generateColumnNames(int numColumns) const

Generate placeholder column names Col1, Col2, …

QStringList parseColumnHeaders(const QString &line, const QString &delimiter) const

Split a header row into cleaned column names.

QPointF parseDataLine(const QString &line, const QString &delimiter, int xCol, int yCol) const

Parse one data line into an (x, y) point.

Returns:

Valid QPointF on success; an invalid point on failure.

bool isCommentLine(const QString &line) const

Test whether line begins with one of the recognized comment characters (#, !, %).

QString cleanSemicolons(const QString &input) const

Strip embedded semicolons so the result can round-trip safely through Blackchirp’s CSV storage.

QStringList readSampleLines(const QString &filePath, int maxLines = 20) const

Read the first maxLines lines of filePath.

void calculateExpectedNumericColumns() const

Recompute and cache the expected numeric-column count.

int detectHeaderLinesUsingDelimiter() const

Header-line count derived from the cached delimiter.

bool analyzeFile(const QString &filePath, const QVariantMap &hints = QVariantMap()) const

Run a full file analysis, populating d_cachedAnalysis.

Returns:

true when the file is recognized as a parseable XY file.

Private Members

mutable FileAnalysis d_cachedAnalysis

Cached analysis result; invalidated when the file’s mtime changes.

struct FileAnalysis

Cached file analysis used by analyzeFile() so the preview, canParse, and full-parse paths share one detection result per (filePath, lastModified) pair.

Public Members

QString filePath

File the cached result describes.

QDateTime lastModified

Mtime captured when the result was produced.

QStringList allLines

Full file contents.

QStringList dataLines

Subset of allLines past the header.

ParseSettings settings

Auto-detected settings.

int expectedNumericColumns = 0

Number of columns that parse as numbers in the data section.

int expectedTotalColumns = 0

Total column count, including non-numeric columns.

bool isValid = false

true when the cached analysis is current and usable.

struct ParsePreview

Result of a parse-preview pass.

Combines the auto-detected settings, a small sample of raw lines, a short slice of parsed points, the total data-line count, and a success flag with optional error message. Used by GenericXYOverlayWidget to show the user what the importer will produce before they commit to the full parse.

Public Members

QStringList sampleLines

First lines of the file, in source order.

ParseSettings detectedSettings

Settings produced by auto-detection.

QVector<QPointF> previewData

Up to a handful of parsed points for display.

int totalDataLines = 0

Total number of data lines in the file.

QString errorMessage

Detection error, when success is false.

bool success = false

true when auto-detection produced a usable result.

struct ParseSettings

Resolved parse parameters for a single file.

The defaults match a comma-delimited file with no header rows and X/Y in the first two columns. autoDetectSettings() populates these fields from the file contents; the overlay dialog can then edit them and pass the result back to parseWithSettings().

Public Members

QString delimiter = ","

Delimiter string used between fields.

int headerLines = 0

Number of leading comment/header lines to skip.

int xColumn = 0

Zero-based index of the X column.

int yColumn = 1

Zero-based index of the Y column.

QStringList columnNames

Resolved column names (auto-generated when no header row is present).

bool hasColumnHeaders = false

true when the first data line is a text header row.