Engauge Digitizer  2
 All Classes Files Functions Variables Enumerations Enumerator Friends Pages
DlgSettingsDigitizeCurve.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 "CmdSettingsDigitizeCurve.h"
9 #include "CursorFactory.h"
10 #include "CursorSize.h"
11 #include "DlgSettingsDigitizeCurve.h"
12 #include "DocumentModelDigitizeCurve.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 
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 (0),
45  m_viewPreview (0),
46  m_modelDigitizeCurveBefore (0),
47  m_modelDigitizeCurveAfter (0)
48 {
49  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::DlgSettingsDigitizeCurve";
50 
51  QWidget *subPanel = createSubPanel ();
52  finishPanel (subPanel);
53 }
54 
55 DlgSettingsDigitizeCurve::~DlgSettingsDigitizeCurve()
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(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(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(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(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,
137  ViewPreview::VIEW_ASPECT_RATIO_VARIABLE,
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  if (m_modelDigitizeCurveBefore != 0) {
189  delete m_modelDigitizeCurveBefore;
190  }
191  if (m_modelDigitizeCurveAfter != 0) {
192  delete m_modelDigitizeCurveAfter;
193  }
194 
195  // Save new data
196  m_modelDigitizeCurveBefore = new DocumentModelDigitizeCurve (cmdMediator.document());
197  m_modelDigitizeCurveAfter = new DocumentModelDigitizeCurve (cmdMediator.document());
198 
199  // Sanity checks. Incoming defaults must be acceptable to the local limits
200  ENGAUGE_ASSERT (INNER_RADIUS_MIN <= m_modelDigitizeCurveAfter->cursorInnerRadius ());
201  ENGAUGE_ASSERT (INNER_RADIUS_MAX >= m_modelDigitizeCurveAfter->cursorInnerRadius ());
202  ENGAUGE_ASSERT (LINE_WIDTH_MIN <= m_modelDigitizeCurveAfter->cursorLineWidth ());
203  ENGAUGE_ASSERT (LINE_WIDTH_MAX >= m_modelDigitizeCurveAfter->cursorLineWidth ());
204 
205  // Populate controls
206  m_btnStandard->setChecked (m_modelDigitizeCurveAfter->cursorStandardCross());
207  m_btnCustom->setChecked (!m_modelDigitizeCurveAfter->cursorStandardCross());
208  m_spinInnerRadius->setValue (m_modelDigitizeCurveAfter->cursorInnerRadius());
209  int index = m_cmbSize->findData (QVariant (m_modelDigitizeCurveAfter->cursorSize()));
210  m_cmbSize->setCurrentIndex (index);
211  m_spinLineWidth->setValue (m_modelDigitizeCurveAfter->cursorLineWidth());
212 
213  updateControls();
214  enableOk (false); // Disable Ok button since there not yet any changes
215  updatePreview();
216 }
217 
218 void DlgSettingsDigitizeCurve::slotCursorCustom (bool)
219 {
220  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorCustom";
221 
222  m_modelDigitizeCurveAfter->setCursorStandardCross(false);
223  updateControls();
224  updatePreview();
225 }
226 
227 void DlgSettingsDigitizeCurve::slotCursorInnerRadius (const QString &)
228 {
229  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorInnerRadius";
230 
231  m_modelDigitizeCurveAfter->setCursorInnerRadius (m_spinInnerRadius->value());
232  updateControls();
233  updatePreview();
234 }
235 
236 void DlgSettingsDigitizeCurve::slotCursorLineWidth (const QString &)
237 {
238  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorLineWidth";
239 
240  m_modelDigitizeCurveAfter->setCursorLineWidth (m_spinLineWidth->value());
241  updateControls();
242  updatePreview();
243 }
244 
245 void DlgSettingsDigitizeCurve::slotCursorSize (const QString &)
246 {
247  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorSize";
248 
249  m_modelDigitizeCurveAfter->setCursorSize ((CursorSize) m_cmbSize->currentData().toInt());
250  updateControls();
251  updatePreview();
252 }
253 
254 void DlgSettingsDigitizeCurve::slotCursorStandard (bool)
255 {
256  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::slotCursorStandard";
257 
258  m_modelDigitizeCurveAfter->setCursorStandardCross(true);
259  updateControls();
260  updatePreview();
261 }
262 
263 void DlgSettingsDigitizeCurve::updateControls()
264 {
265  // Cursor has to fit into current extent
266  bool isGoodState = 2 * (m_modelDigitizeCurveAfter->cursorInnerRadius() + LINE_LENGTH_MIN) <=
267  CursorSizeToPixels (m_modelDigitizeCurveAfter->cursorSize());
268  enableOk (isGoodState);
269 
270  m_spinInnerRadius->setEnabled (m_btnCustom->isChecked());
271  m_cmbSize->setEnabled (m_btnCustom->isChecked());
272  m_spinLineWidth->setEnabled (m_btnCustom->isChecked());
273 }
274 
275 void DlgSettingsDigitizeCurve::updatePreview()
276 {
277  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsDigitizeCurve::updatePreview";
278 
279  CursorFactory cursorFactory;
280  QCursor cursor = cursorFactory.generate (*m_modelDigitizeCurveAfter);
281  m_viewPreview->setCursor (cursor);
282 }
DlgSettingsDigitizeCurve(MainWindow &mainWindow)
Single constructor.
int cursorLineWidth() const
Get method for cursor line 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.
bool cursorStandardCross() const
Get method for cursor type.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
void setCursorSize(CursorSize cursorSize)
Set method for cursor size.
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.
virtual QWidget * createSubPanel()
Create dialog-specific panel to which base class will add Ok and Cancel buttons.
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.
void finishPanel(QWidget *subPanel, int minimumWidth=MINIMUM_DIALOG_WIDTH)
Add Ok and Cancel buttons to subpanel to get the whole dialog.
CursorSize cursorSize() const
Get method for cursor size.
Command for DlgSettingsDigitizeCurve.
Command queue stack.
Definition: CmdMediator.h:23
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:83
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.
void setCursorStandardCross(bool cursorStandardCross)
Set method for cursor type.