File indexing completed on 2024-04-28 05:38:14
0001 /*************************************************************************** 0002 * Copyright (C) 2009 by Renaud Guezennec * 0003 * https://rolisteam.org/contact * 0004 * * 0005 * rolisteam is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 0021 #include "pdfviewer.h" 0022 #include <QBuffer> 0023 #include <QDebug> 0024 #include <QMessageBox> 0025 #include <QPdfBookmarkModel> 0026 #include <QPdfDocument> 0027 #include <QPdfPageNavigator> 0028 #include <QPdfView> 0029 #include <QScrollBar> 0030 #include <QShortcut> 0031 #include <QtGui> 0032 #include <type_traits> 0033 0034 #include "controller/view_controller/pdfcontroller.h" 0035 #include "customs/overlay.h" 0036 #include "ui_pdfviewer.h" 0037 0038 #define MARGING 0 0039 #define ICON_SIZE 32 0040 0041 Q_LOGGING_CATEGORY(MediaContainerPDF, "mediacontainer.pdf") 0042 0043 PdfViewer::PdfViewer(PdfController* ctrl, QWidget* parent) 0044 : MediaContainer(ctrl, MediaContainer::ContainerType::PDFContainer, parent) 0045 , m_ui(new Ui::PdfViewer) 0046 , m_document(new QPdfDocument()) 0047 , m_pdfCtrl(ctrl) 0048 { 0049 setObjectName("PdfViewer"); 0050 setWindowIcon(QIcon::fromTheme("pdfLogo")); 0051 auto wid= new QWidget(); 0052 m_ui->setupUi(wid); 0053 setWidget(wid); 0054 0055 m_ui->m_view->setDocument(m_document.get()); 0056 0057 QPdfBookmarkModel* bookmarkModel= new QPdfBookmarkModel(this); 0058 m_ui->bookmarkView->setModel(bookmarkModel); 0059 bookmarkModel->setDocument(m_document.get()); 0060 0061 makeConnections(); 0062 if(m_pdfCtrl) 0063 { 0064 if(!m_pdfCtrl->data().isEmpty()) 0065 { 0066 auto buf= m_pdfCtrl->buffer(); 0067 if(buf->open(QIODevice::ReadOnly)) 0068 m_document->load(buf); 0069 } 0070 else 0071 m_document->load(m_pdfCtrl->url().toLocalFile()); 0072 } 0073 } 0074 0075 PdfViewer::~PdfViewer() {} 0076 0077 void PdfViewer::makeConnections() 0078 { 0079 m_ui->m_cropViewAct->setIcon(QIcon::fromTheme("crop")); 0080 m_ui->m_shareAct->setIcon(QIcon::fromTheme("share_doc")); 0081 m_ui->m_continuousAct->setIcon(QIcon::fromTheme("view-page-continuous")); 0082 m_ui->m_exportToMapAct->setIcon(QIcon::fromTheme("edit-copy")); 0083 m_ui->m_exportToImage->setIcon(QIcon::fromTheme("image-x-generic")); 0084 m_ui->m_extractTextAct->setIcon(QIcon::fromTheme("text")); 0085 0086 m_ui->m_cropBtn->setDefaultAction(m_ui->m_cropViewAct); 0087 m_ui->m_shareBtn->setDefaultAction(m_ui->m_shareAct); 0088 m_ui->m_exportToMapBtn->setDefaultAction(m_ui->m_exportToMapAct); 0089 m_ui->m_exportToImageBtn->setDefaultAction(m_ui->m_exportToImage); 0090 m_ui->m_continuousBtn->setDefaultAction(m_ui->m_continuousAct); 0091 0092 m_ui->m_extractTextBtn->setDefaultAction(m_ui->m_extractTextAct); 0093 m_ui->m_extractTextBtn->setVisible(false); 0094 m_ui->m_exportToImageBtn->setVisible(false); 0095 0096 m_ui->m_zoomInBtn->setDefaultAction(m_ui->m_zoomInAct); 0097 m_ui->m_zoomOutBtn->setDefaultAction(m_ui->m_zoomOutAct); 0098 0099 m_ui->m_nextPageBtn->setDefaultAction(m_ui->m_nextPageAct); 0100 m_ui->m_previousPageBtn->setDefaultAction(m_ui->m_previousPageAct); 0101 0102 m_ui->m_exportToImage->setEnabled(false); 0103 m_ui->m_exportToMapAct->setEnabled(false); 0104 m_ui->m_extractTextAct->setEnabled(false); 0105 0106 connect(m_ui->m_zoomLevel, &QComboBox::currentIndexChanged, this, 0107 [this]() 0108 { 0109 auto i= m_ui->m_zoomLevel->currentIndex(); 0110 //, FitHeight, TwentyFiveZoom, FiftyZoom, SeventyFiveZoom, OneHundredZoom, OneHundredFitfyZoom, 0111 // TwoHundredZoom}; 0112 if(i == FitWidth) 0113 { 0114 m_ui->m_view->setZoomMode(QPdfView::ZoomMode::FitToWidth); 0115 } 0116 else if(i == FitInView) 0117 { 0118 m_ui->m_view->setZoomMode(QPdfView::ZoomMode::FitInView); 0119 } 0120 else 0121 { 0122 m_ui->m_view->setZoomMode(QPdfView::ZoomMode::Custom); 0123 0124 static QHash<int, qreal> dataValue{{TwentyFiveZoom, 0.25}, {FiftyZoom, 0.5}, 0125 {SeventyFiveZoom, 0.75}, {OneHundredZoom, 1.0}, 0126 {OneHundredFitfyZoom, 1.5}, {TwoHundredZoom, 2.0}}; 0127 m_ui->m_view->setZoomFactor(dataValue.value(i)); 0128 } 0129 }); 0130 connect(m_ui->m_zoomLevel, &QComboBox::currentTextChanged, this, 0131 [this](const QString& text) 0132 { 0133 bool ok; 0134 auto zoomlvl= static_cast<qreal>(text.toInt(&ok)); 0135 if(ok) 0136 { 0137 m_ui->m_view->setZoomFactor(zoomlvl / 100.0); 0138 } 0139 }); 0140 0141 m_ui->m_zoomLevel->setValidator(new QIntValidator); 0142 connect(m_ui->m_continuousAct, &QAction::triggered, this, 0143 [this](bool continuous) { 0144 m_ui->m_view->setPageMode(continuous ? QPdfView::PageMode::MultiPage : QPdfView::PageMode::SinglePage); 0145 }); 0146 0147 const auto& rect= geometry(); 0148 m_ui->m_splitter->setSizes( 0149 QList{{static_cast<int>(rect.width() * 0.2), static_cast<int>(rect.width() * 0.8)}}); // QSplitter 0150 connect(m_ui->m_zoomInAct, &QAction::triggered, this, [this]() { m_pdfCtrl->zoomIn(); }); 0151 connect(m_ui->m_zoomOutAct, &QAction::triggered, this, [this]() { m_pdfCtrl->zoomOut(); }); 0152 0153 m_ui->m_continuousAct->setChecked(true); 0154 m_ui->m_view->setPageMode(QPdfView::PageMode::MultiPage); 0155 0156 connect(m_pdfCtrl, &PdfController::zoomFactorChanged, m_ui->m_view, &QPdfView::setZoomFactor); 0157 0158 connect(m_ui->bookmarkView, &QTreeView::activated, this, &PdfViewer::bookmarkSelected); 0159 0160 auto nav= m_ui->m_view->pageNavigator(); 0161 auto updateCurrentPage= [this, nav]() 0162 { 0163 if(!nav) 0164 return; 0165 0166 m_ui->m_curentPage->setValue(nav->currentPage() + 1); //.arg(m_document->pageCount())); 0167 }; 0168 0169 auto updatePageCount= [this]() 0170 { 0171 m_ui->m_curentPage->setMinimum(1); 0172 m_ui->m_curentPage->setMaximum(m_document->pageCount()); 0173 m_ui->m_pageCount->setText(QString("/ %1").arg(m_document->pageCount())); 0174 }; 0175 0176 connect(nav, &QPdfPageNavigator::currentPageChanged, this, updateCurrentPage); 0177 connect(m_document.get(), &QPdfDocument::pageCountChanged, this, updatePageCount); 0178 connect(nav, &QPdfPageNavigator::forwardAvailableChanged, m_ui->m_nextPageAct, &QAction::setEnabled); 0179 connect(nav, &QPdfPageNavigator::backAvailableChanged, m_ui->m_previousPageAct, &QAction::setEnabled); 0180 0181 m_ui->m_nextPageAct->setEnabled(nav->forwardAvailable()); 0182 m_ui->m_previousPageAct->setEnabled(nav->backAvailable()); 0183 0184 updateCurrentPage(); 0185 updatePageCount(); 0186 0187 connect(m_ui->m_nextPageAct, &QAction::triggered, nav, &QPdfPageNavigator::forward); 0188 connect(m_ui->m_previousPageAct, &QAction::triggered, nav, &QPdfPageNavigator::back); 0189 connect(m_ui->m_curentPage, &QSpinBox::valueChanged, this, 0190 [this, nav]() { 0191 nav->update(m_ui->m_curentPage->value() - 1, QPointF{0, 0}, nav->currentZoom()); 0192 }); 0193 0194 m_ui->m_view->installEventFilter(this); 0195 0196 connect(m_ui->m_exportToImage, &QAction::triggered, this, &PdfViewer::extractImage); 0197 connect(m_ui->m_exportToMapAct, &QAction::triggered, this, &PdfViewer::extractMap); 0198 connect(m_ui->m_extractTextAct, &QAction::triggered, this, &PdfViewer::extractText); 0199 0200 connect(m_ui->m_cropViewAct, &QAction::triggered, this, 0201 [this]() 0202 { 0203 m_ui->m_exportToImage->setEnabled(m_ui->m_cropViewAct->isChecked()); 0204 m_ui->m_exportToMapAct->setEnabled(m_ui->m_cropViewAct->isChecked()); 0205 m_ui->m_extractTextAct->setEnabled(m_ui->m_cropViewAct->isChecked()); 0206 }); 0207 connect(m_ui->m_cropViewAct, &QAction::triggered, this, &PdfViewer::showOverLay); 0208 } 0209 0210 bool PdfViewer::eventFilter(QObject* obj, QEvent* event) 0211 { 0212 if(event->type() == QEvent::Resize && m_overlay && obj == m_ui->m_view) 0213 { 0214 auto geo= m_ui->m_view->geometry(); 0215 m_overlay->setGeometry({m_ui->m_view->mapFromParent(geo.topLeft()), geo.size()}); 0216 return QObject::eventFilter(obj, event); 0217 } 0218 else 0219 { 0220 return QObject::eventFilter(obj, event); 0221 } 0222 } 0223 0224 void PdfViewer::extractImage() 0225 { 0226 if(!m_overlay) 0227 return; 0228 0229 auto rect= m_overlay->selectedRect(); 0230 auto pix= m_ui->m_view->grab(rect); 0231 // m_pdfCtrl->shareImageIntoImage(pix); 0232 m_overlay.reset(); 0233 } 0234 0235 void PdfViewer::extractMap() 0236 { 0237 if(!m_overlay) 0238 return; 0239 auto rect= m_overlay->selectedRect(); 0240 m_ui->m_cropViewAct->setChecked(false); 0241 m_overlay.reset(nullptr); 0242 m_pdfCtrl->copyImage(m_ui->m_view->grab(rect)); 0243 m_ui->m_exportToMapAct->setEnabled(false); 0244 } 0245 void PdfViewer::extractText() 0246 { 0247 if(!m_overlay) 0248 return; 0249 /*auto rect= m_overlay->selectedRect(); 0250 auto geo= m_ui->m_view->geometry(); 0251 auto margins= m_ui->m_view->documentMargins(); 0252 auto nav= m_ui->m_view->pageNavigator(); 0253 auto pos= nav->currentLocation(); 0254 auto page= nav->currentPage(); 0255 auto zoomLevel= m_ui->m_view->zoomFactor(); 0256 // auto pix= m_ui->m_view->select(rect); 0257 // m_pdfCtrl->shareImageIntoMap(pix); 0258 0259 auto geoPage= geo.marginsRemoved(margins); 0260 0261 auto rectPage= rect.marginsRemoved(QMargins{margins.left(), margins.top(), 0, 0}); 0262 qCWarning(MediaContainerPDF) << "Geo:" << geo << "rect:" << rect << "margins:" << margins << "GeoPage:" << geoPage 0263 << "rectpage" << rectPage << "zoom" << zoomLevel; 0264 0265 0266 0267 // qCWarning(MediaContainerPDF) << geoPage << rect << ; 0268 // geo 0269 0270 auto selections= m_document->getSelection(page, rectPage.toRectF().topLeft(), rectPage.toRectF().bottomRight()); 0271 qCWarning(MediaContainerPDF) << selections.text(); 0272 0273 QRectF rectZoom(rect.x() * zoomLevel, rect.y() * zoomLevel, rect.width() * zoomLevel, rect.height() * zoomLevel); 0274 auto selections2= m_document->getSelection(page, rectZoom.topLeft(), rectZoom.bottomRight()); 0275 qCWarning(MediaContainerPDF) << selections2.text(); 0276 // m_overlay.reset();*/ 0277 } 0278 0279 void PdfViewer::sharePdfTo() 0280 { 0281 auto answer 0282 = QMessageBox::question(this, tr("Sharing Pdf File"), 0283 tr("PDF transfer can be really heavy.\nDo you want to continue and share the PDF?"), 0284 QMessageBox::Yes | QMessageBox::Cancel); 0285 if(answer == QMessageBox::Yes) 0286 { 0287 m_pdfCtrl->shareAsPdf(); 0288 } 0289 } 0290 0291 void PdfViewer::updateTitle() 0292 { 0293 setWindowTitle(tr("%1 - (PDF)").arg(m_pdfCtrl->name())); 0294 } 0295 0296 void PdfViewer::bookmarkSelected(const QModelIndex& index) 0297 { 0298 if(!index.isValid()) 0299 return; 0300 0301 const int page= index.data(qToUnderlying<QPdfBookmarkModel::Role>(QPdfBookmarkModel::Role::Page)).toInt(); 0302 m_ui->m_view->pageNavigator()->jump(page, {10, 10}); 0303 } 0304 0305 void PdfViewer::showOverLay() 0306 { 0307 if(m_ui->m_cropViewAct->isChecked()) 0308 { 0309 0310 if(!m_overlay) 0311 { 0312 m_overlay.reset(new Overlay(m_ui->m_view)); 0313 } 0314 auto geo= m_ui->m_view->geometry(); 0315 m_overlay->setGeometry({m_ui->m_view->mapFromParent(geo.topLeft()), geo.size()}); 0316 m_overlay->show(); 0317 } 0318 else 0319 { 0320 if(m_overlay != nullptr) 0321 { 0322 m_overlay->hide(); 0323 m_overlay.reset(nullptr); 0324 m_ui->m_exportToMapAct->setEnabled(false); 0325 } 0326 } 0327 } 0328 0329 void PdfViewer::savePdfToFile(QDataStream& out) 0330 { 0331 Q_UNUSED(out) 0332 // QByteArray baPdfViewer; 0333 // QBuffer bufPdfViewer(&baPdfViewer); 0334 // if(!m_pixMap.isNull()) 0335 // { 0336 // if (!m_pixMap.save(&bufPdfViewer, "jpg", 70)) 0337 // { 0338 // error(tr("PdfViewer Compression fails (savePdfViewerToFile - PdfViewer.cpp)"),this); 0339 // return; 0340 // } 0341 // out << baPdfViewer; 0342 // } 0343 } 0344 0345 void PdfViewer::contextMenuEvent(QContextMenuEvent* event) 0346 { 0347 QMenu menu(this); 0348 0349 menu.addAction(m_ui->m_cropViewAct); 0350 menu.addAction(m_ui->m_exportToMapAct); 0351 menu.addAction(m_ui->m_continuousAct); 0352 menu.addSeparator(); 0353 menu.addAction(m_ui->m_zoomInAct); 0354 menu.addAction(m_ui->m_zoomOutAct); 0355 menu.addSeparator(); 0356 menu.addAction(m_ui->m_shareAct); 0357 0358 menu.exec(event->globalPos()); 0359 } 0360 0361 /*void PdfViewer::putDataIntoCleverUri() 0362 { 0363 QByteArray data; 0364 QDataStream out(&data, QIODevice::WriteOnly); 0365 savePdfToFile(out); 0366 if(nullptr != m_uri) 0367 { 0368 m_uri->setData(data); 0369 } 0370 }*/