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