diff --git a/Pdf4QtLib/Pdf4QtLib.pro b/Pdf4QtLib/Pdf4QtLib.pro index 0aa16d5..2a63d49 100644 --- a/Pdf4QtLib/Pdf4QtLib.pro +++ b/Pdf4QtLib/Pdf4QtLib.pro @@ -52,6 +52,7 @@ SOURCES += \ sources/pdfdocumentbuilder.cpp \ sources/pdfdocumentmanipulator.cpp \ sources/pdfdocumenttextflow.cpp \ + sources/pdfdocumenttextfloweditormodel.cpp \ sources/pdfdocumentwriter.cpp \ sources/pdfexecutionpolicy.cpp \ sources/pdffile.cpp \ @@ -117,6 +118,7 @@ HEADERS += \ sources/pdfdocumentdrawinterface.h \ sources/pdfdocumentmanipulator.h \ sources/pdfdocumenttextflow.h \ + sources/pdfdocumenttextfloweditormodel.h \ sources/pdfdocumentwriter.h \ sources/pdfexecutionpolicy.h \ sources/pdffile.h \ diff --git a/Pdf4QtLib/sources/pdfdocumenttextflow.h b/Pdf4QtLib/sources/pdfdocumenttextflow.h index 15e8d93..9c495a6 100644 --- a/Pdf4QtLib/sources/pdfdocumenttextflow.h +++ b/Pdf4QtLib/sources/pdfdocumenttextflow.h @@ -55,6 +55,11 @@ public: PDFInteger pageIndex = 0; QString text; Flags flags = None; + + bool isText() const { return flags.testFlag(Text); } + bool isSpecial() const { return !isText(); } + bool isTitle() const { return flags.testFlag(StructureTitle); } + bool isLanguage() const { return flags.testFlag(StructureLanguage); } }; using Items = std::vector; @@ -181,6 +186,18 @@ public: /// Returns true, if text flow is empty bool isEmpty() const { return m_originalTextFlow.isEmpty(); } + /// Returns item count in edited text flow + size_t getItemCount() const { return m_editedTextFlow.size(); } + + /// Returns page index for given item + /// \param index Index + PDFInteger getPageIndex(size_t index) const { return getEditedItem(index)->pageIndex; } + + bool isItemTypeText(size_t index) const { return getEditedItem(index)->isText(); } + bool isItemTypeSpecial(size_t index) const { return getEditedItem(index)->isSpecial(); } + bool isItemTypeTitle(size_t index) const { return getEditedItem(index)->isTitle(); } + bool isItemTypeLanguage(size_t index) const { return getEditedItem(index)->isLanguage(); } + private: void createEditedFromOriginalTextFlow(); void updateModifiedFlag(size_t index); diff --git a/Pdf4QtLib/sources/pdfdocumenttextfloweditormodel.cpp b/Pdf4QtLib/sources/pdfdocumenttextfloweditormodel.cpp new file mode 100644 index 0000000..cd31de2 --- /dev/null +++ b/Pdf4QtLib/sources/pdfdocumenttextfloweditormodel.cpp @@ -0,0 +1,221 @@ +// Copyright (C) 2021 Jakub Melka +// +// This file is part of PDF4QT. +// +// PDF4QT is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// with the written consent of the copyright owner, any later version. +// +// PDF4QT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with PDF4QT. If not, see . + +#include "pdfdocumenttextfloweditormodel.h" +#include "pdfdocumenttextflow.h" + +namespace pdf +{ + +PDFDocumentTextFlowEditorModel::PDFDocumentTextFlowEditorModel(QObject* parent) : + BaseClass(parent), + m_editor(nullptr) +{ + +} + +PDFDocumentTextFlowEditorModel::~PDFDocumentTextFlowEditorModel() +{ + +} + +QVariant PDFDocumentTextFlowEditorModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Vertical) + { + return BaseClass::headerData(section, orientation, role); + } + + if (role == Qt::DisplayRole) + { + switch (section) + { + case ColumnPageNo: + return tr("Page No."); + + case ColumnType: + return tr("Type"); + + case ColumnState: + return tr("State"); + + case ColumnText: + return tr("Text"); + + default: + Q_ASSERT(false); + break; + } + } + + return BaseClass::headerData(section, orientation, role); +} + +int PDFDocumentTextFlowEditorModel::rowCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + { + return 0; + } + + if (m_editor) + { + return int(m_editor->getItemCount()); + } + + return 0; +} + +int PDFDocumentTextFlowEditorModel::columnCount(const QModelIndex& parent) const +{ + if (parent.isValid()) + { + return 0; + } + + return ColumnLast; +} + +QVariant PDFDocumentTextFlowEditorModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid() || !m_editor) + { + return QVariant(); + } + + if (role == Qt::DisplayRole || role == Qt::EditRole) + { + switch (index.column()) + { + case ColumnPageNo: + { + PDFInteger pageIndex = m_editor->getPageIndex(index.row()); + if (pageIndex >= 0) + { + return QString::number(pageIndex + 1); + } + + return QVariant(); + } + + case ColumnType: + { + if (m_editor->isItemTypeTitle(index.row())) + { + return tr("Title"); + } + if (m_editor->isItemTypeLanguage(index.row())) + { + return tr("Language"); + } + if (m_editor->isItemTypeSpecial(index.row())) + { + return tr("Special"); + } + + return tr("Text"); + } + + case ColumnState: + { + const bool isModified = m_editor->isModified(index.row()); + const bool isRemoved = m_editor->isRemoved(index.row()); + + if (isRemoved) + { + return tr("Removed"); + } + + if (isModified) + { + return tr("Modified"); + } + + return tr("Active"); + } + + case ColumnText: + return m_editor->getText(index.row()); + + default: + Q_ASSERT(false); + break; + } + } + + return QVariant(); +} + +bool PDFDocumentTextFlowEditorModel::setData(const QModelIndex& index, const QVariant& value, int role) +{ + if (role == Qt::EditRole && index.column() == ColumnText) + { + m_editor->setText(value.toString(), index.row()); + return true; + } + + return false; +} + +Qt::DropActions PDFDocumentTextFlowEditorModel::supportedDropActions() const +{ + return Qt::DropAction(); +} + +Qt::DropActions PDFDocumentTextFlowEditorModel::supportedDragActions() const +{ + return Qt::DropActions(); +} + +Qt::ItemFlags PDFDocumentTextFlowEditorModel::flags(const QModelIndex& index) const +{ + Qt::ItemFlags flags = BaseClass::flags(index); + + if (index.column() == ColumnText) + { + flags.setFlag(Qt::ItemIsEditable); + } + + return flags; +} + +PDFDocumentTextFlowEditor* PDFDocumentTextFlowEditorModel::getEditor() const +{ + return m_editor; +} + +void PDFDocumentTextFlowEditorModel::setEditor(PDFDocumentTextFlowEditor* editor) +{ + if (m_editor != editor) + { + beginResetModel(); + m_editor = editor; + endResetModel(); + } +} + +void PDFDocumentTextFlowEditorModel::beginFlowChange() +{ + beginResetModel(); +} + +void PDFDocumentTextFlowEditorModel::endFlowChange() +{ + endResetModel(); +} + +} // namespace pdf diff --git a/Pdf4QtLib/sources/pdfdocumenttextfloweditormodel.h b/Pdf4QtLib/sources/pdfdocumenttextfloweditormodel.h new file mode 100644 index 0000000..71763b2 --- /dev/null +++ b/Pdf4QtLib/sources/pdfdocumenttextfloweditormodel.h @@ -0,0 +1,70 @@ +// Copyright (C) 2021 Jakub Melka +// +// This file is part of PDF4QT. +// +// PDF4QT is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// with the written consent of the copyright owner, any later version. +// +// PDF4QT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with PDF4QT. If not, see . + +#ifndef PDFDOCUMENTTEXTFLOWEDITORMODEL_H +#define PDFDOCUMENTTEXTFLOWEDITORMODEL_H + +#include "pdfglobal.h" + +#include + +namespace pdf +{ +class PDFDocumentTextFlowEditor; + +class PDF4QTLIBSHARED_EXPORT PDFDocumentTextFlowEditorModel : public QAbstractTableModel +{ + Q_OBJECT + +private: + using BaseClass = QAbstractTableModel; + +public: + PDFDocumentTextFlowEditorModel(QObject* parent); + virtual ~PDFDocumentTextFlowEditorModel() override; + + enum Column + { + ColumnPageNo, + ColumnType, + ColumnState, + ColumnText, + ColumnLast + }; + + virtual int rowCount(const QModelIndex& parent) const override; + virtual int columnCount(const QModelIndex& parent) const override; + virtual QVariant data(const QModelIndex& index, int role) const override; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role) override; + virtual Qt::DropActions supportedDropActions() const override; + virtual Qt::DropActions supportedDragActions() const override; + virtual Qt::ItemFlags flags(const QModelIndex& index) const override; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const override; + + PDFDocumentTextFlowEditor* getEditor() const; + void setEditor(PDFDocumentTextFlowEditor* editor); + + void beginFlowChange(); + void endFlowChange(); + +private: + PDFDocumentTextFlowEditor* m_editor; +}; + +} // namespace pdf + +#endif // PDFDOCUMENTTEXTFLOWEDITORMODEL_H diff --git a/Pdf4QtLib/sources/pdfplugin.h b/Pdf4QtLib/sources/pdfplugin.h index 2a8e481..a9f9cdc 100644 --- a/Pdf4QtLib/sources/pdfplugin.h +++ b/Pdf4QtLib/sources/pdfplugin.h @@ -27,6 +27,7 @@ #include class QAction; +class QMainWindow; namespace pdf { @@ -55,6 +56,7 @@ public: virtual QString getOriginalFileName() const = 0; virtual pdf::PDFTextSelection getSelectedText() const = 0; + virtual QMainWindow* getMainWindow() const = 0; }; class PDF4QTLIBSHARED_EXPORT PDFPlugin : public QObject diff --git a/Pdf4QtViewer/pdfprogramcontroller.cpp b/Pdf4QtViewer/pdfprogramcontroller.cpp index e119a63..f4702ba 100644 --- a/Pdf4QtViewer/pdfprogramcontroller.cpp +++ b/Pdf4QtViewer/pdfprogramcontroller.cpp @@ -1073,6 +1073,11 @@ pdf::PDFTextSelection PDFProgramController::getSelectedText() const return m_mainWindowInterface->getSelectedText(); } +QMainWindow* PDFProgramController::getMainWindow() const +{ + return m_mainWindow; +} + void PDFProgramController::onActionRotateRightTriggered() { m_pdfWidget->getDrawWidgetProxy()->performOperation(pdf::PDFDrawWidgetProxy::RotateRight); diff --git a/Pdf4QtViewer/pdfprogramcontroller.h b/Pdf4QtViewer/pdfprogramcontroller.h index 4f3317a..eeebb17 100644 --- a/Pdf4QtViewer/pdfprogramcontroller.h +++ b/Pdf4QtViewer/pdfprogramcontroller.h @@ -285,6 +285,7 @@ public: virtual QString getOriginalFileName() const override; virtual pdf::PDFTextSelection getSelectedText() const override; + virtual QMainWindow* getMainWindow() const override; signals: void queryPasswordRequest(QString* password, bool* ok); diff --git a/Pdf4QtViewerPlugins/AudioBookPlugin/AudioBookPlugin.pro b/Pdf4QtViewerPlugins/AudioBookPlugin/AudioBookPlugin.pro index f7b404c..37cf0a6 100644 --- a/Pdf4QtViewerPlugins/AudioBookPlugin/AudioBookPlugin.pro +++ b/Pdf4QtViewerPlugins/AudioBookPlugin/AudioBookPlugin.pro @@ -33,10 +33,12 @@ DESTDIR = $$OUT_PWD/../../pdfplugins CONFIG += c++11 SOURCES += \ - audiobookplugin.cpp + audiobookplugin.cpp \ + audiotextstreameditordockwidget.cpp HEADERS += \ - audiobookplugin.h + audiobookplugin.h \ + audiotextstreameditordockwidget.h CONFIG += force_debug_info @@ -46,3 +48,6 @@ DISTFILES += \ RESOURCES += \ icons.qrc +FORMS += \ + audiotextstreameditordockwidget.ui + diff --git a/Pdf4QtViewerPlugins/AudioBookPlugin/audiobookplugin.cpp b/Pdf4QtViewerPlugins/AudioBookPlugin/audiobookplugin.cpp index b61b7bb..0a43a71 100644 --- a/Pdf4QtViewerPlugins/AudioBookPlugin/audiobookplugin.cpp +++ b/Pdf4QtViewerPlugins/AudioBookPlugin/audiobookplugin.cpp @@ -18,13 +18,16 @@ #include "audiobookplugin.h" #include +#include namespace pdfplugin { AudioBookPlugin::AudioBookPlugin() : pdf::PDFPlugin(nullptr), - m_createTextStreamAction(nullptr) + m_createTextStreamAction(nullptr), + m_audioTextStreamDockWidget(nullptr), + m_audioTextStreamEditorModel(nullptr) { } @@ -63,6 +66,21 @@ void AudioBookPlugin::onCreateTextStreamTriggered() { Q_ASSERT(m_document); + if (!m_audioTextStreamDockWidget) + { + m_audioTextStreamDockWidget = new AudioTextStreamEditorDockWidget(m_dataExchangeInterface->getMainWindow()); + m_audioTextStreamDockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); + m_dataExchangeInterface->getMainWindow()->addDockWidget(Qt::BottomDockWidgetArea, m_audioTextStreamDockWidget, Qt::Horizontal); + m_audioTextStreamDockWidget->setFloating(false); + + Q_ASSERT(!m_audioTextStreamEditorModel); + m_audioTextStreamEditorModel = new pdf::PDFDocumentTextFlowEditorModel(m_audioTextStreamDockWidget); + m_audioTextStreamEditorModel->setEditor(&m_textFlowEditor); + m_audioTextStreamDockWidget->setModel(m_audioTextStreamEditorModel); + } + + m_audioTextStreamDockWidget->show(); + if (!m_textFlowEditor.isEmpty()) { return; @@ -71,7 +89,10 @@ void AudioBookPlugin::onCreateTextStreamTriggered() pdf::PDFDocumentTextFlowFactory factory; factory.setCalculateBoundingBoxes(true); pdf::PDFDocumentTextFlow textFlow = factory.create(m_document, pdf::PDFDocumentTextFlowFactory::Algorithm::Auto); + + m_audioTextStreamEditorModel->beginFlowChange(); m_textFlowEditor.setTextFlow(std::move(textFlow)); + m_audioTextStreamEditorModel->endFlowChange(); } void AudioBookPlugin::updateActions() diff --git a/Pdf4QtViewerPlugins/AudioBookPlugin/audiobookplugin.h b/Pdf4QtViewerPlugins/AudioBookPlugin/audiobookplugin.h index 917c1a4..16892b1 100644 --- a/Pdf4QtViewerPlugins/AudioBookPlugin/audiobookplugin.h +++ b/Pdf4QtViewerPlugins/AudioBookPlugin/audiobookplugin.h @@ -20,6 +20,8 @@ #include "pdfplugin.h" #include "pdfdocumenttextflow.h" +#include "pdfdocumenttextfloweditormodel.h" +#include "audiotextstreameditordockwidget.h" #include @@ -49,6 +51,8 @@ private: QAction* m_createTextStreamAction; pdf::PDFDocumentTextFlowEditor m_textFlowEditor; + AudioTextStreamEditorDockWidget* m_audioTextStreamDockWidget; + pdf::PDFDocumentTextFlowEditorModel* m_audioTextStreamEditorModel; }; } // namespace pdfplugin diff --git a/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.cpp b/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.cpp new file mode 100644 index 0000000..1266297 --- /dev/null +++ b/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.cpp @@ -0,0 +1,54 @@ +// Copyright (C) 2021 Jakub Melka +// +// This file is part of PDF4QT. +// +// PDF4QT is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// with the written consent of the copyright owner, any later version. +// +// PDF4QT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with PDF4QT. If not, see . + +#include "audiotextstreameditordockwidget.h" +#include "ui_audiotextstreameditordockwidget.h" + +#include "pdfwidgetutils.h" + +namespace pdfplugin +{ + +AudioTextStreamEditorDockWidget::AudioTextStreamEditorDockWidget(QWidget *parent) : + QDockWidget(parent), + ui(new Ui::AudioTextStreamEditorDockWidget), + m_model(nullptr) +{ + ui->setupUi(this); + ui->textStreamTableView->horizontalHeader()->setStretchLastSection(true); + ui->textStreamTableView->horizontalHeader()->setMinimumSectionSize(pdf::PDFWidgetUtils::scaleDPI_x(this, 85)); + + setMinimumSize(pdf::PDFWidgetUtils::scaleDPI(this, QSize(300, 150))); +} + +AudioTextStreamEditorDockWidget::~AudioTextStreamEditorDockWidget() +{ + delete ui; +} + +pdf::PDFDocumentTextFlowEditorModel* AudioTextStreamEditorDockWidget::getModel() const +{ + return m_model; +} + +void AudioTextStreamEditorDockWidget::setModel(pdf::PDFDocumentTextFlowEditorModel* model) +{ + m_model = model; + ui->textStreamTableView->setModel(m_model); +} + +} // namespace pdfplugin diff --git a/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.h b/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.h new file mode 100644 index 0000000..b384679 --- /dev/null +++ b/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.h @@ -0,0 +1,51 @@ +// Copyright (C) 2021 Jakub Melka +// +// This file is part of PDF4QT. +// +// PDF4QT is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// with the written consent of the copyright owner, any later version. +// +// PDF4QT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with PDF4QT. If not, see . + +#ifndef AUDIOTEXTSTREAMEDITORDOCKWIDGET_H +#define AUDIOTEXTSTREAMEDITORDOCKWIDGET_H + +#include "pdfdocumenttextfloweditormodel.h" + +#include + +namespace Ui +{ +class AudioTextStreamEditorDockWidget; +} + +namespace pdfplugin +{ + +class AudioTextStreamEditorDockWidget : public QDockWidget +{ + Q_OBJECT + +public: + explicit AudioTextStreamEditorDockWidget(QWidget* parent); + virtual ~AudioTextStreamEditorDockWidget() override; + + pdf::PDFDocumentTextFlowEditorModel* getModel() const; + void setModel(pdf::PDFDocumentTextFlowEditorModel* model); + +private: + Ui::AudioTextStreamEditorDockWidget* ui; + pdf::PDFDocumentTextFlowEditorModel* m_model; +}; + +} // namespace pdfplugin + +#endif // AUDIOTEXTSTREAMEDITORDOCKWIDGET_H diff --git a/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.ui b/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.ui new file mode 100644 index 0000000..bb9057c --- /dev/null +++ b/Pdf4QtViewerPlugins/AudioBookPlugin/audiotextstreameditordockwidget.ui @@ -0,0 +1,26 @@ + + + AudioTextStreamEditorDockWidget + + + + 0 + 0 + 723 + 552 + + + + Text Stream for Audio Book + + + + + + + + + + + +