annotate data/fileio/CSVFileWriter.cpp @ 1442:3c3eedc2fad8 streaming-csv-writer

Implement progress reporting for multi-selection. Needs refactoring.
author Lucas Thompson <dev@lucas.im>
date Tue, 17 Apr 2018 10:03:50 +0100
parents 09c2ba31a711
children cdb316c6a151
rev   line source
Chris@148 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@148 2
Chris@148 3 /*
Chris@148 4 Sonic Visualiser
Chris@148 5 An audio file viewer and annotation editor.
Chris@148 6 Centre for Digital Music, Queen Mary, University of London.
Chris@148 7 This file copyright 2006 Chris Cannam.
Chris@148 8
Chris@148 9 This program is free software; you can redistribute it and/or
Chris@148 10 modify it under the terms of the GNU General Public License as
Chris@148 11 published by the Free Software Foundation; either version 2 of the
Chris@148 12 License, or (at your option) any later version. See the file
Chris@148 13 COPYING included with this distribution for more information.
Chris@148 14 */
Chris@148 15
Chris@148 16 #include "CSVFileWriter.h"
dev@1436 17 #include "CSVStreamWriter.h"
Chris@148 18
Chris@150 19 #include "model/Model.h"
Chris@148 20 #include "model/SparseOneDimensionalModel.h"
Chris@148 21 #include "model/SparseTimeValueModel.h"
Chris@148 22 #include "model/NoteModel.h"
Chris@148 23 #include "model/TextModel.h"
Chris@148 24
Chris@675 25 #include "base/TempWriteFile.h"
Chris@675 26 #include "base/Exceptions.h"
Chris@839 27 #include "base/Selection.h"
Chris@675 28
Chris@148 29 #include <QFile>
Chris@148 30 #include <QTextStream>
dev@1436 31 #include <exception>
dev@1442 32 #include <numeric>
Chris@148 33
Chris@1063 34 CSVFileWriter::CSVFileWriter(QString path,
Chris@1063 35 Model *model,
Chris@1063 36 QString delimiter,
Chris@1063 37 DataExportOptions options) :
Chris@148 38 m_path(path),
Chris@148 39 m_model(model),
Chris@148 40 m_error(""),
Chris@1063 41 m_delimiter(delimiter),
Chris@1063 42 m_options(options)
Chris@148 43 {
Chris@148 44 }
Chris@148 45
Chris@148 46 CSVFileWriter::~CSVFileWriter()
Chris@148 47 {
Chris@148 48 }
Chris@148 49
Chris@148 50 bool
Chris@148 51 CSVFileWriter::isOK() const
Chris@148 52 {
Chris@148 53 return m_error == "";
Chris@148 54 }
Chris@148 55
Chris@148 56 QString
Chris@148 57 CSVFileWriter::getError() const
Chris@148 58 {
Chris@148 59 return m_error;
Chris@148 60 }
Chris@148 61
Chris@148 62 void
Chris@148 63 CSVFileWriter::write()
Chris@148 64 {
dev@1436 65 Selection all {
dev@1436 66 m_model->getStartFrame(),
dev@1436 67 m_model->getEndFrame()
dev@1436 68 };
dev@1436 69 MultiSelection selections;
dev@1436 70 selections.addSelection(all);
dev@1436 71 writeSelection(&selections);
Chris@148 72 }
Chris@148 73
Chris@839 74 void
Chris@839 75 CSVFileWriter::writeSelection(MultiSelection *selection)
Chris@839 76 {
Chris@839 77 try {
Chris@839 78 TempWriteFile temp(m_path);
Chris@148 79
Chris@839 80 QFile file(temp.getTemporaryFilename());
Chris@839 81 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
Chris@839 82 m_error = tr("Failed to open file %1 for writing")
Chris@839 83 .arg(temp.getTemporaryFilename());
Chris@839 84 return;
Chris@839 85 }
Chris@839 86
Chris@839 87 QTextStream out(&file);
Chris@839 88
dev@1436 89 bool completed = false;
dev@1436 90
dev@1442 91 const auto nFramesToWrite = std::accumulate(
dev@1442 92 selection->getSelections().begin(),
dev@1442 93 selection->getSelections().end(),
dev@1442 94 0,
dev@1442 95 [](sv_frame_t acc, const Selection& current) -> sv_frame_t {
dev@1442 96 return acc + (current.getEndFrame() - current.getStartFrame());
dev@1442 97 }
dev@1442 98 );
dev@1442 99
dev@1442 100 sv_frame_t nFramesWritten = 0;
dev@1442 101 const auto createProgressCalculator = [
dev@1442 102 &nFramesWritten,
dev@1442 103 &nFramesToWrite
dev@1442 104 ](sv_frame_t nFramesToWriteForSelection) {
dev@1442 105 const auto nFramesWrittenAtSelectionStart = nFramesWritten;
dev@1442 106 nFramesWritten += nFramesToWriteForSelection;
dev@1442 107 return [
dev@1442 108 &nFramesWritten,
dev@1442 109 &nFramesToWrite,
dev@1442 110 nFramesWrittenAtSelectionStart
dev@1442 111 ] (sv_frame_t nFramesWrittenForSelection) {
dev@1442 112 const auto nFramesWrittenSoFar = (
dev@1442 113 nFramesWrittenAtSelectionStart + nFramesWrittenForSelection
dev@1442 114 );
dev@1442 115 return 100 * nFramesWrittenSoFar / nFramesToWrite;
dev@1442 116 };
dev@1442 117 };
dev@1442 118
dev@1436 119 for (const auto& bounds : selection->getSelections()) {
dev@1442 120 completed = CSV::writeToStreamInChunks(
dev@1436 121 out,
dev@1436 122 *m_model,
dev@1436 123 bounds,
dev@1436 124 m_reporter,
dev@1436 125 m_delimiter,
dev@1442 126 m_options,
dev@1442 127 16384,
dev@1442 128 createProgressCalculator
dev@1436 129 );
dev@1436 130 if (!completed) {
dev@1436 131 break;
dev@1436 132 }
Chris@839 133 }
Chris@839 134
Chris@839 135 file.close();
dev@1436 136 if (completed) {
dev@1436 137 temp.moveToTarget();
dev@1436 138 }
Chris@839 139
Chris@839 140 } catch (FileOperationFailed &f) {
Chris@839 141 m_error = f.what();
dev@1436 142 } catch (const std::exception &e) { // ProgressReporter could throw
dev@1436 143 m_error = e.what();
Chris@839 144 }
Chris@839 145 }