Chris@148: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@148: Chris@148: /* Chris@148: Sonic Visualiser Chris@148: An audio file viewer and annotation editor. Chris@148: Centre for Digital Music, Queen Mary, University of London. Chris@148: This file copyright 2006 Chris Cannam. Chris@148: Chris@148: This program is free software; you can redistribute it and/or Chris@148: modify it under the terms of the GNU General Public License as Chris@148: published by the Free Software Foundation; either version 2 of the Chris@148: License, or (at your option) any later version. See the file Chris@148: COPYING included with this distribution for more information. Chris@148: */ Chris@148: Chris@148: #include "CSVFileWriter.h" dev@1436: #include "CSVStreamWriter.h" Chris@148: Chris@150: #include "model/Model.h" Chris@148: #include "model/SparseOneDimensionalModel.h" Chris@148: #include "model/SparseTimeValueModel.h" Chris@148: #include "model/NoteModel.h" Chris@148: #include "model/TextModel.h" Chris@148: Chris@675: #include "base/TempWriteFile.h" Chris@675: #include "base/Exceptions.h" Chris@839: #include "base/Selection.h" Chris@675: Chris@148: #include Chris@148: #include dev@1436: #include dev@1442: #include Chris@148: Chris@1063: CSVFileWriter::CSVFileWriter(QString path, Chris@1063: Model *model, Chris@1063: QString delimiter, Chris@1063: DataExportOptions options) : Chris@148: m_path(path), Chris@148: m_model(model), Chris@148: m_error(""), Chris@1063: m_delimiter(delimiter), Chris@1063: m_options(options) Chris@148: { Chris@148: } Chris@148: Chris@148: CSVFileWriter::~CSVFileWriter() Chris@148: { Chris@148: } Chris@148: Chris@148: bool Chris@148: CSVFileWriter::isOK() const Chris@148: { Chris@148: return m_error == ""; Chris@148: } Chris@148: Chris@148: QString Chris@148: CSVFileWriter::getError() const Chris@148: { Chris@148: return m_error; Chris@148: } Chris@148: Chris@148: void Chris@148: CSVFileWriter::write() Chris@148: { dev@1436: Selection all { dev@1436: m_model->getStartFrame(), dev@1436: m_model->getEndFrame() dev@1436: }; dev@1436: MultiSelection selections; dev@1436: selections.addSelection(all); dev@1436: writeSelection(&selections); Chris@148: } Chris@148: Chris@839: void Chris@839: CSVFileWriter::writeSelection(MultiSelection *selection) Chris@839: { Chris@839: try { Chris@839: TempWriteFile temp(m_path); Chris@148: Chris@839: QFile file(temp.getTemporaryFilename()); Chris@839: if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { Chris@839: m_error = tr("Failed to open file %1 for writing") Chris@839: .arg(temp.getTemporaryFilename()); Chris@839: return; Chris@839: } Chris@839: Chris@839: QTextStream out(&file); Chris@839: dev@1436: bool completed = false; dev@1436: dev@1442: const auto nFramesToWrite = std::accumulate( dev@1442: selection->getSelections().begin(), dev@1442: selection->getSelections().end(), dev@1442: 0, dev@1442: [](sv_frame_t acc, const Selection& current) -> sv_frame_t { dev@1442: return acc + (current.getEndFrame() - current.getStartFrame()); dev@1442: } dev@1442: ); dev@1442: dev@1442: sv_frame_t nFramesWritten = 0; dev@1442: const auto createProgressCalculator = [ dev@1442: &nFramesWritten, dev@1442: &nFramesToWrite dev@1442: ](sv_frame_t nFramesToWriteForSelection) { dev@1442: const auto nFramesWrittenAtSelectionStart = nFramesWritten; dev@1442: nFramesWritten += nFramesToWriteForSelection; dev@1442: return [ dev@1442: &nFramesWritten, dev@1442: &nFramesToWrite, dev@1442: nFramesWrittenAtSelectionStart dev@1442: ] (sv_frame_t nFramesWrittenForSelection) { dev@1442: const auto nFramesWrittenSoFar = ( dev@1442: nFramesWrittenAtSelectionStart + nFramesWrittenForSelection dev@1442: ); dev@1442: return 100 * nFramesWrittenSoFar / nFramesToWrite; dev@1442: }; dev@1442: }; dev@1442: dev@1436: for (const auto& bounds : selection->getSelections()) { dev@1443: completed = CSVStreamWriter::writeInChunks( dev@1436: out, dev@1436: *m_model, dev@1436: bounds, dev@1436: m_reporter, dev@1436: m_delimiter, dev@1442: m_options, dev@1442: 16384, dev@1442: createProgressCalculator dev@1436: ); dev@1436: if (!completed) { dev@1436: break; dev@1436: } Chris@839: } Chris@839: Chris@839: file.close(); dev@1436: if (completed) { dev@1436: temp.moveToTarget(); dev@1436: } Chris@839: Chris@839: } catch (FileOperationFailed &f) { Chris@839: m_error = f.what(); dev@1436: } catch (const std::exception &e) { // ProgressReporter could throw dev@1436: m_error = e.what(); Chris@839: } Chris@839: }