aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--afdnotebook.cc52
-rw-r--r--afdnotebook.h9
-rw-r--r--mainwindow.cc47
-rw-r--r--mainwindow.h2
-rw-r--r--notebookview.cc4
-rw-r--r--notebookview.h2
-rw-r--r--stftxtexport.cc39
-rw-r--r--stftxtexport.h2
9 files changed, 97 insertions, 61 deletions
diff --git a/.gitignore b/.gitignore
index 6bfbf75..44a5db4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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;