Engauge Digitizer  2
DlgSettingsAxesChecker.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 "Checker.h"
8 #include "CmdMediator.h"
9 #include "CmdSettingsAxesChecker.h"
10 #include "CoordScale.h"
11 #include "DlgSettingsAxesChecker.h"
12 #include "EngaugeAssert.h"
13 #include "Logger.h"
14 #include "MainWindow.h"
15 #include <QButtonGroup>
16 #include <QComboBox>
17 #include <QGraphicsRectItem>
18 #include <QGraphicsScene>
19 #include <QGridLayout>
20 #include <QGroupBox>
21 #include <QLabel>
22 #include <QLineEdit>
23 #include <qmath.h>
24 #include <QRadioButton>
25 #include "ViewPreview.h"
26 
27 const int AXIS_WIDTH = 4;
28 const int MINIMUM_HEIGHT = 500;
29 const int RECT_WIDTH = 640;
30 const int RECT_HEIGHT = 480;
31 const int X_LEFT = RECT_WIDTH / 8;
32 const int X_RIGHT = RECT_WIDTH * 7 / 8;
33 const int Y_TOP = RECT_HEIGHT / 8;
34 const int Y_BOTTOM = RECT_HEIGHT * 7 / 8;
35 const int TICKS_PER_AXIS = 6;
36 const int TICK_MARK_LENGTH = 8;
37 
39  DlgSettingsAbstractBase (tr ("Axes Checker"),
40  "DlgSettingsAxesChecker",
41  mainWindow),
42  m_checker (0),
43  m_modelAxesCheckerBefore (0),
44  m_modelAxesCheckerAfter (0),
45  m_modelCoords (0)
46 {
47  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::DlgSettingsAxesChecker";
48 
49  QWidget *subPanel = createSubPanel ();
50  finishPanel (subPanel);
51 }
52 
53 DlgSettingsAxesChecker::~DlgSettingsAxesChecker()
54 {
55  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::~DlgSettingsAxesChecker";
56 
57  delete m_checker;
58 }
59 
60 void DlgSettingsAxesChecker::createControls (QGridLayout *layout,
61  int &row)
62 {
63  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::createControls";
64 
65  QGroupBox *groupBox = new QGroupBox (tr ("Axes Checker Lifetime"));
66  layout->addWidget (groupBox, row++, 1, 1, 2);
67 
68  QGridLayout *layoutLifetime = new QGridLayout;
69  groupBox->setLayout (layoutLifetime);
70 
71  int rowLifetime = 0;
72  m_btnNever = new QRadioButton (tr ("Do not show"), groupBox);
73  m_btnNever->setWhatsThis (tr ("Never show axes checker."));
74  layoutLifetime->addWidget (m_btnNever, rowLifetime++, 0, 1, 2);
75 
76  m_btnNSeconds = new QRadioButton (tr ("Show for a number of seconds"), groupBox);
77  m_btnNSeconds->setWhatsThis (tr ("Show axes checker for a number of seconds after changing axes points."));
78  layoutLifetime->addWidget (m_btnNSeconds, rowLifetime, 0, 1, 1);
79 
80  m_cmbSeconds = new QComboBox;
81  for (int seconds = 1; seconds <= 10; seconds++) {
82  m_cmbSeconds->addItem (QString::number (seconds), QVariant (seconds));
83  }
84  layoutLifetime->addWidget (m_cmbSeconds, rowLifetime++, 1);
85  connect (m_cmbSeconds, SIGNAL (activated (const QString &)), this, SLOT (slotSeconds (const QString &))); // activated() ignores code changes
86 
87  m_btnForever = new QRadioButton (tr ("Show always"), groupBox);
88  m_btnForever->setWhatsThis (tr ("Always show axes checker."));
89  layoutLifetime->addWidget (m_btnForever, rowLifetime++, 0, 1, 2);
90 
91  m_groupMode = new QButtonGroup;
92  m_groupMode->addButton (m_btnNever);
93  m_groupMode->addButton (m_btnNSeconds);
94  m_groupMode->addButton (m_btnForever);
95  connect (m_groupMode, SIGNAL (buttonReleased (QAbstractButton*)), this, SLOT (slotGroupMode (QAbstractButton*)));
96 
97  QLabel *labelLineColor = new QLabel (QString ("%1:").arg (tr ("Line color")));
98  layout->addWidget (labelLineColor, row, 1);
99 
100  m_cmbLineColor = new QComboBox;
101  m_cmbLineColor->setWhatsThis (tr ("Select a color for the highlight lines drawn at each axis point"));
102  populateColorComboWithoutTransparent (*m_cmbLineColor);
103  connect (m_cmbLineColor, SIGNAL (activated (const QString &)), this, SLOT (slotLineColor (const QString &))); // activated() ignores code changes
104  layout->addWidget (m_cmbLineColor, row++, 2);
105 }
106 
107 void DlgSettingsAxesChecker::createOptionalSaveDefault (QHBoxLayout * /* layout */)
108 {
109 }
110 
111 void DlgSettingsAxesChecker::createPoints ()
112 {
113  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::createPoints";
114 
115  QBrush AXES_BRUSH (Qt::gray);
116 
117  m_checker = new Checker (*m_scenePreview);
118 
119  // Create an invisible rectangular item that will guarantee a margin all around the outside, since otherwise QGraphicsView
120  // will zoom in on the points
121  QGraphicsRectItem *itemRect = new QGraphicsRectItem (0,
122  0,
123  RECT_WIDTH,
124  RECT_HEIGHT);
125  itemRect->setPen (Qt::NoPen);
126  m_scenePreview->addItem (itemRect);
127 
128  // For a realistic background, draw a rectangle underneath (lower z value), and some tick marks
129  QGraphicsRectItem *frameBox = new QGraphicsRectItem (X_LEFT,
130  Y_BOTTOM,
131  X_RIGHT - X_LEFT,
132  Y_TOP - Y_BOTTOM);
133  frameBox->setPen (QPen (AXES_BRUSH, AXIS_WIDTH));
134  frameBox->setZValue (-1);
135  m_scenePreview->addItem (frameBox);
136  for (int x = X_LEFT; x < X_RIGHT; x += (X_RIGHT - X_LEFT) / TICKS_PER_AXIS) {
137  QGraphicsLineItem *tick = new QGraphicsLineItem (x, Y_BOTTOM, x, Y_BOTTOM + TICK_MARK_LENGTH);
138  tick->setPen (QPen (AXES_BRUSH, AXIS_WIDTH));
139  tick->setZValue (-1);
140  m_scenePreview->addItem (tick);
141  }
142  for (int y = Y_TOP; y < Y_BOTTOM; y += (Y_BOTTOM - Y_TOP) / TICKS_PER_AXIS) {
143  QGraphicsLineItem *tick = new QGraphicsLineItem (X_LEFT, y, X_LEFT + TICK_MARK_LENGTH, y);
144  tick->setPen (QPen (AXES_BRUSH, AXIS_WIDTH));
145  tick->setZValue (-1);
146  m_scenePreview->addItem (tick);
147  }
148 }
149 
150 void DlgSettingsAxesChecker::createPreview (QGridLayout *layout,
151  int &row)
152 {
153  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::createPreview";
154 
155  QLabel *labelPreview = new QLabel (tr ("Preview"));
156  layout->addWidget (labelPreview, row++, 0, 1, 4);
157 
158  m_scenePreview = new QGraphicsScene (this);
159  m_viewPreview = new ViewPreview (m_scenePreview,
160  ViewPreview::VIEW_ASPECT_RATIO_VARIABLE,
161  this);
162  m_viewPreview->setWhatsThis (tr ("Preview window that shows how current settings affect the displayed axes checker"));
163  m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
164  m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
165  m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
166 
167  layout->addWidget (m_viewPreview, row++, 0, 1, 4);
168 }
169 
171 {
172  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::createSubPanel";
173 
174  QWidget *subPanel = new QWidget ();
175  QGridLayout *layout = new QGridLayout (subPanel);
176  subPanel->setLayout (layout);
177 
178  layout->setColumnStretch(0, 1); // Empty first column
179  layout->setColumnStretch(1, 0); // X
180  layout->setColumnStretch(2, 0); // Y
181  layout->setColumnStretch(3, 1); // Empty first column
182 
183  int row = 0;
184  createControls (layout, row);
185  createPreview (layout, row);
186 
187  createPoints ();
188 
189  return subPanel;
190 }
191 
193 {
194  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::handleOk";
195 
197  cmdMediator ().document(),
198  *m_modelAxesCheckerBefore,
199  *m_modelAxesCheckerAfter);
200  cmdMediator ().push (cmd);
201 
202  hide ();
203 }
204 
206 {
207  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::load";
208 
210 
211  // Flush old data
212  delete m_modelAxesCheckerBefore;
213  delete m_modelAxesCheckerAfter;
214  delete m_modelCoords;
215 
216  // Save new data
217  m_modelAxesCheckerBefore = new DocumentModelAxesChecker (cmdMediator.document());
218  m_modelAxesCheckerAfter = new DocumentModelAxesChecker (cmdMediator.document());
219  m_modelCoords = new DocumentModelCoords (cmdMediator.document());
220 
221  // Populate controls
222  CheckerMode checkerMode = m_modelAxesCheckerAfter->checkerMode();
223  m_btnNever->setChecked (checkerMode == CHECKER_MODE_NEVER);
224  m_btnNSeconds->setChecked (checkerMode == CHECKER_MODE_N_SECONDS);
225  m_btnForever->setChecked (checkerMode == CHECKER_MODE_FOREVER);
226  int indexSeconds = m_cmbSeconds->findData (QVariant (m_modelAxesCheckerAfter->checkerSeconds()));
227  ENGAUGE_ASSERT (indexSeconds >= 0);
228  m_cmbSeconds->setCurrentIndex(indexSeconds);
229 
230  int indexLineColor = m_cmbLineColor->findData (QVariant (m_modelAxesCheckerAfter->lineColor()));
231  ENGAUGE_ASSERT (indexLineColor >= 0);
232  m_cmbLineColor->setCurrentIndex (indexLineColor);
233 
234  updateControls ();
235  enableOk (false); // Disable Ok button since there not yet any changes
236  updatePreview();
237 }
238 
240 {
241  if (!smallDialogs) {
242  setMinimumHeight (MINIMUM_HEIGHT);
243  }
244 }
245 
246 void DlgSettingsAxesChecker::slotGroupMode (QAbstractButton*)
247 {
248  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::slotGroupMode";
249 
250  if (m_btnNever->isChecked ()) {
251  m_modelAxesCheckerAfter->setCheckerMode(CHECKER_MODE_NEVER);
252  } else if (m_btnNSeconds->isChecked ()) {
253  m_modelAxesCheckerAfter->setCheckerMode(CHECKER_MODE_N_SECONDS);
254  } else {
255  m_modelAxesCheckerAfter->setCheckerMode(CHECKER_MODE_FOREVER);
256  }
257 
258  updateControls ();
259  updatePreview();
260 }
261 
262 void DlgSettingsAxesChecker::slotLineColor(const QString &)
263 {
264  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::slotLineColor";
265 
266  m_modelAxesCheckerAfter->setLineColor ((ColorPalette) m_cmbLineColor->currentData().toInt());
267  updateControls();
268  updatePreview();
269 }
270 
271 void DlgSettingsAxesChecker::slotSeconds (const QString &)
272 {
273  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::slotLineColor";
274 
275  m_modelAxesCheckerAfter->setCheckerSeconds(m_cmbSeconds->currentData().toInt());
276  updateControls();
277 }
278 
279 void DlgSettingsAxesChecker::updateControls ()
280 {
281  enableOk (true);
282 
283  m_cmbSeconds->setEnabled (m_btnNSeconds->isChecked ());
284 }
285 
286 void DlgSettingsAxesChecker::updatePreview()
287 {
288  const int ZERO_RADIUS_SINCE_NO_POINTS = 0;
289 
290  QVector<QPointF> points;
291  points.push_back (QPointF (X_LEFT, Y_TOP));
292  points.push_back (QPointF (X_LEFT, Y_BOTTOM));
293  points.push_back (QPointF (X_RIGHT, Y_BOTTOM));
294 
295  QPolygonF polygon (points);
296 
297  ENGAUGE_ASSERT (m_checker != 0);
298  m_checker->prepareForDisplay (polygon,
299  ZERO_RADIUS_SINCE_NO_POINTS,
300  *m_modelAxesCheckerAfter,
301  *m_modelCoords,
302  mainWindow().cmdMediator()->document().documentAxesPointsRequired());
303 }
void setCheckerMode(CheckerMode checkerMode)
Set method for checker mode.
void setCheckerSeconds(int seconds)
Set method for checker lifetime in seconds.
int checkerSeconds() const
Get method for checker lifetime in seconds.
void setCmdMediator(CmdMediator &cmdMediator)
Store CmdMediator for easy access by the leaf class.
Document & document()
Provide the Document to commands, primarily for undo/redo processing.
Definition: CmdMediator.cpp:72
Box shape that is drawn through the three axis points, to temporarily (usually) or permanently (rarel...
Definition: Checker.h:33
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 setLineColor(ColorPalette lineColor)
Set method for line color.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
CheckerMode checkerMode() const
Get method for checker lifetime mode.
void prepareForDisplay(const QPolygonF &polygon, int pointRadius, const DocumentModelAxesChecker &modelAxesChecker, const DocumentModelCoords &modelCoords, DocumentAxesPointsRequired documentAxesPointsRequired)
Create the polygon from current information, including pixel coordinates, just prior to display...
Definition: Checker.cpp:134
Class that modifies QGraphicsView to automatically expand/shrink the view to fit the window...
Definition: ViewPreview.h:14
Command for DlgSettingsAxesChecker.
void populateColorComboWithoutTransparent(QComboBox &combo)
Add colors in color palette to combobox, without transparent entry at end.
ColorPalette lineColor() const
Get method for line color.
virtual void setSmallDialogs(bool smallDialogs)
If false then dialogs have a minimum size so all controls are visible.
Model for DlgSettingsCoords and CmdSettingsCoords.
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 handleOk()
Process slotOk.
Model for DlgSettingsAxesChecker and CmdSettingsAxesChecker.
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.
Command queue stack.
Definition: CmdMediator.h:23
Abstract base class for all Settings dialogs.
DlgSettingsAxesChecker(MainWindow &mainWindow)
Single constructor.
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.