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