diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | afdnotebook.cc | 52 | ||||
-rw-r--r-- | afdnotebook.h | 9 | ||||
-rw-r--r-- | mainwindow.cc | 47 | ||||
-rw-r--r-- | mainwindow.h | 2 | ||||
-rw-r--r-- | notebookview.cc | 4 | ||||
-rw-r--r-- | notebookview.h | 2 | ||||
-rw-r--r-- | stftxtexport.cc | 39 | ||||
-rw-r--r-- | stftxtexport.h | 2 |
9 files changed, 97 insertions, 61 deletions
@@ -3,3 +3,4 @@ .qmake.stash Makefile /build +/build-* diff --git a/afdnotebook.cc b/afdnotebook.cc index 58ae359..8b90619 100644 --- a/afdnotebook.cc +++ b/afdnotebook.cc @@ -170,7 +170,7 @@ QList<int> AfdNotebook::pagesWithStrokes(const QString &penSerial) const { if (_penData.contains(penSerial)) { const PenData &data = _penData[penSerial]; - return data.strokes.uniqueKeys(); + return data.strokes.keys(); } else { return QList<int>(); } @@ -182,36 +182,16 @@ QStringList AfdNotebook::strokeFiles(const QString &penSerial, int page) const if (!_penData.contains(penSerial)) return l; const PenData &data = _penData[penSerial]; - QMultiMap<int, StrokeData>::const_iterator it = data.strokes.find(page); - while (it != data.strokes.end() && it.key() == page) { - const StrokeData &stroke = it.value(); - l.append(_dir.filePath(stroke.file)); - ++it; - } - - return l; -} - -bool AfdNotebook::readStrokes(const QString &penSerial, int page, StfReader::StrokeHandler *handler) -{ - if (!_penData.contains(penSerial)) return true; - - StfReader stf; - stf.setStrokeHandler(handler); - - const PenData &data = _penData[penSerial]; - QMultiMap<int, StrokeData>::const_iterator it = data.strokes.find(page); - while (it != data.strokes.end() && it.key() == page) { - const StrokeData &stroke = it.value(); - qDebug() << "Reading strokes from" << stroke.file; - if (!stf.parse(_dir.filePath(stroke.file))) { - qWarning() << "Could not parse stroke file" << stroke.file; - return false; + auto it = data.strokes.find(page); + if (it != data.strokes.end()) { + const QList<StrokeData>& strokes = it.value(); + l.reserve(strokes.size()); + foreach (const StrokeData &stroke, strokes) { + l.append(_dir.filePath(stroke.file)); } - ++it; } - return true; + return l; } QMap<QString, QString> AfdNotebook::parsePropertyList(QIODevice *dev) @@ -355,6 +335,8 @@ bool AfdNotebook::findPenData() QDir penDir(pageDir.filePath(penName)); if (!penDir.exists()) continue; + PenData& penData = _penData[penName]; + QStringList strokeFiles = penDir.entryList(QStringList("*.stf"), QDir::Files); foreach (const QString &strokeFile, strokeFiles) { qDebug() << " stroke data" << strokeFile; @@ -378,7 +360,19 @@ bool AfdNotebook::findPenData() qDebug() << " from" << stroke.begin << "to" << stroke.end; - _penData[penName].strokes.insert(pageNum, stroke); + penData.strokes[pageNum].append(stroke); + } + + // Sort all the stroke files in each page by starting time + auto it = penData.strokes.begin(); + while (it != penData.strokes.end()) { + QList<StrokeData> &strokes = *it; + if (!strokes.isEmpty()) { + std::sort(strokes.begin(), strokes.end(), StrokeData::CompareByBeginTime); + ++it; + } else { + it = penData.strokes.erase(it); + } } } } diff --git a/afdnotebook.h b/afdnotebook.h index 645d002..9f8886d 100644 --- a/afdnotebook.h +++ b/afdnotebook.h @@ -56,8 +56,6 @@ public: QStringList strokeFiles(const QString &penSerial, int page) const; - bool readStrokes(const QString &penSerial, int page, StfReader::StrokeHandler *handler); - private: struct Gfx { QString basename; @@ -72,10 +70,15 @@ private: QString file; quint64 begin; quint64 end; + + static bool CompareByBeginTime(const StrokeData &a, const StrokeData &b) { + return a.begin < b.begin; + } }; struct PenData { - QMultiMap<int, StrokeData> strokes; + // pageNum -> List of Strokes + QMap<int, QList<StrokeData>> strokes; }; private: diff --git a/mainwindow.cc b/mainwindow.cc index dae4ae6..e7a73fa 100644 --- a/mainwindow.cc +++ b/mainwindow.cc @@ -142,7 +142,7 @@ void MainWindow::exportCurrentPageAsSvg(const QString &file) painter.end(); } -void MainWindow::exportCurrentPageAsStrokeListTxt(const QString &file) +void MainWindow::exportCurrentPageAsTXYP(const QString &file, bool relativeTime) { QFile f(file); if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) { @@ -150,7 +150,7 @@ void MainWindow::exportCurrentPageAsStrokeListTxt(const QString &file) tr("Could not export current page to '%s'").arg(file)); return; } - ui->notebookView->exportPageAsStrokeList(&f, ui->notebookView->curPage()); + ui->notebookView->exportPageAsTXYP(&f, ui->notebookView->curPage(), relativeTime); f.close(); } @@ -310,13 +310,21 @@ void MainWindow::handlePenSyncFailed(const QString &penName) void MainWindow::handleExport() { + QSettings settings; + if (_curNotebookName == PAPER_REPLAY) { + settings.beginGroup("export"); + settings.beginGroup("audio"); + + QString dir = settings.value("dir").toString(); + QStringList filters; filters << tr("Current audio as AAC (*.aac)"); QString filter; - QString fileName = QFileDialog::getSaveFileName(this, tr("Export page"), QString(), + QString fileName = QFileDialog::getSaveFileName(this, tr("Export page"), dir, filters.join(";;"), &filter); if (fileName.isEmpty()) return; + int filterIndex = filters.indexOf(filter); switch (filterIndex) { case 0: @@ -325,18 +333,31 @@ void MainWindow::handleExport() } exportCurrentPaperReplayAsAac(fileName); break; + default: + Q_UNREACHABLE(); } + + QFileInfo file(fileName); + settings.setValue("dir", file.absolutePath()); } else if (!_curNotebookName.isEmpty()) { + settings.beginGroup("export"); + settings.beginGroup("page"); + + QString dir = settings.value("dir").toString(); + QStringList filters; filters << tr("Current page as PNG image (*.png)") << tr("Current page as SVG image (*.svg)") - << tr("Current page as stroke list text file (*.txt)") + << tr("Current page as TXYP (*.txyp)") << tr("Current audio as AAC (*.aac)"); - QString filter; - QString fileName = QFileDialog::getSaveFileName(this, tr("Export page"), QString(), + int filterIndex = settings.value("filetype").toInt(); + QString filter = filters.value(filterIndex); + + QString fileName = QFileDialog::getSaveFileName(this, tr("Export page"), dir, filters.join(";;"), &filter); if (fileName.isEmpty()) return; - int filterIndex = filters.indexOf(filter); + + filterIndex = filters.indexOf(filter); switch (filterIndex) { case 0: if (!fileName.endsWith(".png", Qt::CaseInsensitive)) { @@ -351,10 +372,10 @@ void MainWindow::handleExport() exportCurrentPageAsSvg(fileName); break; case 2: - if (!fileName.endsWith(".txt", Qt::CaseInsensitive)) { - fileName.append(".txt"); + if (!fileName.endsWith(".txyp", Qt::CaseInsensitive)) { + fileName.append(".txyp"); } - exportCurrentPageAsStrokeListTxt(fileName); + exportCurrentPageAsTXYP(fileName, settings.value("txyp_relative_t", true).toBool()); break; case 3: if (!fileName.endsWith(".aac", Qt::CaseInsensitive)) { @@ -362,7 +383,13 @@ void MainWindow::handleExport() } exportCurrentPaperReplayAsAac(fileName); break; + default: + Q_UNREACHABLE(); } + + QFileInfo file(fileName); + settings.setValue("dir", file.absolutePath()); + settings.setValue("filetype", filterIndex); } else { QMessageBox::warning(this, tr("Export page"), tr("Open a notebook or audio in order to export")); diff --git a/mainwindow.h b/mainwindow.h index c7a871f..dc06243 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -45,7 +45,7 @@ public slots: void exportCurrentPageAsPng(const QString &file); void exportCurrentPageAsSvg(const QString &file); - void exportCurrentPageAsStrokeListTxt(const QString &file); + void exportCurrentPageAsTXYP(const QString &file, bool relativeTime); void exportCurrentPaperReplayAsAac(const QString &file); private slots: diff --git a/notebookview.cc b/notebookview.cc index 505a337..06d035b 100644 --- a/notebookview.cc +++ b/notebookview.cc @@ -150,10 +150,10 @@ void NotebookView::renderPage(QPainter *painter, int pageNum, const QRectF &targ scene.render(painter, target, source, Qt::KeepAspectRatio); } -void NotebookView::exportPageAsStrokeList(QIODevice *device, int pageNum) +void NotebookView::exportPageAsTXYP(QIODevice *device, int pageNum, bool relativeTime) { StfTxtExport writer(_nb); - writer.exportStrokeList(device, pageNum); + writer.exportToTXYP(device, pageNum, relativeTime); } void NotebookView::requestPaperReplay(const QString &file, qint64 time) diff --git a/notebookview.h b/notebookview.h index c1e425d..cced421 100644 --- a/notebookview.h +++ b/notebookview.h @@ -59,7 +59,7 @@ public: QImage exportPageAsImage(int pageNum) const; void renderPage(QPainter *painter, int pageNum, const QRectF &target = QRectF(), const QRectF &source = QRectF()) const; - void exportPageAsStrokeList(QIODevice *device, int pageNum); + void exportPageAsTXYP(QIODevice *device, int pageNum, bool relativeTime); void requestPaperReplay(const QString &file, qint64 time); diff --git a/stftxtexport.cc b/stftxtexport.cc index 0163848..e6793b2 100644 --- a/stftxtexport.cc +++ b/stftxtexport.cc @@ -20,32 +20,42 @@ #include <QtCore/QTextStream> #include "stftxtexport.h" -class StfToTxtStrokeList : public StfReader::StrokeHandler { +class StfToTXYP : public StfReader::StrokeHandler { QTextStream _out; QPoint _lastP; - qint64 _lastTime; + int _lastForce; + qint64 _startTime; + bool _relativeTime; public: - StfToTxtStrokeList(QIODevice *out) - : _out(out) { + StfToTXYP(QIODevice *out, bool relativeTime) + : _out(out), _lastP(), _lastForce(0), _startTime(0), _relativeTime(relativeTime) { + _out << "T\tX\tY\tP\n"; } bool startStroke(const QPoint& p, int force, qint64 time) { - _out << time << " penDown " << p.x() << ' ' << p.y() << ' ' << force << '\n'; + if (_relativeTime && _startTime == 0) { + _startTime = time; + } + _out << (time - _startTime) << '\t' << p.x() << '\t' << p.y() << '\t' << force << '\n'; _lastP = p; - _lastTime = time; + _lastForce = force; return true; } bool strokePoint(const QPoint& p, int force, qint64 time) { - _out << time << " penMove " << p.x() << ' ' << p.y() << ' ' << force << '\n'; + _out << (time - _startTime) << '\t' << p.x() << '\t' << p.y() << '\t' << force << '\n'; _lastP = p; - _lastTime = time; + _lastForce = force; return true; } bool endStroke(qint64 time) { - _out << time << " penUp " << _lastP.x() << ' ' << _lastP.y() << ' ' << 0 << '\n'; + // Ensure there is a entry with force=0, in case the pen didn't provide it + if (_lastForce != 0) { + _out << (time - _startTime) << '\t' << _lastP.x() << '\t' << _lastP.y() << '\t' << 0 << '\n'; + _lastForce = 0; + } return true; } }; @@ -55,11 +65,15 @@ StfTxtExport::StfTxtExport(AfdNotebook *nb) { } -void StfTxtExport::exportStrokeList(QIODevice *out, int pageNum) +void StfTxtExport::exportToTXYP(QIODevice *out, int pageNum, bool relativeTime) { QStringList pens = _nb->penSerials(); if (pens.isEmpty()) return; + StfToTXYP h(out, relativeTime); + StfReader r; + r.setStrokeHandler(&h); + QStringList strokeFiles = _nb->strokeFiles(pens.first(), pageNum); foreach (const QString &strokeFile, strokeFiles) { QFile in(strokeFile); @@ -68,11 +82,8 @@ void StfTxtExport::exportStrokeList(QIODevice *out, int pageNum) continue; } - StfToTxtStrokeList h(out); - StfReader r; - r.setStrokeHandler(&h); if (!r.parse(&in)) { - qWarning() << "Could not open parse file:" << strokeFile; + qWarning() << "Could not parse stroke file:" << strokeFile; continue; } } diff --git a/stftxtexport.h b/stftxtexport.h index 90a83e0..b9ca821 100644 --- a/stftxtexport.h +++ b/stftxtexport.h @@ -26,7 +26,7 @@ class StfTxtExport public: explicit StfTxtExport(AfdNotebook *nb); - void exportStrokeList(QIODevice *out, int pageNum); + void exportToTXYP(QIODevice *out, int pageNum, bool relativeTime); private: AfdNotebook *_nb; |