Engauge Digitizer 2
Loading...
Searching...
No Matches
DlgSettingsPointMatch.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
7#include "CmdMediator.h"
10#include "EngaugeAssert.h"
11#include "Logger.h"
12#include "MainWindow.h"
13#include <QComboBox>
14#include <QGraphicsEllipseItem>
15#include <QGraphicsPixmapItem>
16#include <QGraphicsRectItem>
17#include <QGraphicsScene>
18#include <QGridLayout>
19#include <QLabel>
20#include <qmath.h>
21#include <QPen>
22#include <QSpinBox>
23#include "ViewPreview.h"
24
25const int MINIMUM_HEIGHT = 480;
26const int POINT_SIZE_MAX = 1024;
27const int POINT_SIZE_MIN = 5;
28
30 DlgSettingsAbstractBase (tr ("Point Match"),
31 "DlgSettingsPointMatch",
32 mainWindow),
33 m_scenePreview (nullptr),
34 m_viewPreview (nullptr),
35 m_circle (nullptr),
36 m_modelPointMatchBefore (nullptr),
37 m_modelPointMatchAfter (nullptr)
38{
39 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::DlgSettingsPointMatch";
40
43}
44
46{
47 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::~DlgSettingsPointMatch";
48}
49
50QPointF DlgSettingsPointMatch::boxPositionConstraint(const QPointF &posIn)
51{
52 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::boxPositionConstraint";
53
54 double radius = radiusAlongDiagonal();
55 double diameter = 2.0 * radius;
56
57 // Do not move any part outside the preview window or else ugly, and unwanted, shifting will occur
58 QPointF pos (posIn);
59 if (pos.x() - radius < 0) {
60 pos.setX (radius);
61 }
62
63 if (pos.y() - radius < 0) {
64 pos.setY (radius);
65 }
66
67 if (pos.x() + diameter > m_scenePreview->sceneRect().width ()) {
68 pos.setX (m_scenePreview->sceneRect().width() - diameter);
69 }
70
71 if (pos.y() + diameter > m_scenePreview->sceneRect().height ()) {
72 pos.setY (m_scenePreview->sceneRect().height() - diameter);
73 }
74
75 return pos;
76}
77
78void DlgSettingsPointMatch::createControls (QGridLayout *layout,
79 int &row)
80{
81 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::createControls";
82
83 QLabel *labelPointSize = new QLabel (QString ("%1:").arg (tr ("Maximum point size (pixels)")));
84 layout->addWidget (labelPointSize, row, 1);
85
86 m_spinPointSize = new QSpinBox;
87 m_spinPointSize->setWhatsThis (tr ("Select a maximum point size in pixels.\n\n"
88 "Sample match points must fit within a square box, around the cursor, having width and height "
89 "equal to this maximum.\n\n"
90 "This size is also used to determine if a region of pixels that are on, in the processed image, "
91 "should be ignored since that region is wider or taller than this limit.\n\n"
92 "This value has a lower limit"));
93 m_spinPointSize->setMinimum (POINT_SIZE_MIN);
94 m_spinPointSize->setMaximum (POINT_SIZE_MAX);
95 connect (m_spinPointSize, SIGNAL (valueChanged (int)), this, SLOT (slotMaxPointSize (int)));
96 layout->addWidget (m_spinPointSize, row++, 2);
97
98 QLabel *labelAcceptedPointColor = new QLabel (QString ("%1:").arg (tr ("Accepted point color")));
99 layout->addWidget (labelAcceptedPointColor, row, 1);
100
101 m_cmbAcceptedPointColor = new QComboBox;
102 m_cmbAcceptedPointColor->setWhatsThis (tr ("Select a color for matched points that are accepted"));
103 populateColorComboWithTransparent (*m_cmbAcceptedPointColor);
104 connect (m_cmbAcceptedPointColor, SIGNAL (activated (const QString &)), this, SLOT (slotAcceptedPointColor (const QString &))); // activated() ignores code changes
105 layout->addWidget (m_cmbAcceptedPointColor, row++, 2);
106
107 QLabel *labelRejectedPointColor = new QLabel (QString ("%1:").arg (tr ("Rejected point color")));
108 layout->addWidget (labelRejectedPointColor, row, 1);
109
110 m_cmbRejectedPointColor = new QComboBox;
111 m_cmbRejectedPointColor->setWhatsThis (tr ("Select a color for matched points that are rejected"));
112 populateColorComboWithTransparent (*m_cmbRejectedPointColor);
113 connect (m_cmbRejectedPointColor, SIGNAL (activated (const QString &)), this, SLOT (slotRejectedPointColor (const QString &))); // activated() ignores code changes
114 layout->addWidget (m_cmbRejectedPointColor, row++, 2);
115
116 QLabel *labelCandidatePointColor = new QLabel (QString ("%1:").arg (tr ("Candidate point color")));
117 layout->addWidget (labelCandidatePointColor, row, 1);
118
119 m_cmbCandidatePointColor = new QComboBox;
120 m_cmbCandidatePointColor->setWhatsThis (tr ("Select a color for the point being decided upon"));
121 populateColorComboWithTransparent (*m_cmbCandidatePointColor);
122 connect (m_cmbCandidatePointColor, SIGNAL (activated (const QString &)), this, SLOT (slotCandidatePointColor (const QString &))); // activated() ignores code changes
123 layout->addWidget (m_cmbCandidatePointColor, row++, 2);
124}
125
129
130void DlgSettingsPointMatch::createPreview (QGridLayout *layout,
131 int &row)
132{
133 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::createPreview";
134
135 QLabel *labelPreview = new QLabel (tr ("Preview"));
136 layout->addWidget (labelPreview, row++, 0, 1, 4);
137
138 m_scenePreview = new QGraphicsScene (this);
139 m_viewPreview = new ViewPreview (m_scenePreview,
141 this);
142 m_viewPreview->setWhatsThis (tr ("Preview window shows how current settings affect "
143 "point matching, and how the marked and candidate points are displayed.\n\nThe points are separated "
144 "by the point separation value, and the maximum point size is shown as a box in the center"));
145 m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
146 m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
147 m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
148 connect (m_viewPreview, SIGNAL (signalMouseMove (QPointF)), this, SLOT (slotMouseMove (QPointF)));
149
150 layout->addWidget (m_viewPreview, row++, 0, 1, 4);
151}
152
154{
155 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::createSubPanel";
156
157 QWidget *subPanel = new QWidget ();
159 subPanel->setLayout (layout);
160
161 layout->setColumnStretch(0, 1); // Empty column
162 layout->setColumnStretch(1, 0); // Labels
163 layout->setColumnStretch(2, 0); // Controls
164 layout->setColumnStretch(3, 1); // Empty column
165
166 int row = 0;
167 createControls (layout, row);
168 createPreview (layout, row);
169 createTemplate ();
170
171 return subPanel;
172}
173
174void DlgSettingsPointMatch::createTemplate ()
175{
176 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::createTemplate";
177
178 QPen pen (QBrush (Qt::black), 0);
179
180 m_circle = new QGraphicsEllipseItem;
181 m_circle->setPen (pen);
182 m_circle->setZValue (100);
183 m_scenePreview->addItem (m_circle);
184}
185
187{
188 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::handleOk";
189
191 cmdMediator ().document(),
192 *m_modelPointMatchBefore,
193 *m_modelPointMatchAfter);
194 cmdMediator ().push (cmd);
195
196 hide ();
197}
198
199void DlgSettingsPointMatch::initializeBox ()
200{
201 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::initializeBox";
202
203 m_circle->setPos (cmdMediator().document().pixmap().width () / 2.0,
204 cmdMediator().document().pixmap().height () / 2.0); // Initially box is in center of preview
205}
206
208{
209 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::load";
210
212
213 // Flush old data
214 delete m_modelPointMatchBefore;
215 delete m_modelPointMatchAfter;
216
217 // Save new data
218 m_modelPointMatchBefore = new DocumentModelPointMatch (cmdMediator.document());
219 m_modelPointMatchAfter = new DocumentModelPointMatch (cmdMediator.document());
220
221 // Sanity checks. Incoming defaults must be acceptable to the local limits
223 ENGAUGE_ASSERT (POINT_SIZE_MAX > m_modelPointMatchAfter->maxPointSize());
224
225 // Populate controls
226 m_spinPointSize->setValue(qFloor (m_modelPointMatchAfter->maxPointSize()));
227
228 int indexAccepted = m_cmbAcceptedPointColor->findData(QVariant(m_modelPointMatchAfter->paletteColorAccepted()));
230 m_cmbAcceptedPointColor->setCurrentIndex(indexAccepted);
231
232 int indexCandidate = m_cmbCandidatePointColor->findData(QVariant(m_modelPointMatchAfter->paletteColorCandidate()));
234 m_cmbCandidatePointColor->setCurrentIndex(indexCandidate);
235
236 int indexRejected = m_cmbRejectedPointColor->findData(QVariant(m_modelPointMatchAfter->paletteColorRejected()));
238 m_cmbRejectedPointColor->setCurrentIndex(indexRejected);
239
240 initializeBox ();
241
242 // Fix the preview size using an invisible boundary
243 QGraphicsRectItem *boundary = m_scenePreview->addRect (QRect (0,
244 0,
245 cmdMediator.document().pixmap().width (),
246 cmdMediator.document().pixmap().height ()));
247 boundary->setVisible (false);
248
249 m_scenePreview->addPixmap (cmdMediator.document().pixmap());
250
251 updateControls();
252 enableOk (false); // Disable Ok button since there not yet any changes
253 updatePreview();
254}
255
256double DlgSettingsPointMatch::radiusAlongDiagonal () const
257{
258 double maxPointSize = m_modelPointMatchAfter->maxPointSize();
259
260 return qSqrt (2.0) * maxPointSize / 2.0;
261}
262
264{
265 if (!smallDialogs) {
267 }
268}
269
270void DlgSettingsPointMatch::slotAcceptedPointColor (const QString &)
271{
272 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::slotAcceptedPointColor";
273
274 m_modelPointMatchAfter->setPaletteColorAccepted(static_cast<ColorPalette> (m_cmbAcceptedPointColor->currentData().toInt()));
275
276 updateControls();
277 updatePreview();
278}
279
280void DlgSettingsPointMatch::slotCandidatePointColor (const QString &)
281{
282 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::slotCandidatePointColor";
283
284 m_modelPointMatchAfter->setPaletteColorCandidate(static_cast<ColorPalette> (m_cmbCandidatePointColor->currentData().toInt()));
285 updateControls();
286 updatePreview();
287}
288
289void DlgSettingsPointMatch::slotMaxPointSize (int maxPointSize)
290{
291 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::slotMaxPointSize";
292
293 m_modelPointMatchAfter->setMaxPointSize(maxPointSize);
294 updateControls();
295 updatePreview();
296}
297
298void DlgSettingsPointMatch::slotMouseMove (QPointF pos)
299{
300 // Move the box so it follows the mouse move, making sure to keep it entirely inside the view to
301 // prevent autoresizing by QGraphicsView
302 pos = boxPositionConstraint (pos);
303
304 m_circle->setPos (pos);
305}
306
307void DlgSettingsPointMatch::slotRejectedPointColor (const QString &)
308{
309 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsPointMatch::slotRejectedPointColor";
310
311 m_modelPointMatchAfter->setPaletteColorRejected(static_cast<ColorPalette> (m_cmbRejectedPointColor->currentData().toInt()));
312 updateControls();
313 updatePreview();
314}
315
316void DlgSettingsPointMatch::updateControls()
317{
318 // All controls in this dialog are always fully validated so the ok button is always enabled (after the first change)
319 enableOk (true);
320}
321
322void DlgSettingsPointMatch::updatePreview()
323{
324 // Geometry parameters
325 double maxPointSize = m_modelPointMatchAfter->maxPointSize();
326
327 double xLeft = -1.0 * maxPointSize / 2.0;
328 double yTop = -1.0 * maxPointSize / 2.0;
329
330 // Update circle size
331 m_circle->setRect (xLeft,
332 yTop,
333 maxPointSize,
334 maxPointSize);
335}
ColorPalette
const int MINIMUM_HEIGHT
const int INNER_RADIUS_MIN
const int POINT_SIZE_MIN
const int POINT_SIZE_MAX
const int MINIMUM_HEIGHT
#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
Command queue stack.
Definition CmdMediator.h:24
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Command for DlgSettingsPointMatch.
Abstract base class for all Settings dialogs.
void setCmdMediator(CmdMediator &cmdMediator)
Store CmdMediator for easy access by the leaf class.
void finishPanel(QWidget *subPanel, int minimumWidth=MINIMUM_DIALOG_WIDTH, int minimumHeightOrZero=0)
Add Ok and Cancel buttons to subpanel to get the whole dialog.
void populateColorComboWithTransparent(QComboBox &combo)
Add colors in color palette to combobox, with transparent entry at end.
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.
void enableOk(bool enable)
Let leaf subclass control the Ok button.
static int MINIMUM_PREVIEW_HEIGHT
Dialog layout constant that guarantees preview has sufficent room.
MainWindow & mainWindow()
Get method for MainWindow.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
DlgSettingsPointMatch(MainWindow &mainWindow)
Single constructor.
virtual void handleOk()
Process slotOk.
virtual void createOptionalSaveDefault(QHBoxLayout *layout)
Let subclass define an optional Save As Default button.
virtual QWidget * createSubPanel()
Create dialog-specific panel to which base class will add Ok and Cancel buttons.
Model for DlgSettingsPointMatch and CmdSettingsPointMatch.
void setMaxPointSize(double maxPointSize)
Set method for max point size.
void setPaletteColorCandidate(ColorPalette paletteColorCandidate)
Set method for candidate color.
ColorPalette paletteColorRejected() const
Get method for rejected color.
void setPaletteColorAccepted(ColorPalette paletteColorAccepted)
Set method for accepted color.
ColorPalette paletteColorCandidate() const
Get method for candidate color.
double maxPointSize() const
Get method for max point size.
void setPaletteColorRejected(ColorPalette paletteColorRejected)
Set method for rejected color.
ColorPalette paletteColorAccepted() const
Get method for accepted color.
QPixmap pixmap() const
Return the image that is being digitized.
Definition Document.cpp:817
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition MainWindow.h:92
Class that modifies QGraphicsView to automatically expand/shrink the view to fit the window,...
Definition ViewPreview.h:15
@ VIEW_ASPECT_RATIO_VARIABLE
Definition ViewPreview.h:22
#define LOG4CPP_INFO_S(logger)
Definition convenience.h:18