Engauge Digitizer 2
Loading...
Searching...
No Matches
DlgImportCroppingPdf.cpp
Go to the documentation of this file.
1/******************************************************************************************************
2 * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3 * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4 * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5 ******************************************************************************************************/
6
8#include "EngaugeAssert.h"
9#include "Logger.h"
10#include "MainWindow.h"
11#include "PdfCropping.h"
12#include "poppler-qt5.h"
13#include <QApplication>
14#include <QGraphicsPixmapItem>
15#include <QGraphicsScene>
16#include <QGridLayout>
17#include <QImage>
18#include <QLabel>
19#include <QLayout>
20#include <QPushButton>
21#include <QSettings>
22#include <QSpinBox>
23#include <QTimer>
24#include "Settings.h"
25#include "ViewPreview.h"
26
27using namespace Poppler;
28
29int DlgImportCroppingPdf::MINIMUM_DIALOG_WIDTH = 350;
30int DlgImportCroppingPdf::MINIMUM_PREVIEW_HEIGHT = 200;
31const int X_TOP_LEFT = 0, Y_TOP_LEFT = 0;
32const int WIDTH = -1, HEIGHT = -1; // Negative values give full page
33const int FIRST_PAGE_1_BASED = 1;
34const int SMALLEST_DELAY_MS = 500; // Below 500 triggers "double jump" bug in linux
35
36DlgImportCroppingPdf::DlgImportCroppingPdf(const Poppler::Document &document,
37 int resolution) :
38 m_document (document),
39 m_resolution (resolution),
40 m_pixmap (nullptr)
41{
42 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::DlgImportCroppingPdf";
43
44 setWindowTitle (tr ("PDF File Import Cropping"));
45 setModal (true);
46
47 QWidget *subPanel = new QWidget ();
48 QGridLayout *layout = new QGridLayout (subPanel);
49 subPanel->setLayout (layout);
50
51 int row = 0;
52
53 createTimer ();
54 createPageSpinner (layout, row);
55 createPreview (layout, row);
56 finishPanel (subPanel);
57 updatePreview ();
58
59 // Bring the two middle columns together
60 layout->setColumnStretch (0, 1);
61 layout->setColumnStretch (1, 0);
62 layout->setColumnStretch (2, 0);
63 layout->setColumnStretch (3, 1);
64}
65
67{
68 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::~DlgImportCroppingPdf";
69}
70
71void DlgImportCroppingPdf::createPageSpinner (QGridLayout *layout,
72 int &row)
73{
74 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::createPageSpinner";
75
76 const int MIN_WIDTH_SPINNER = 90;
77
78 QLabel *labelPage = new QLabel (QString ("%1:").arg (tr ("Page")));
79 layout->addWidget (labelPage, row, 1, 1, 1);
80
81 m_spinPage = new QSpinBox;
82 m_spinPage->setMinimumWidth (MIN_WIDTH_SPINNER);
83 m_spinPage->setWhatsThis (tr ("Page number that will be imported"));
84 m_spinPage->setRange (1, m_document.numPages());
85 layout->addWidget (m_spinPage, row++, 2, 1, 1);
86 connect (m_spinPage, SIGNAL (valueChanged (int)), this, SLOT (slotPage (int)));
87}
88
89void DlgImportCroppingPdf::createPdfCropping ()
90{
91 // Create frame that shows what will be included, and what will be excluded, during the import
92 m_pdfCropping = new PdfCropping (*m_scenePreview,
93 *m_viewPreview);
94}
95
96void DlgImportCroppingPdf::createPreview (QGridLayout *layout,
97 int &row)
98{
99 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::createPreview";
100
101 QLabel *labelPreview = new QLabel (tr ("Preview"));
102 layout->addWidget (labelPreview, row++, 0, 1, 1, Qt::AlignLeft);
103
104 m_scenePreview = new QGraphicsScene (this);
105 m_viewPreview = new ViewPreview (m_scenePreview,
107 this);
108 m_viewPreview->setWhatsThis (tr ("Preview window that shows what part of the image will be imported. "
109 "The image portion inside the rectangular frame will be imported from the currently selected page. "
110 "The frame can be moved and resized by dragging the corner handles."));
111 m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
112 m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
113 m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
114 layout->addWidget (m_viewPreview, row++, 0, 1, 4);
115
116 // More preview initialization
117 initializeFrameGeometryAndPixmap (); // Before first call to updatePreview
118 createPdfCropping ();
119}
120
121void DlgImportCroppingPdf::createTimer ()
122{
123 m_timer = new QTimer;
124 m_timer->setSingleShot (true);
125 connect (m_timer, SIGNAL (timeout ()), this, SLOT (slotTimeout ()));
126}
127
128void DlgImportCroppingPdf::finishPanel (QWidget *subPanel)
129{
130 const int STRETCH_OFF = 0, STRETCH_ON = 1;
131
132 QVBoxLayout *panelLayout = new QVBoxLayout (this);
133
134 setMinimumWidth (MINIMUM_DIALOG_WIDTH);
135 setLayout (panelLayout);
136
137 panelLayout->addWidget (subPanel);
138 panelLayout->setStretch (panelLayout->count () - 1, STRETCH_ON);
139
140 QWidget *panelButtons = new QWidget (this);
141 QHBoxLayout *buttonLayout = new QHBoxLayout (panelButtons);
142
143 QHBoxLayout *layoutRightSide = new QHBoxLayout;
144
145 QWidget *widgetRightSide = new QWidget;
146 widgetRightSide->setLayout (layoutRightSide);
147 buttonLayout->addWidget (widgetRightSide);
148
149 QSpacerItem *spacerExpanding = new QSpacerItem (40, 5, QSizePolicy::Expanding, QSizePolicy::Expanding);
150 layoutRightSide->addItem (spacerExpanding);
151
152 m_btnOk = new QPushButton (tr ("Ok"));
153 layoutRightSide->addWidget (m_btnOk, 0, Qt::AlignRight);
154 connect (m_btnOk, SIGNAL (released ()), this, SLOT (slotOk ()));
155
156 QSpacerItem *spacerFixed = new QSpacerItem (40, 5, QSizePolicy::Fixed, QSizePolicy::Fixed);
157 layoutRightSide->addItem (spacerFixed);
158
159 m_btnCancel = new QPushButton (tr ("Cancel"));
160 layoutRightSide->addWidget (m_btnCancel, 0, Qt::AlignRight);
161 connect (m_btnCancel, SIGNAL (released ()), this, SLOT (slotCancel ()));
162
163 panelLayout->addWidget (panelButtons, STRETCH_ON);
164 panelLayout->setStretch (panelLayout->count () - 1, STRETCH_OFF);
165}
166
168{
169 // If the entire page was to be returned, then this method would simply return m_image. However, only the framed
170 // portion is to be returned
171 ENGAUGE_ASSERT (m_pdfCropping != nullptr);
172 QRectF rectFramePixels = m_pdfCropping->frameRect ();
173
174 return m_image.copy (rectFramePixels.toRect ());
175}
176
177void DlgImportCroppingPdf::initializeFrameGeometryAndPixmap ()
178{
179 m_image = loadImage (FIRST_PAGE_1_BASED);
180 QGraphicsPixmapItem *pixmap = new QGraphicsPixmapItem (QPixmap::fromImage (m_image));
181 m_scenePreview->addItem (pixmap);
182
183 // Force resize so image fills preview area. We do this only once initially for speed
184 m_viewPreview->setSceneRect (pixmap->boundingRect ());
185}
186
187QImage DlgImportCroppingPdf::loadImage (int page1Based) const
188{
189 QImage image;
190
191 int page0Based = page1Based - 1;
192 Page *page = m_document.page (page0Based);
193 if (page != nullptr) {
194
195 image = page->renderToImage (m_resolution,
196 m_resolution,
199 WIDTH,
200 HEIGHT);
201
202 delete page;
203 }
204
205 return image;
206}
207
208void DlgImportCroppingPdf::saveGeometryToSettings()
209{
210 // Store the settings for use by showEvent
211 QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
212 settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
213 settings.setValue (SETTINGS_IMPORT_CROPPING_POS, saveGeometry ());
214 settings.endGroup();
215}
216
217void DlgImportCroppingPdf::showEvent (QShowEvent * /* event */)
218{
219 QSettings settings (SETTINGS_ENGAUGE, SETTINGS_DIGITIZER);
220 settings.beginGroup (SETTINGS_GROUP_IMPORT_CROPPING);
221 if (settings.contains (SETTINGS_IMPORT_CROPPING_POS)) {
222
223 // Restore the settings that were stored by the last call to saveGeometryToSettings
224 restoreGeometry (settings.value (SETTINGS_IMPORT_CROPPING_POS).toByteArray ());
225 }
226 settings.endGroup ();
227}
228
229void DlgImportCroppingPdf::slotCancel ()
230{
231 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::slotCancel";
232
233 // Restore cursor in case updatePreview has not already completed and then restored it
234 QApplication::restoreOverrideCursor ();
235
236 setResult (QDialog::Rejected);
237 saveGeometryToSettings();
238 hide();
239}
240
241void DlgImportCroppingPdf::slotOk ()
242{
243 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::slotOk";
244
245 // Restore cursor in case updatePreview has not already completed and then restored it
246 QApplication::restoreOverrideCursor ();
247
248 setResult (QDialog::Accepted);
249 saveGeometryToSettings();
250 hide();
251}
252
253void DlgImportCroppingPdf::slotPage (int page)
254{
255 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::slotPage"
256 << " page=" << page
257 << " stepBy=" << m_spinPage->singleStep ();
258
259 // Show wait cursor until slow calculations are over
260 QApplication::setOverrideCursor (Qt::WaitCursor);
261
262 m_timer->start (SMALLEST_DELAY_MS);
263}
264
265void DlgImportCroppingPdf::slotTimeout ()
266{
267 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::slotTimeout";
268
269 updatePreview ();
270}
271
272void DlgImportCroppingPdf::updatePreview ()
273{
274 LOG4CPP_INFO_S ((*mainCat)) << "DlgImportCroppingPdf::updatePreview";
275
276 if (m_pixmap != nullptr) {
277 m_scenePreview->removeItem (m_pixmap);
278 }
279
280 m_image = loadImage (m_spinPage->value ());
281 m_pixmap = new QGraphicsPixmapItem (QPixmap::fromImage (m_image));
282 m_scenePreview->addItem (m_pixmap);
283
284 // Calculations for preview updating are now over
285 QApplication::restoreOverrideCursor ();
286}
const int X_TOP_LEFT
const int SMALLEST_DELAY_MS
const int WIDTH
const int FIRST_PAGE_1_BASED
const int HEIGHT
const int Y_TOP_LEFT
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) define ENGAUGE...
log4cpp::Category * mainCat
Definition Logger.cpp:14
const QString SETTINGS_ENGAUGE
const QString SETTINGS_GROUP_IMPORT_CROPPING
const QString SETTINGS_IMPORT_CROPPING_POS
const QString SETTINGS_DIGITIZER
virtual void showEvent(QShowEvent *event)
Do preparation before dialog is displayed.
QImage image() const
Image that was selected. Value is null if loading failed.
DlgImportCroppingPdf(const Poppler::Document &document, int resolution)
Single constructor.
This class shows a frame around the selected portion of the pdf import preview window.
Definition PdfCropping.h:25
QRectF frameRect() const
Frame rectangle selected by user.
Class that modifies QGraphicsView to automatically expand/shrink the view to fit the window,...
Definition ViewPreview.h:15
@ VIEW_ASPECT_RATIO_ONE_TO_ONE
Definition ViewPreview.h:23
#define LOG4CPP_INFO_S(logger)
Definition convenience.h:18