* @brief Creates a new CSV file and writes the header row from the frame schema. */
| 129 | * @brief Creates a new CSV file and writes the header row from the frame schema. |
| 130 | */ |
| 131 | void CSV::ExportWorker::createCsvFile(const DataModel::Frame& frame) |
| 132 | { |
| 133 | const auto dt = QDateTime::currentDateTime(); |
| 134 | const auto fileName = dt.toString("yyyy-MM-dd_HH-mm-ss") + ".csv"; |
| 135 | |
| 136 | const auto subdir = Misc::WorkspaceManager::instance().path("CSV"); |
| 137 | QString safeTitle = frame.title; |
| 138 | safeTitle.remove(QChar('/')); |
| 139 | safeTitle.remove(QChar('\\')); |
| 140 | safeTitle.remove(QChar(':')); |
| 141 | safeTitle.remove(QChar('*')); |
| 142 | safeTitle.remove(QChar('?')); |
| 143 | safeTitle.remove(QChar('"')); |
| 144 | safeTitle.remove(QChar('<')); |
| 145 | safeTitle.remove(QChar('>')); |
| 146 | safeTitle.remove(QChar('|')); |
| 147 | safeTitle.remove(QChar('\0')); |
| 148 | safeTitle.remove(QStringLiteral("..")); |
| 149 | safeTitle = safeTitle.simplified(); |
| 150 | |
| 151 | int keepCsv = 0; |
| 152 | for (int i = safeTitle.size(); i > 0; --i) { |
| 153 | const QChar c = safeTitle.at(i - 1); |
| 154 | if (c != QChar('.') && c != QChar(' ')) { |
| 155 | keepCsv = i; |
| 156 | break; |
| 157 | } |
| 158 | } |
| 159 | safeTitle.truncate(keepCsv); |
| 160 | |
| 161 | if (safeTitle.isEmpty()) |
| 162 | safeTitle = QStringLiteral("Untitled"); |
| 163 | |
| 164 | const QString path = QString("%1/%2/").arg(subdir, safeTitle); |
| 165 | |
| 166 | QDir dir(path); |
| 167 | if (!dir.exists() && !dir.mkpath(".")) { |
| 168 | qWarning() << "Failed to create directory:" << path; |
| 169 | return; |
| 170 | } |
| 171 | |
| 172 | m_csvFile.setFileName(dir.filePath(fileName)); |
| 173 | if (!m_csvFile.open(QIODevice::WriteOnly | QIODevice::Text)) { |
| 174 | qWarning() << "Cannot open CSV file for writing:" << dir.filePath(fileName); |
| 175 | return; |
| 176 | } |
| 177 | |
| 178 | m_lastFinalValues.clear(); |
| 179 | |
| 180 | m_textStream.setDevice(&m_csvFile); |
| 181 | m_textStream.setGenerateByteOrderMark(true); |
| 182 | m_textStream.setEncoding(QStringConverter::Utf8); |
| 183 | |
| 184 | m_schema = DataModel::buildExportSchema(frame); |
| 185 | |
| 186 | m_textStream << "Elapsed (s)"; |
| 187 | for (const auto& col : m_schema.columns) { |
| 188 | auto label = QString("%1/%2").arg(col.groupTitle, col.title).simplified(); |
nothing calls this directly
no test coverage detected