From 2910de560ead3ff65db26292fc27e427a5cf9b5e Mon Sep 17 00:00:00 2001 From: Javier Date: Sun, 14 Jun 2015 05:18:53 +0200 Subject: add export feature and desktop file --- mainwindow.cc | 135 +++++++++++++ mainwindow.h | 10 + mainwindow.ui | 63 ++++++- notebookview.cc | 28 +++ notebookview.h | 6 + paperreplay.cc | 6 +- scribiu.desktop | 11 ++ scribiu.pro | 16 +- scribiu.svg | 553 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ smartpensyncer.cc | 3 +- 10 files changed, 826 insertions(+), 5 deletions(-) create mode 100644 scribiu.desktop create mode 100644 scribiu.svg diff --git a/mainwindow.cc b/mainwindow.cc index dd687a2..0fdf38d 100644 --- a/mainwindow.cc +++ b/mainwindow.cc @@ -1,4 +1,7 @@ #include +#include +#include +#include #include "mainwindow.h" #include "ui_mainwindow.h" @@ -24,10 +27,15 @@ MainWindow::MainWindow(QWidget *parent) : ui->paperReplayView->horizontalHeader()->setResizeMode(1, QHeaderView::Fixed); ui->paperReplayView->setVisible(false); Phonon::createPath(_media, _mediaOutput); + _media->setTickInterval(500); ui->replaySlider->setMediaObject(_media); ui->pauseButton->setVisible(false); connect(_media, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(handleMediaStateChange(Phonon::State))); + connect(_media, SIGNAL(totalTimeChanged(qint64)), + this, SLOT(handleMediaTotalTimeChanged(qint64))); + connect(_media, SIGNAL(tick(qint64)), + this, SLOT(handleMediaTick(qint64))); } MainWindow::~MainWindow() @@ -73,6 +81,46 @@ void MainWindow::openNotebook(const QString &pen, const QString ¬ebook) } } +void MainWindow::exportCurrentPageAsPng(const QString &file) +{ + qDebug() << "Exporting current page" << ui->notebookView->curPage() << "to" << file; + QImage image = ui->notebookView->exportPage(ui->notebookView->curPage()); + if (!image.save(file, "PNG")) { + QMessageBox::warning(this, tr("Export page"), + tr("Could not export current page to '%s'").arg(file)); + } +} + +void MainWindow::exportCurrentPageAsSvg(const QString &file) +{ + QSvgGenerator svg; + svg.setFileName(file); + svg.setSize(ui->notebookView->getCurPageSize()); + svg.setViewBox(ui->notebookView->getCurPageTrim()); + svg.setTitle(_curNotebookName + " p." + QString::number(ui->notebookView->curPage())); + svg.setDescription("Page " + QString::number(ui->notebookView->curPage()) + " of " + _curNotebookName + " from " + _curPenName); + qDebug() << "Exporting current page" << ui->notebookView->curPage() << "to" << file; + QPainter painter; + painter.begin(&svg); + ui->notebookView->renderPage(&painter, ui->notebookView->curPage()); + painter.end(); +} + +void MainWindow::exportCurrentPaperReplayAsAac(const QString &file) +{ + QString src = _media->currentSource().fileName(); + if (src.isEmpty()) { + QMessageBox::warning(this, tr("Export audio"), + tr("No audio file is selected")); + return; + } + qDebug() << "Exporting current audio" << src << "to" << file; + if (!QFile::copy(src, file)) { + QMessageBox::warning(this, tr("Export audio"), + tr("Could not export current audio to '%s'").arg(file)); + } +} + void MainWindow::handleNotebookSelected(const QModelIndex &index) { if (!index.isValid()) { @@ -151,13 +199,100 @@ void MainWindow::handleMediaStateChange(Phonon::State state) _media->seek(_pendingSeek); _pendingSeek = 0; } + ui->mediaPosLabel->setText(formatDuration(_media->currentTime())); + ui->mediaLenLabel->setText("/ " + formatDuration(_media->totalTime())); break; case Phonon::PausedState: ui->playButton->setVisible(true); ui->pauseButton->setVisible(false); + ui->mediaPosLabel->setText(formatDuration(_media->currentTime())); + ui->mediaLenLabel->setText("/ " + formatDuration(_media->totalTime())); break; default: ui->playButton->setVisible(true); ui->pauseButton->setVisible(false); + ui->mediaPosLabel->setText(QString()); + ui->mediaLenLabel->setText(QString()); + break; + } +} + +void MainWindow::handleMediaTotalTimeChanged(qint64 time) +{ + ui->mediaLenLabel->setText("/ " + formatDuration(time)); +} + +void MainWindow::handleMediaTick(qint64 time) +{ + ui->mediaPosLabel->setText(formatDuration(time)); +} + +void MainWindow::handleExport() +{ + if (_curNotebookName == PAPER_REPLAY) { + QStringList filters; + filters << tr("Current audio as AAC (*.aac)"); + QString filter; + QString fileName = QFileDialog::getSaveFileName(this, tr("Export page"), QString(), + filters.join(";;"), &filter); + if (fileName.isEmpty()) return; + int filterIndex = filters.indexOf(filter); + switch (filterIndex) { + case 0: + if (!fileName.endsWith(".aac", Qt::CaseInsensitive)) { + fileName.append(".aac"); + } + exportCurrentPaperReplayAsAac(fileName); + break; + } + } else if (!_curNotebookName.isEmpty()) { + QStringList filters; + filters << tr("Current page as PNG image (*.png)") + << tr("Current page as SVG image (*.svg)") + << tr("Current audio as AAC (*.aac)"); + QString filter; + QString fileName = QFileDialog::getSaveFileName(this, tr("Export page"), QString(), + filters.join(";;"), &filter); + if (fileName.isEmpty()) return; + int filterIndex = filters.indexOf(filter); + switch (filterIndex) { + case 0: + if (!fileName.endsWith(".png", Qt::CaseInsensitive)) { + fileName.append(".png"); + } + exportCurrentPageAsPng(fileName); + break; + case 1: + if (!fileName.endsWith(".svg", Qt::CaseInsensitive)) { + fileName.append(".svg"); + } + exportCurrentPageAsSvg(fileName); + break; + case 2: + if (!fileName.endsWith(".aac", Qt::CaseInsensitive)) { + fileName.append(".aac"); + } + exportCurrentPaperReplayAsAac(fileName); + break; + } + } else { + QMessageBox::warning(this, tr("Export page"), + tr("Open a notebook or audio in order to export")); + } +} + +QString MainWindow::formatDuration(qint64 time) +{ + int secs = time / 1000; + 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/mainwindow.h b/mainwindow.h index cafec49..9bce36a 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -24,6 +24,10 @@ public slots: void closeNotebook(); void openNotebook(const QString &pen, const QString ¬ebook); + void exportCurrentPageAsPng(const QString &file); + void exportCurrentPageAsSvg(const QString &file); + void exportCurrentPaperReplayAsAac(const QString &file); + private slots: void handleNotebookSelected(const QModelIndex &index); void handleCurPageChanged(); @@ -32,6 +36,12 @@ private slots: void handlePaperReplayPlay(); void handlePaperReplayPause(); void handleMediaStateChange(Phonon::State state); + void handleMediaTotalTimeChanged(qint64 time); + void handleMediaTick(qint64 time); + void handleExport(); + +private: + QString formatDuration(qint64 time); private: Ui::MainWindow *ui; diff --git a/mainwindow.ui b/mainwindow.ui index 1662e7f..56ad8ad 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -117,6 +117,40 @@ + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 10 + + + + + + + + + 30 + 30 + + + + ... + + + + + + + + @@ -233,6 +267,9 @@ + + 4 + @@ -273,7 +310,14 @@ - + + + + + + + + @@ -517,6 +561,22 @@ + + exportButton + clicked() + MainWindow + handleExport() + + + 402 + 42 + + + 358 + 192 + + + handleNotebookSelected(QModelIndex) @@ -526,5 +586,6 @@ handlePaperReplayPlay() handlePaperReplayPause() handlePaperReplaySelected(QModelIndex) + handleExport() diff --git a/notebookview.cc b/notebookview.cc index 2bca4f7..f433664 100644 --- a/notebookview.cc +++ b/notebookview.cc @@ -88,6 +88,34 @@ void NotebookView::setZoom(int zoom) } } +QSize NotebookView::getCurPageSize() const +{ + return _nb->getPageSize(_curPage); +} + +QRect NotebookView::getCurPageTrim() const +{ + return _nb->getPageTrim(_curPage); +} + +QImage NotebookView::exportPage(int pageNum) const +{ + const QRect pageTrim = getCurPageTrim(); + QImage image(pageTrim.width() / 4, pageTrim.height() / 4, QImage::Format_RGB32); + QPainter painter(&image); + painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + renderPage(&painter, pageNum, QRectF(), pageTrim); + return image; +} + +void NotebookView::renderPage(QPainter *painter, int pageNum, const QRectF &target, const QRectF &source) const +{ + QGraphicsScene scene; + PageItem *item = new PageItem(_nb, 0, pageNum); + scene.addItem(item); + scene.render(painter, target, source, Qt::KeepAspectRatio); +} + void NotebookView::requestPaperReplay(const QString &file, qint64 time) { emit paperReplayRequested(file, time); diff --git a/notebookview.h b/notebookview.h index 1b3eb46..7039506 100644 --- a/notebookview.h +++ b/notebookview.h @@ -32,6 +32,12 @@ public: int zoom() const; + QSize getCurPageSize() const; + QRect getCurPageTrim() const; + + QImage exportPage(int pageNum) const; + void renderPage(QPainter *painter, int pageNum, const QRectF &target = QRectF(), const QRectF &source = QRectF()) const; + void requestPaperReplay(const QString &file, qint64 time); signals: diff --git a/paperreplay.cc b/paperreplay.cc index 5baeac7..f2d5b20 100644 --- a/paperreplay.cc +++ b/paperreplay.cc @@ -142,8 +142,10 @@ bool PaperReplay::open(const QString &path, quint64 notebookGuid) if (!parseSessionInfo(session.d, sessionDir.filePath("session.info"))) { qWarning() << "Could not parse:" << sessionDir.absoluteFilePath("session.info"); } - if (!parseSessionPages(session.d, sessionDir.filePath("session.pages"))) { - qWarning() << "Could not parse:" << sessionDir.absoluteFilePath("session.pages"); + if (sessionDir.exists("session.pages")) { + if (!parseSessionPages(session.d, sessionDir.filePath("session.pages"))) { + qWarning() << "Could not parse:" << sessionDir.absoluteFilePath("session.pages"); + } } if (!session.d->file.isEmpty()) { diff --git a/scribiu.desktop b/scribiu.desktop new file mode 100644 index 0000000..ef5cbe9 --- /dev/null +++ b/scribiu.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Name=Scribiu +GenericName=Livescribe Manager +Comment=Read notebooks and audio notes from your Livescribe pen +Exec=/usr/bin/scribiu +TryExec=/usr/bin/scribiu +Icon=scribiu +Terminal=false +Type=Application +Categories=Office; diff --git a/scribiu.pro b/scribiu.pro index 437e1ce..c85a260 100644 --- a/scribiu.pro +++ b/scribiu.pro @@ -1,4 +1,4 @@ -QT += core gui phonon +QT += core gui svg phonon greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -41,3 +41,17 @@ HEADERS += mainwindow.h \ paperreplaymodel.h FORMS += mainwindow.ui + +isEmpty(PREFIX) { + PREFIX = /usr +} + +target.path = $$PREFIX/bin + +icon.path = $$PREFIX/share/icons/hicolor/scalable/apps +icon.files = scribiu.svg + +desktop.path = $$PREFIX/share/applications +desktop.files = scribiu.desktop + +INSTALLS += target icon desktop diff --git a/scribiu.svg b/scribiu.svg new file mode 100644 index 0000000..97a453d --- /dev/null +++ b/scribiu.svg @@ -0,0 +1,553 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Jakub Steiner + + + http://jimmac.musichall.cz + + + + + office + applications + category + + + + + + + + + + + + + + + + + + + + + diff --git a/smartpensyncer.cc b/smartpensyncer.cc index fe7a281..93331ef 100644 --- a/smartpensyncer.cc +++ b/smartpensyncer.cc @@ -4,6 +4,7 @@ #include #include #include +#include "paperreplay.h" #include "smartpensyncer.h" #define BUFFER_SIZE 16 * 1024 @@ -152,7 +153,7 @@ bool SmartpenSyncer::syncNotebook(const Smartpen::ChangeReport &change) bool SmartpenSyncer::syncPaperReplay() { - QDir replayDir(_penDataDir.filePath("PaperReplay")); + QDir replayDir(_penDataDir.filePath(PAPER_REPLAY)); if (!replayDir.exists()) { if (!replayDir.mkpath(".")) { qWarning() << "Cannot create PaperReplay data directory:" << replayDir.absolutePath(); -- cgit v1.2.3