mirror of
				https://github.com/JakubMelka/PDF4QT.git
				synced 2025-06-05 21:59:17 +02:00 
			
		
		
		
	Issue #107: Enable/Disable image conversion GUI
This commit is contained in:
		| @@ -58,6 +58,7 @@ private: | ||||
| class PDF4QTLIBSHARED_EXPORT PDFImage | ||||
| { | ||||
| public: | ||||
|     PDFImage() = default; | ||||
|  | ||||
|     /// Creates image from the content and the dictionary. If image can't be created, then exception is thrown. | ||||
|     /// \param document Document | ||||
| @@ -112,8 +113,6 @@ public: | ||||
|     const PDFImageData& getSoftMaskData() const { return m_softMask; } | ||||
|  | ||||
| private: | ||||
|     PDFImage() = default; | ||||
|  | ||||
|     PDFImageData m_imageData; | ||||
|     PDFImageData m_softMask; | ||||
|     PDFColorSpacePointer m_colorSpace; | ||||
|   | ||||
| @@ -62,7 +62,7 @@ GENERATE_EXPORT_HEADER(Pdf4QtViewer | ||||
|                        PDF4QTVIEWERLIBSHARED_EXPORT | ||||
|                        EXPORT_FILE_NAME "${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}/pdf4qtviewer_export.h") | ||||
|  | ||||
| target_link_libraries(Pdf4QtViewer PRIVATE Pdf4QtLib Qt6::Core Qt6::Gui Qt6::Widgets Qt6::PrintSupport Qt6::TextToSpeech Qt6::Xml Qt6::OpenGLWidgets) | ||||
| target_link_libraries(Pdf4QtViewer PRIVATE Pdf4QtLib Qt6::Core Qt6::Gui Qt6::Widgets Qt6::PrintSupport Qt6::TextToSpeech Qt6::Xml Qt6::Svg Qt6::OpenGLWidgets) | ||||
| target_include_directories(Pdf4QtViewer INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) | ||||
| target_include_directories(Pdf4QtViewer PUBLIC ${CMAKE_BINARY_DIR}/${INSTALL_INCLUDEDIR}) | ||||
|  | ||||
|   | ||||
| @@ -23,16 +23,122 @@ | ||||
| #include "pdfimage.h" | ||||
| #include "pdfdbgheap.h" | ||||
| #include "pdfexception.h" | ||||
| #include "pdfwidgetutils.h" | ||||
|  | ||||
| #include <QCheckBox> | ||||
| #include <QPushButton> | ||||
| #include <QElapsedTimer> | ||||
| #include <QtConcurrent/QtConcurrent> | ||||
| #include <QListWidget> | ||||
| #include <QStyledItemDelegate> | ||||
| #include <QPainter> | ||||
| #include <QtSvg/QSvgRenderer> | ||||
| #include <QMouseEvent> | ||||
| #include <QToolTip> | ||||
|  | ||||
| namespace pdfviewer | ||||
| { | ||||
|  | ||||
| class ImagePreviewDelegate : public QStyledItemDelegate | ||||
| { | ||||
| public: | ||||
|     ImagePreviewDelegate(std::vector<PDFCreateBitonalDocumentDialog::ImageConversionInfo>* imageConversionInfos, QObject* parent) : | ||||
|         QStyledItemDelegate(parent), | ||||
|         m_imageConversionInfos(imageConversionInfos) | ||||
|     { | ||||
|         m_yesRenderer.load(QString(":/resources/result-ok.svg")); | ||||
|         m_noRenderer.load(QString(":/resources/result-error.svg")); | ||||
|     } | ||||
|  | ||||
|     virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override | ||||
|     { | ||||
|         QStyledItemDelegate::paint(painter, option, index); | ||||
|  | ||||
|         QRect markRect = getMarkRect(option); | ||||
|  | ||||
|         if (index.isValid()) | ||||
|         { | ||||
|             const PDFCreateBitonalDocumentDialog::ImageConversionInfo& info = m_imageConversionInfos->at(index.row()); | ||||
|             if (info.conversionEnabled) | ||||
|             { | ||||
|                 m_yesRenderer.render(painter, markRect); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 m_noRenderer.render(painter, markRect); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     virtual bool editorEvent(QEvent* event, | ||||
|                              QAbstractItemModel* model, | ||||
|                              const QStyleOptionViewItem& option, | ||||
|                              const QModelIndex& index) | ||||
|     { | ||||
|         Q_UNUSED(model); | ||||
|         Q_UNUSED(index); | ||||
|  | ||||
|         if (event->type() == QEvent::MouseButtonPress && index.isValid()) | ||||
|         { | ||||
|             QMouseEvent* mouseEvent = dynamic_cast<QMouseEvent*>(event); | ||||
|             if (mouseEvent && mouseEvent->button() == Qt::LeftButton) | ||||
|             { | ||||
|                 // Do we click on yes/no mark? | ||||
|                 QRectF markRect = getMarkRect(option); | ||||
|                 if (markRect.contains(mouseEvent->position())) | ||||
|                 { | ||||
|                     PDFCreateBitonalDocumentDialog::ImageConversionInfo& info = m_imageConversionInfos->at(index.row()); | ||||
|                     info.conversionEnabled = !info.conversionEnabled; | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     virtual bool helpEvent(QHelpEvent* event, | ||||
|                            QAbstractItemView* view, | ||||
|                            const QStyleOptionViewItem& option, | ||||
|                            const QModelIndex& index) override | ||||
|     { | ||||
|         Q_UNUSED(index); | ||||
|  | ||||
|         if (!event || !view) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (event->type() == QEvent::ToolTip) | ||||
|         { | ||||
|             // Are we hovering over yes/no mark? | ||||
|             QRectF markRect = getMarkRect(option); | ||||
|             if (markRect.contains(event->pos())) | ||||
|             { | ||||
|                 event->accept(); | ||||
|                 QToolTip::showText(event->globalPos(), tr("Toggle this icon to switch image conversion to bitonic format on or off."), view); | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     static constexpr QSize s_iconSize = QSize(24, 24); | ||||
|  | ||||
|     QRect getMarkRect(const QStyleOptionViewItem& option) const | ||||
|     { | ||||
|         QSize markSize = pdf::PDFWidgetUtils::scaleDPI(option.widget, s_iconSize); | ||||
|         QRect markRect(option.rect.left(), option.rect.top(), markSize.width(), markSize.height()); | ||||
|         return markRect; | ||||
|     } | ||||
|  | ||||
|     std::vector<PDFCreateBitonalDocumentDialog::ImageConversionInfo>* m_imageConversionInfos; | ||||
|     mutable QSvgRenderer m_yesRenderer; | ||||
|     mutable QSvgRenderer m_noRenderer; | ||||
| }; | ||||
|  | ||||
| PDFCreateBitonalDocumentDialog::PDFCreateBitonalDocumentDialog(const pdf::PDFDocument* document, | ||||
|                                                                const pdf::PDFCMS* cms, | ||||
|                                                                QWidget* parent) : | ||||
| @@ -58,6 +164,8 @@ PDFCreateBitonalDocumentDialog::PDFCreateBitonalDocumentDialog(const pdf::PDFDoc | ||||
|     updateUi(); | ||||
|     pdf::PDFWidgetUtils::style(this); | ||||
|  | ||||
|     ui->imageListWidget->setItemDelegate( new ImagePreviewDelegate(&m_imagesToBeConverted, this)); | ||||
|  | ||||
|     loadImages(); | ||||
| } | ||||
|  | ||||
| @@ -90,9 +198,52 @@ void PDFCreateBitonalDocumentDialog::loadImages() | ||||
|     ui->imageListWidget->setIconSize(iconSize); | ||||
|     QSize imageSize = iconSize * ui->imageListWidget->devicePixelRatioF(); | ||||
|  | ||||
|     pdf::PDFCMSGeneric genericCms; | ||||
|  | ||||
|     int i = 0; | ||||
|     for (pdf::PDFObjectReference reference : m_imageReferences) | ||||
|     { | ||||
|         if (i++>10) | ||||
|         { | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         std::optional<pdf::PDFImage> pdfImage = getImageFromReference(reference); | ||||
|         if (!pdfImage) | ||||
|         { | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         pdf::PDFCMSGeneric genericCms; | ||||
|         pdf::PDFRenderErrorReporterDummy errorReporter; | ||||
|         QImage image = pdfImage->getImage(&genericCms, &errorReporter, nullptr); | ||||
|         if (image.isNull()) | ||||
|         { | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         QListWidgetItem* item = new QListWidgetItem(ui->imageListWidget); | ||||
|         image = image.scaled(imageSize.width(), imageSize.height(), Qt::KeepAspectRatio, Qt::FastTransformation); | ||||
|         item->setIcon(QIcon(QPixmap::fromImage(image))); | ||||
|         Qt::ItemFlags flags = item->flags(); | ||||
|         flags.setFlag(Qt::ItemIsEditable, true); | ||||
|         item->setFlags(flags); | ||||
|  | ||||
|         ImageConversionInfo imageConversionInfo; | ||||
|         imageConversionInfo.imageReference = reference; | ||||
|         imageConversionInfo.conversionEnabled = true; | ||||
|         m_imagesToBeConverted.push_back(imageConversionInfo); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void PDFCreateBitonalDocumentDialog::updateUi() | ||||
| { | ||||
|     ui->thresholdEditBox->setEnabled(ui->manualThresholdRadioButton->isChecked()); | ||||
|  | ||||
|     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_processed && !m_conversionInProgress); | ||||
|     ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(!m_conversionInProgress); | ||||
|     m_createBitonalDocumentButton->setEnabled(!m_conversionInProgress); | ||||
| } | ||||
|  | ||||
| std::optional<pdf::PDFImage> PDFCreateBitonalDocumentDialog::getImageFromReference(pdf::PDFObjectReference reference) const | ||||
| { | ||||
|     std::optional<pdf::PDFImage> pdfImage; | ||||
|     pdf::PDFObject imageObject = m_document->getObjectByReference(reference); | ||||
| @@ -101,7 +252,7 @@ void PDFCreateBitonalDocumentDialog::loadImages() | ||||
|     if (!imageObject.isStream()) | ||||
|     { | ||||
|         // Image is not stream | ||||
|             continue; | ||||
|         return pdfImage; | ||||
|     } | ||||
|  | ||||
|     const pdf::PDFStream* stream = imageObject.getStream(); | ||||
| @@ -127,36 +278,10 @@ void PDFCreateBitonalDocumentDialog::loadImages() | ||||
|     } | ||||
|     catch (pdf::PDFException) | ||||
|     { | ||||
|             continue; | ||||
|         // Do nothing | ||||
|     } | ||||
|  | ||||
|         QImage image = pdfImage->getImage(&genericCms, &errorReporter, nullptr); | ||||
|  | ||||
|         if (image.isNull()) | ||||
|         { | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         QListWidgetItem* item = new QListWidgetItem(ui->imageListWidget); | ||||
|         QWidget* widget = new QWidget; | ||||
|         QHBoxLayout* layout = new QHBoxLayout(widget); | ||||
|         QCheckBox* checkbox = new QCheckBox(widget); | ||||
|         layout->addWidget(checkbox); | ||||
|  | ||||
|         image = image.scaled(imageSize.width(), imageSize.height(), Qt::KeepAspectRatio, Qt::FastTransformation); | ||||
|         item->setIcon(QIcon(QPixmap::fromImage(image))); | ||||
|  | ||||
|         ui->imageListWidget->setItemWidget(item, widget); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void PDFCreateBitonalDocumentDialog::updateUi() | ||||
| { | ||||
|     ui->thresholdEditBox->setEnabled(ui->manualThresholdRadioButton->isChecked()); | ||||
|  | ||||
|     ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(m_processed && !m_conversionInProgress); | ||||
|     ui->buttonBox->button(QDialogButtonBox::Cancel)->setEnabled(!m_conversionInProgress); | ||||
|     m_createBitonalDocumentButton->setEnabled(!m_conversionInProgress); | ||||
|     return pdfImage; | ||||
| } | ||||
|  | ||||
| }   // namespace pdfviewer | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| #include "pdfcms.h" | ||||
| #include "pdfdocument.h" | ||||
| #include "pdfobjectutils.h" | ||||
| #include "pdfimage.h" | ||||
|  | ||||
| #include <QDialog> | ||||
| #include <QFuture> | ||||
| @@ -43,6 +44,12 @@ public: | ||||
|  | ||||
|     pdf::PDFDocument takeBitonaldDocument() { return qMove(m_bitonalDocument); } | ||||
|  | ||||
|     struct ImageConversionInfo | ||||
|     { | ||||
|         pdf::PDFObjectReference imageReference; | ||||
|         bool conversionEnabled = true; | ||||
|     }; | ||||
|  | ||||
| private: | ||||
|     void createBitonalDocument(); | ||||
|     void onCreateBitonalDocumentButtonClicked(); | ||||
| @@ -50,6 +57,8 @@ private: | ||||
|  | ||||
|     void updateUi(); | ||||
|  | ||||
|     std::optional<pdf::PDFImage> getImageFromReference(pdf::PDFObjectReference reference) const; | ||||
|  | ||||
|     Ui::PDFCreateBitonalDocumentDialog* ui; | ||||
|     const pdf::PDFDocument* m_document; | ||||
|     const pdf::PDFCMS* m_cms; | ||||
| @@ -60,7 +69,7 @@ private: | ||||
|     pdf::PDFDocument m_bitonalDocument; | ||||
|     pdf::PDFObjectClassifier m_classifier; | ||||
|     std::vector<pdf::PDFObjectReference> m_imageReferences; | ||||
|     std::vector<pdf::PDFObjectReference> m_imagesToBeConvertedReferences; | ||||
|     std::vector<ImageConversionInfo> m_imagesToBeConverted; | ||||
| }; | ||||
|  | ||||
| }   // namespace pdfviewer | ||||
|   | ||||
		Reference in New Issue
	
	Block a user