Engauge Digitizer 2
Loading...
Searching...
No Matches
DlgSettingsDigitizeCurve.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"
9#include "CursorFactory.h"
10#include "CursorSize.h"
13#include "EngaugeAssert.h"
14#include "Logger.h"
15#include "MainWindow.h"
16#include "PointStyle.h"
17#include <QCheckBox>
18#include <QComboBox>
19#include <QGraphicsPixmapItem>
20#include <QGridLayout>
21#include <QGraphicsScene>
22#include <QGroupBox>
23#include <QLabel>
24#include <qmath.h>
25#include <QRadioButton>
26#include <QSpinBox>
27#include "Segment.h"
28#include "SegmentFactory.h"
29#include "ViewPreview.h"
30
31const int IMAGE_WIDTH = 100;
32const int IMAGE_HEIGHT = 100;
33const int MINIMUM_HEIGHT = 450;
34const int INNER_RADIUS_MAX = 64;
35const int INNER_RADIUS_MIN = 0;
36const int LINE_LENGTH_MIN = 2; // Min length of one line in the cursor, in pixels
37const int LINE_WIDTH_MAX = 32;
38const int LINE_WIDTH_MIN = 1;
39
41 DlgSettingsAbstractBase (tr ("Digitize Curve"),
42 "DlgSettingsDigitizeCurve",
43 mainWindow),
44 m_scenePreview (nullptr),
45 m_viewPreview (nullptr),
46 m_modelDigitizeCurveBefore (nullptr),
47 m_modelDigitizeCurveAfter (nullptr)
48{
49 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::DlgSettingsDigitizeCurve";
50
51 QWidget *subPanel = createSubPanel ();
52 finishPanel (subPanel);
53}
54
56{
57 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::~DlgSettingsDigitizeCurve";
58}
59
60void DlgSettingsDigitizeCurve::createControls (QGridLayout *layout,
61 int &row)
62{
63 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::createControls";
64
65 m_boxCursor = new QGroupBox (tr ("Cursor"));
66 layout->addWidget (m_boxCursor, row++, 1, 1, 2);
67
68 // Layout inside cursor group box
69 QGridLayout *layoutCursor = new QGridLayout;
70 m_boxCursor->setLayout (layoutCursor);
71 int rowCursor = 0;
72
73 QLabel *labelCursorType = new QLabel(QString ("%1:").arg (tr ("Type")));
74 layoutCursor->addWidget (labelCursorType, rowCursor, 0);
75
76 m_btnStandard = new QRadioButton (tr ("Standard cross"));
77 m_btnStandard->setWhatsThis (tr ("Selects the standard cross cursor"));
78 layoutCursor->addWidget (m_btnStandard, rowCursor++, 1);
79 connect (m_btnStandard, SIGNAL (toggled (bool)), this, SLOT (slotCursorStandard(bool)));
80
81 m_btnCustom = new QRadioButton (tr ("Custom cross"));
82 m_btnCustom->setWhatsThis (tr ("Selects a custom cursor based on the settings selected below"));
83 layoutCursor->addWidget (m_btnCustom, rowCursor++, 1);
84 connect (m_btnCustom, SIGNAL (toggled (bool)), this, SLOT (slotCursorCustom(bool)));
85
86 QLabel *labelSize = new QLabel(QString ("%1:").arg (tr ("Size (pixels)")));
87 layoutCursor->addWidget (labelSize, rowCursor, 0);
88
89 m_cmbSize = new QComboBox;
90 m_cmbSize->addItem (QString::number (CursorSizeToPixels (CURSOR_SIZE_16)), QVariant (CURSOR_SIZE_16));
91 m_cmbSize->addItem (QString::number (CursorSizeToPixels (CURSOR_SIZE_32)), QVariant (CURSOR_SIZE_32));
92 m_cmbSize->addItem (QString::number (CursorSizeToPixels (CURSOR_SIZE_48)), QVariant (CURSOR_SIZE_48));
93 m_cmbSize->addItem (QString::number (CursorSizeToPixels (CURSOR_SIZE_64)), QVariant (CURSOR_SIZE_64));
94 ENGAUGE_ASSERT (m_cmbSize->count() == NUM_CURSOR_SIZES);
95 m_cmbSize->setWhatsThis (tr ("Horizontal and vertical size of the cursor in pixels"));
96 layoutCursor->addWidget (m_cmbSize, rowCursor++, 1);
97 connect (m_cmbSize, SIGNAL (currentIndexChanged (const QString &)), this, SLOT (slotCursorSize (const QString &)));
98
99 QLabel *labelInnerRadius = new QLabel(QString ("%1:").arg (tr ("Inner radius (pixels)")));
100 layoutCursor->addWidget (labelInnerRadius, rowCursor, 0);
101
102 m_spinInnerRadius = new QSpinBox;
103 m_spinInnerRadius->setRange (INNER_RADIUS_MIN, INNER_RADIUS_MAX);
104 m_spinInnerRadius->setWhatsThis (tr ("Radius of circle at the center of the cursor that will remain empty"));
105 layoutCursor->addWidget (m_spinInnerRadius, rowCursor++, 1);
106 connect (m_spinInnerRadius, SIGNAL (valueChanged(const QString &)), this, SLOT (slotCursorInnerRadius (const QString &)));
107
108 QLabel *labelLineWidth = new QLabel(QString ("%1:").arg (tr ("Line width (pixels)")));
109 layoutCursor->addWidget (labelLineWidth, rowCursor, 0);
110
111 m_spinLineWidth = new QSpinBox;
112 m_spinLineWidth->setRange (LINE_WIDTH_MIN, LINE_WIDTH_MAX);
113 m_spinLineWidth->setWhatsThis (tr ("Width of each arm of the cross of the cursor"));
114 layoutCursor->addWidget (m_spinLineWidth, rowCursor++, 1);
115 connect (m_spinLineWidth, SIGNAL (valueChanged(const QString &)), this, SLOT (slotCursorLineWidth (const QString &)));
116}
117
119{
120}
121
122void DlgSettingsDigitizeCurve::createPreview (QGridLayout *layout,
123 int &row)
124{
125 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::createPreview";
126
127 QLabel *labelPreview = new QLabel (tr ("Preview"));
128 layout->addWidget (labelPreview, row++, 0, 1, 4);
129
130 m_scenePreview = new QGraphicsScene (this);
131 m_scenePreview->setSceneRect(0,
132 0,
135
136 m_viewPreview = new ViewPreview (m_scenePreview,
138 this);
139 m_viewPreview->setWhatsThis (tr ("Preview window showing the currently selected cursor.\n\n"
140 "Drag the cursor over this area to see the effects of the current settings on the cursor shape."));
141 m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
142 m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
143 m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
144
145 layout->addWidget (m_viewPreview, row++, 0, 1, 4);
146}
147
149{
150 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::createSubPanel";
151
152 QWidget *subPanel = new QWidget ();
153 QGridLayout *layout = new QGridLayout (subPanel);
154 subPanel->setLayout (layout);
155
156 layout->setColumnStretch (0, 1); // Empty first column
157 layout->setColumnStretch (1, 0); // Labels
158 layout->setColumnStretch (2, 0); // User controls
159 layout->setColumnStretch (3, 1); // Empty last column
160
161 int row = 0;
162 createControls(layout, row);
163 createPreview (layout, row);
164
165 return subPanel;
166}
167
169{
170 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::handleOk";
171
173 cmdMediator ().document(),
174 *m_modelDigitizeCurveBefore,
175 *m_modelDigitizeCurveAfter);
176 cmdMediator ().push (cmd);
177
178 hide ();
179}
180
182{
183 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::load";
184
186
187 // Flush old data
188 delete m_modelDigitizeCurveBefore;
189 delete m_modelDigitizeCurveAfter;
190
191 // Save new data
192 m_modelDigitizeCurveBefore = new DocumentModelDigitizeCurve (cmdMediator.document());
193 m_modelDigitizeCurveAfter = new DocumentModelDigitizeCurve (cmdMediator.document());
194
195 // Sanity checks. Incoming defaults must be acceptable to the local limits
197 ENGAUGE_ASSERT (INNER_RADIUS_MAX >= m_modelDigitizeCurveAfter->cursorInnerRadius ());
199 ENGAUGE_ASSERT (LINE_WIDTH_MAX >= m_modelDigitizeCurveAfter->cursorLineWidth ());
200
201 // Populate controls
202 m_btnStandard->setChecked (m_modelDigitizeCurveAfter->cursorStandardCross());
203 m_btnCustom->setChecked (!m_modelDigitizeCurveAfter->cursorStandardCross());
204 m_spinInnerRadius->setValue (m_modelDigitizeCurveAfter->cursorInnerRadius());
205 int index = m_cmbSize->findData (QVariant (m_modelDigitizeCurveAfter->cursorSize()));
206 m_cmbSize->setCurrentIndex (index);
207 m_spinLineWidth->setValue (m_modelDigitizeCurveAfter->cursorLineWidth());
208
209 updateControls();
210 enableOk (false); // Disable Ok button since there not yet any changes
211 updatePreview();
212}
213
215{
216 if (!smallDialogs) {
218 }
219}
220
221void DlgSettingsDigitizeCurve::slotCursorCustom (bool)
222{
223 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorCustom";
224
225 m_modelDigitizeCurveAfter->setCursorStandardCross(false);
226 updateControls();
227 updatePreview();
228}
229
230void DlgSettingsDigitizeCurve::slotCursorInnerRadius (const QString &)
231{
232 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorInnerRadius";
233
234 m_modelDigitizeCurveAfter->setCursorInnerRadius (m_spinInnerRadius->value());
235 updateControls();
236 updatePreview();
237}
238
239void DlgSettingsDigitizeCurve::slotCursorLineWidth (const QString &)
240{
241 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorLineWidth";
242
243 m_modelDigitizeCurveAfter->setCursorLineWidth (m_spinLineWidth->value());
244 updateControls();
245 updatePreview();
246}
247
248void DlgSettingsDigitizeCurve::slotCursorSize (const QString &)
249{
250 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorSize";
251
252 m_modelDigitizeCurveAfter->setCursorSize (static_cast<CursorSize> (m_cmbSize->currentData().toInt()));
253 updateControls();
254 updatePreview();
255}
256
257void DlgSettingsDigitizeCurve::slotCursorStandard (bool)
258{
259 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorStandard";
260
261 m_modelDigitizeCurveAfter->setCursorStandardCross(true);
262 updateControls();
263 updatePreview();
264}
265
266void DlgSettingsDigitizeCurve::updateControls()
267{
268 // Cursor has to fit into current extent
269 bool isGoodState = 2 * (m_modelDigitizeCurveAfter->cursorInnerRadius() + LINE_LENGTH_MIN) <=
270 CursorSizeToPixels (m_modelDigitizeCurveAfter->cursorSize());
272
273 m_spinInnerRadius->setEnabled (m_btnCustom->isChecked());
274 m_cmbSize->setEnabled (m_btnCustom->isChecked());
275 m_spinLineWidth->setEnabled (m_btnCustom->isChecked());
276}
277
278void DlgSettingsDigitizeCurve::updatePreview()
279{
280 LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::updatePreview";
281
283 QCursor cursor = cursorFactory.generate (*m_modelDigitizeCurveAfter);
284 m_viewPreview->setCursor (cursor);
285}
int CursorSizeToPixels(CursorSize cursorSize)
CursorSize
Custom cursor sizes supported on all platforms for the most part, according to QCursor documentation.
Definition CursorSize.h:11
@ CURSOR_SIZE_48
Definition CursorSize.h:14
@ CURSOR_SIZE_32
Definition CursorSize.h:13
@ CURSOR_SIZE_16
Definition CursorSize.h:12
@ CURSOR_SIZE_64
Definition CursorSize.h:15
@ NUM_CURSOR_SIZES
Definition CursorSize.h:16
const int MINIMUM_HEIGHT
const int INNER_RADIUS_MIN
const int LINE_WIDTH_MAX
const int LINE_LENGTH_MIN
const int IMAGE_WIDTH
const int INNER_RADIUS_MAX
const int IMAGE_HEIGHT
const int MINIMUM_HEIGHT
const int LINE_WIDTH_MIN
#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 DlgSettingsDigitizeCurve.
Create standard cross cursor, or custom cursor, according to settings.
QCursor generate(const DocumentModelDigitizeCurve &modelDigitizeCurve) const
Factory method to generate standard or custom cursor.
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.
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.
DlgSettingsDigitizeCurve(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.
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.
Model for DlgSettingsDigitizeCurve and CmdSettingsDigitizeCurve.
void setCursorStandardCross(bool cursorStandardCross)
Set method for cursor type.
void setCursorLineWidth(int lineWidth)
Set method for cursor line width.
void setCursorInnerRadius(int innerRadius)
Set method for cursor inner radius.
CursorSize cursorSize() const
Get method for cursor size.
int cursorInnerRadius() const
Get method for cursor inner radius.
bool cursorStandardCross() const
Get method for cursor type.
int cursorLineWidth() const
Get method for cursor line width.
void setCursorSize(CursorSize cursorSize)
Set method for cursor size.
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