diff options
-rw-r--r-- | mainwindow.cc | 41 | ||||
-rw-r--r-- | mainwindow.h | 6 | ||||
-rw-r--r-- | mainwindow.ui | 90 | ||||
-rw-r--r-- | notebookview.cc | 2 | ||||
-rw-r--r-- | paperreplay.cc | 37 | ||||
-rw-r--r-- | paperreplay.h | 6 | ||||
-rw-r--r-- | paperreplaymodel.cc | 119 | ||||
-rw-r--r-- | paperreplaymodel.h | 35 | ||||
-rw-r--r-- | scribiu.pro | 6 |
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 ¬ebook) { 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 |