Engauge Digitizer  2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 
31 const int IMAGE_WIDTH = 100;
32 const int IMAGE_HEIGHT = 100;
33 const int MINIMUM_HEIGHT = 450;
34 const int INNER_RADIUS_MAX = 64;
35 const int INNER_RADIUS_MIN = 0;
36 const int LINE_LENGTH_MIN = 2; // Min length of one line in the cursor, in pixels
37 const int LINE_WIDTH_MAX = 32;
38 const 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 
60 void 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 
122 void 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,
133  IMAGE_WIDTH,
134  IMAGE_HEIGHT);
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 
185  setCmdMediator (cmdMediator);
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
196  ENGAUGE_ASSERT (INNER_RADIUS_MIN <= m_modelDigitizeCurveAfter->cursorInnerRadius ());
197  ENGAUGE_ASSERT (INNER_RADIUS_MAX >= m_modelDigitizeCurveAfter->cursorInnerRadius ());
198  ENGAUGE_ASSERT (LINE_WIDTH_MIN <= m_modelDigitizeCurveAfter->cursorLineWidth ());
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) {
217  setMinimumHeight (MINIMUM_HEIGHT);
218  }
219 }
220 
221 void DlgSettingsDigitizeCurve::slotCursorCustom (bool)
222 {
223  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorCustom";
224 
225  m_modelDigitizeCurveAfter->setCursorStandardCross(false);
226  updateControls();
227  updatePreview();
228 }
229 
230 void 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 
239 void 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 
248 void 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 
257 void DlgSettingsDigitizeCurve::slotCursorStandard (bool)
258 {
259  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorStandard";
260 
261  m_modelDigitizeCurveAfter->setCursorStandardCross(true);
262  updateControls();
263  updatePreview();
264 }
265 
266 void 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());
271  enableOk (isGoodState);
272 
273  m_spinInnerRadius->setEnabled (m_btnCustom->isChecked());
274  m_cmbSize->setEnabled (m_btnCustom->isChecked());
275  m_spinLineWidth->setEnabled (m_btnCustom->isChecked());
276 }
277 
278 void DlgSettingsDigitizeCurve::updatePreview()
279 {
280  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::updatePreview";
281 
282  CursorFactory cursorFactory;
283  QCursor cursor = cursorFactory.generate (*m_modelDigitizeCurveAfter);
284  m_viewPreview->setCursor (cursor);
285 }
DlgSettingsDigitizeCurve(MainWindow &mainWindow)
Single constructor.
const int LINE_WIDTH_MIN
int cursorLineWidth() const
Get method for cursor line width.
const int IMAGE_WIDTH
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
virtual void createOptionalSaveDefault(QHBoxLayout *layout)
Let subclass define an optional Save As Default button.
Create standard cross cursor, or custom cursor, according to settings.
Definition: CursorFactory.h:15
void setCursorLineWidth(int lineWidth)
Set method for cursor line width.
void setCmdMediator(CmdMediator &cmdMediator)
Store CmdMediator for easy access by the leaf class.
virtual void handleOk()
Process slotOk.
const int LINE_WIDTH_MAX
#define LOG4CPP_INFO_S(logger)
Definition: convenience.h:18
bool cursorStandardCross() const
Get method for cursor type.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
const int LINE_LENGTH_MIN
const int INNER_RADIUS_MAX
void setCursorSize(CursorSize cursorSize)
Set method for cursor size.
void finishPanel(QWidget *subPanel, int minimumWidth=MINIMUM_DIALOG_WIDTH, int minimumHeightOrZero=0)
Add Ok and Cancel buttons to subpanel to get the whole dialog.
Model for DlgSettingsDigitizeCurve and CmdSettingsDigitizeCurve.
Class that modifies QGraphicsView to automatically expand/shrink the view to fit the window...
Definition: ViewPreview.h:14
int cursorInnerRadius() const
Get method for cursor inner radius.
void setCursorInnerRadius(int innerRadius)
Set method for cursor inner radius.
const int IMAGE_HEIGHT
virtual QWidget * createSubPanel()
Create dialog-specific panel to which base class will add Ok and Cancel buttons.
log4cpp::Category * mainCat
Definition: Logger.cpp:14
static int MINIMUM_PREVIEW_HEIGHT
Dialog layout constant that guarantees preview has sufficent room.
void enableOk(bool enable)
Let leaf subclass control the Ok button.
int CursorSizeToPixels(CursorSize cursorSize)
Definition: CursorSize.cpp:10
CursorSize cursorSize() const
Get method for cursor size.
Command for DlgSettingsDigitizeCurve.
Command queue stack.
Definition: CmdMediator.h:23
const int MINIMUM_HEIGHT
Abstract base class for all Settings dialogs.
QCursor generate(const DocumentModelDigitizeCurve &modelDigitizeCurve) const
Factory method to generate standard or custom cursor.
MainWindow & mainWindow()
Get method for MainWindow.
Main window consisting of menu, graphics scene, status bar and optional toolbars as a Single Document...
Definition: MainWindow.h:91
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.
void setCursorStandardCross(bool cursorStandardCross)
Set method for cursor type.
const int INNER_RADIUS_MIN
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT if defined(QT_NO_DEBUG) &amp;&amp; !defined(QT_FORCE_ASSERTS) define ENGAUGE...
Definition: EngaugeAssert.h:20
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.