aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mainwindow.cc41
-rw-r--r--mainwindow.h6
-rw-r--r--mainwindow.ui90
-rw-r--r--notebookview.cc2
-rw-r--r--paperreplay.cc37
-rw-r--r--paperreplay.h6
-rw-r--r--paperreplaymodel.cc119
-rw-r--r--paperreplaymodel.h35
-rw-r--r--scribiu.pro6
9 files changed, 323 insertions, 19 deletions
diff --git a/mainwindow.cc b/mainwindow.cc
index e269c61..dd687a2 100644
--- a/mainwindow.cc
+++ b/mainwindow.cc
@@ -8,7 +8,9 @@ MainWindow::MainWindow(QWidget *parent) :
_notebooks(new NotebookModel(this)),
_manager(new SmartpenManager(this)),
_media(new Phonon::MediaObject(this)),
- _mediaOutput(new Phonon::AudioOutput(this))
+ _mediaOutput(new Phonon::AudioOutput(this)),
+ _replay(new PaperReplay(this)),
+ _replayModel(new PaperReplayModel(_replay, this))
{
ui->setupUi(this);
ui->notebookTree->setModel(_notebooks);
@@ -16,6 +18,11 @@ MainWindow::MainWindow(QWidget *parent) :
ui->notebookTree->header()->setResizeMode(1, QHeaderView::Fixed);
ui->notebookTree->header()->setResizeMode(2, QHeaderView::Fixed);
ui->notebookTree->expandAll();
+ ui->notebookView->setVisible(false);
+ ui->paperReplayView->setModel(_replayModel);
+ ui->paperReplayView->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
+ ui->paperReplayView->horizontalHeader()->setResizeMode(1, QHeaderView::Fixed);
+ ui->paperReplayView->setVisible(false);
Phonon::createPath(_media, _mediaOutput);
ui->replaySlider->setMediaObject(_media);
ui->pauseButton->setVisible(false);
@@ -32,22 +39,38 @@ void MainWindow::closeNotebook()
{
_curPenName.clear();
_curNotebookName.clear();
+ _replay->close();
ui->notebookView->setNotebook(QString());
+ ui->notebookView->setVisible(false);
+ ui->paperReplayView->setVisible(false);
}
void MainWindow::openNotebook(const QString &pen, const QString &notebook)
{
if (_curPenName == pen && _curNotebookName == notebook) return;
+ closeNotebook();
+
_curPenName = pen;
_curNotebookName = notebook;
- QString nbDir = _notebooks->notebookDirectory(_curPenName, _curNotebookName);
+ if (_curNotebookName == PAPER_REPLAY) {
+ QString replayDir = _notebooks->paperReplayDirectory(_curPenName);
+
+ if (_replay->open(replayDir, 0)) {
+ _replayModel->refresh();
+ }
- qDebug() << "Opening notebook" << _curPenName << _curNotebookName << nbDir;
+ ui->paperReplayView->setVisible(true);
+ } else {
+ QString nbDir = _notebooks->notebookDirectory(_curPenName, _curNotebookName);
- ui->notebookView->setPaperReplay(_notebooks->paperReplayDirectory(_curPenName));
- ui->notebookView->setNotebook(nbDir);
+ qDebug() << "Opening notebook" << _curPenName << _curNotebookName << nbDir;
+
+ ui->notebookView->setPaperReplay(_notebooks->paperReplayDirectory(_curPenName));
+ ui->notebookView->setNotebook(nbDir);
+ ui->notebookView->setVisible(true);
+ }
}
void MainWindow::handleNotebookSelected(const QModelIndex &index)
@@ -56,6 +79,7 @@ void MainWindow::handleNotebookSelected(const QModelIndex &index)
closeNotebook();
return;
}
+
QModelIndex parent = index.parent();
if (!parent.isValid()) {
closeNotebook();
@@ -73,6 +97,12 @@ void MainWindow::handleCurPageChanged()
ui->pageEdit->setText(QString::number(ui->notebookView->curPage() + 1));
}
+void MainWindow::handlePaperReplaySelected(const QModelIndex &index)
+{
+ QString file = _replayModel->sessionFilename(index);
+ handlePaperReplayRequested(file, 0);
+}
+
void MainWindow::handlePaperReplayRequested(const QString &file, qint64 time)
{
QFileInfo finfo(file);
@@ -113,7 +143,6 @@ void MainWindow::handlePaperReplayPause()
void MainWindow::handleMediaStateChange(Phonon::State state)
{
- qDebug() << "Media state change:" << state;
switch (state) {
case Phonon::PlayingState:
ui->playButton->setVisible(false);
diff --git a/mainwindow.h b/mainwindow.h
index 7a8fab4..cafec49 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -5,6 +5,7 @@
#include <phonon/MediaObject>
#include <phonon/AudioOutput>
#include "notebookmodel.h"
+#include "paperreplaymodel.h"
#include "smartpenmanager.h"
namespace Ui {
@@ -26,6 +27,7 @@ public slots:
private slots:
void handleNotebookSelected(const QModelIndex &index);
void handleCurPageChanged();
+ void handlePaperReplaySelected(const QModelIndex &index);
void handlePaperReplayRequested(const QString &file, qint64 time);
void handlePaperReplayPlay();
void handlePaperReplayPause();
@@ -35,12 +37,16 @@ private:
Ui::MainWindow *ui;
NotebookModel *_notebooks;
SmartpenManager *_manager;
+
Phonon::MediaObject *_media;
Phonon::AudioOutput *_mediaOutput;
qint64 _pendingSeek;
QString _curPenName;
QString _curNotebookName;
+
+ PaperReplay *_replay;
+ PaperReplayModel *_replayModel;
};
#endif // MAINWINDOW_H
diff --git a/mainwindow.ui b/mainwindow.ui
index 4a0e1ea..1662e7f 100644
--- a/mainwindow.ui
+++ b/mainwindow.ui
@@ -183,14 +183,53 @@
</layout>
</item>
<item>
- <widget class="NotebookView" name="notebookView">
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOn</enum>
+ <layout class="QHBoxLayout" name="pane2Mid">
+ <property name="spacing">
+ <number>0</number>
</property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAlwaysOn</enum>
- </property>
- </widget>
+ <item>
+ <widget class="NotebookView" name="notebookView">
+ <property name="verticalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOn</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTableView" name="paperReplayView">
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="showGrid">
+ <bool>false</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
</item>
<item>
<layout class="QHBoxLayout" name="paperReplayTools">
@@ -224,7 +263,9 @@
<string>...</string>
</property>
<property name="icon">
- <iconset theme="media-playback-pause"/>
+ <iconset theme="media-playback-pause">
+ <normaloff/>
+ </iconset>
</property>
</widget>
</item>
@@ -444,6 +485,38 @@
</hint>
</hints>
</connection>
+ <connection>
+ <sender>paperReplayView</sender>
+ <signal>activated(QModelIndex)</signal>
+ <receiver>MainWindow</receiver>
+ <slot>handlePaperReplaySelected(QModelIndex)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>597</x>
+ <y>193</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>358</x>
+ <y>192</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>paperReplayView</sender>
+ <signal>doubleClicked(QModelIndex)</signal>
+ <receiver>MainWindow</receiver>
+ <slot>handlePaperReplaySelected(QModelIndex)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>597</x>
+ <y>193</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>358</x>
+ <y>192</y>
+ </hint>
+ </hints>
+ </connection>
</connections>
<slots>
<slot>handleNotebookSelected(QModelIndex)</slot>
@@ -452,5 +525,6 @@
<slot>handlePaperReplayRequested(QString,qint64)</slot>
<slot>handlePaperReplayPlay()</slot>
<slot>handlePaperReplayPause()</slot>
+ <slot>handlePaperReplaySelected(QModelIndex)</slot>
</slots>
</ui>
diff --git a/notebookview.cc b/notebookview.cc
index 9553451..2bca4f7 100644
--- a/notebookview.cc
+++ b/notebookview.cc
@@ -163,7 +163,7 @@ bool NotebookView::createPages()
if (pens.isEmpty()) return false;
// Failure to open paperreplay data is not fatal
- bool haveReplay = _replay->open(_replayPath, pens[0], _nb->guid());
+ bool haveReplay = _replay->open(_replayPath, _nb->guid());
QList<int> pagesWithStrokes = _nb->pagesWithStrokes(pens.first());
Q_ASSERT(_pages.isEmpty());
diff --git a/paperreplay.cc b/paperreplay.cc
index e0e654e..5baeac7 100644
--- a/paperreplay.cc
+++ b/paperreplay.cc
@@ -17,6 +17,17 @@ bool readUtfString(QDataStream &stream, QString &s)
s = QString::fromUtf8(buffer);
return true;
}
+
+QString findPenSerial(const QString &path)
+{
+ QDir dir(path + "/userdata");
+ QStringList entries = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
+ if (entries.isEmpty()) {
+ return QString();
+ } else {
+ return entries.first();
+ }
+}
}
PaperReplay::PaperReplay(QObject *parent) :
@@ -47,6 +58,11 @@ quint64 PaperReplay::Session::id() const
return d ? d->id : 0;
}
+QString PaperReplay::Session::name() const
+{
+ return d->name;
+}
+
QString PaperReplay::Session::fileName() const
{
return d->file;
@@ -62,6 +78,11 @@ qint64 PaperReplay::Session::endTime() const
return d->end;
}
+bool PaperReplay::Session::startTimeLess(const Session &a, const Session &b)
+{
+ return a.d->start < b.d->start;
+}
+
PaperReplay::SessionList::SessionList()
{
}
@@ -90,8 +111,14 @@ QList<PaperReplay::Session> PaperReplay::SessionList::sessionsDuringTime(qint64
return sessions;
}
-bool PaperReplay::open(const QString &path, const QString &penSerial, quint64 notebookGuid)
+bool PaperReplay::open(const QString &path, quint64 notebookGuid)
{
+ QString penSerial = findPenSerial(path);
+ if (penSerial.isEmpty()) {
+ qDebug() << "Cannot open paper replay:" << path << "does not contain any pen data";
+ return false;
+ }
+
_dir.setPath(path + QString("/userdata/%1/Paper Replay/99/%2/sessions")
.arg(penSerial)
.arg(qulonglong(notebookGuid), notebookGuid == 0 ? 1 : 16, 16, QLatin1Char('0')));
@@ -123,6 +150,8 @@ bool PaperReplay::open(const QString &path, const QString &penSerial, quint64 no
session.d->file = sessionDir.filePath(session.d->file);
}
+ _sessions.insert(sessionId, session);
+
foreach (quint64 page, session.d->pages) {
_byPageTime[page].insert(session.d->start, session);
}
@@ -133,9 +162,15 @@ bool PaperReplay::open(const QString &path, const QString &penSerial, quint64 no
void PaperReplay::close()
{
_byPageTime.clear();
+ _sessions.clear();
_dir.setPath(QString());
}
+QList<PaperReplay::Session> PaperReplay::sessions() const
+{
+ return _sessions.values();
+}
+
PaperReplay::SessionList PaperReplay::sessions(quint64 pageAddress) const
{
return SessionList(_byPageTime[pageAddress]);
diff --git a/paperreplay.h b/paperreplay.h
index c9eb6f2..a81e8a4 100644
--- a/paperreplay.h
+++ b/paperreplay.h
@@ -41,6 +41,8 @@ public:
QString fileName() const;
+ static bool startTimeLess(const Session &a, const Session &b);
+
private:
Session(quint64 id);
QSharedDataPointer<SessionData> d;
@@ -63,9 +65,10 @@ public:
friend class PaperReplay;
};
- bool open(const QString &path, const QString &penSerial, quint64 notebookGuid);
+ bool open(const QString &path, quint64 notebookGuid = 0);
void close();
+ QList<Session> sessions() const;
SessionList sessions(quint64 pageAddress) const;
private:
@@ -79,6 +82,7 @@ private:
private:
QDir _dir;
+ QHash<quint64, Session> _sessions;
QMap<quint64, QMap<qint64, Session> > _byPageTime;
};
diff --git a/paperreplaymodel.cc b/paperreplaymodel.cc
new file mode 100644
index 0000000..e818b9c
--- /dev/null
+++ b/paperreplaymodel.cc
@@ -0,0 +1,119 @@
+#include "smartpen.h"
+#include "notebookmodel.h"
+#include "paperreplaymodel.h"
+
+PaperReplayModel::PaperReplayModel(PaperReplay *replay, QObject *parent) :
+ QAbstractTableModel(parent), _replay(replay)
+{
+}
+
+QVariant PaperReplayModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid()) return QVariant();
+ int row = index.row();
+ int column = index.column();
+ const PaperReplay::Session &session = _sessions.at(row);
+ switch (column) {
+ case 0:
+ switch (role) {
+ case Qt::DisplayRole:
+ return getSessionName(session);
+ }
+ break;
+ case 1:
+ switch (role) {
+ case Qt::DisplayRole:
+ return getSessionLength(session);
+ }
+ break;
+ }
+
+ return QVariant();
+}
+
+QVariant PaperReplayModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ switch (orientation) {
+ case Qt::Horizontal:
+ switch (section) {
+ case 0:
+ switch (role) {
+ case Qt::DisplayRole:
+ return tr("Recording");
+ }
+ break;
+ case 1:
+ switch (role) {
+ case Qt::DisplayRole:
+ return tr("Length");
+ }
+ break;
+ }
+ break;
+ case Qt::Vertical:
+ break;
+ }
+ return QVariant();
+}
+
+int PaperReplayModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) return 0;
+ return _sessions.size();
+}
+
+int PaperReplayModel::columnCount(const QModelIndex &parent) const
+{
+ if (parent.isValid()) return 0;
+ return 2;
+}
+
+QString PaperReplayModel::sessionFilename(const QModelIndex &index) const
+{
+ if (!index.isValid()) return QString();
+ int row = index.row();
+ const PaperReplay::Session &session = _sessions.at(row);
+ return session.fileName();
+}
+
+void PaperReplayModel::refresh()
+{
+ beginResetModel();
+ _sessions = _replay->sessions();
+ qSort(_sessions.begin(), _sessions.end(), PaperReplay::Session::startTimeLess);
+ endResetModel();
+}
+
+QString PaperReplayModel::getSessionName(const PaperReplay::Session &session)
+{
+ QString title = session.name();
+
+ if (title.isEmpty()) {
+ QDateTime date = Smartpen::fromPenTime(session.startTime());
+ title = date.toString(Qt::DefaultLocaleLongDate);
+ }
+
+ return title;
+}
+
+QString PaperReplayModel::getSessionDate(const PaperReplay::Session &session)
+{
+ QDateTime date = Smartpen::fromPenTime(session.startTime());
+ return date.toString(Qt::DefaultLocaleShortDate);
+}
+
+QString PaperReplayModel::getSessionLength(const PaperReplay::Session &session)
+{
+ int secs = Smartpen::fromPenTime(session.startTime()).secsTo(Smartpen::fromPenTime(session.endTime()));
+ int mins = secs / 60;
+ secs %= 60;
+ int hours = mins / 60;
+ mins %= 60;
+
+ const QChar fill('0');
+ if (hours) {
+ return QString("%1:%2:%3").arg(hours).arg(mins, 2, 10, fill).arg(secs, 2, 10, fill);
+ } else {
+ return QString("%2:%3").arg(mins).arg(secs, 2, 10, fill);
+ }
+}
diff --git a/paperreplaymodel.h b/paperreplaymodel.h
new file mode 100644
index 0000000..4184c8c
--- /dev/null
+++ b/paperreplaymodel.h
@@ -0,0 +1,35 @@
+#ifndef PAPERREPLAYMODEL_H
+#define PAPERREPLAYMODEL_H
+
+#include <QtCore/QAbstractTableModel>
+#include "paperreplay.h"
+
+class PaperReplayModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ explicit PaperReplayModel(PaperReplay *replay, QObject *parent = 0);
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+
+ QString sessionFilename(const QModelIndex &index) const;
+
+signals:
+
+public slots:
+ void refresh();
+
+private:
+ static QString getSessionName(const PaperReplay::Session &session);
+ static QString getSessionDate(const PaperReplay::Session &session);
+ static QString getSessionLength(const PaperReplay::Session &session);
+
+private:
+ PaperReplay *_replay;
+ QList<PaperReplay::Session> _sessions;
+};
+
+#endif // PAPERREPLAYMODEL_H
diff --git a/scribiu.pro b/scribiu.pro
index a49ef42..437e1ce 100644
--- a/scribiu.pro
+++ b/scribiu.pro
@@ -22,7 +22,8 @@ SOURCES += main.cc\
stfgraphicsitem.cc \
paperreplay.cc \
afdpageaddress.cc \
- stfstrokeitem.cc
+ stfstrokeitem.cc \
+ paperreplaymodel.cc
HEADERS += mainwindow.h \
smartpenmanager.h \
@@ -36,6 +37,7 @@ HEADERS += mainwindow.h \
stfgraphicsitem.h \
paperreplay.h \
afdpageaddress.h \
- stfstrokeitem.h
+ stfstrokeitem.h \
+ paperreplaymodel.h
FORMS += mainwindow.ui