Engauge Digitizer  2
DlgSettingsAxesChecker.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 "Checker.h"
8 #include "CmdMediator.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 (nullptr),
43  m_modelAxesCheckerBefore (nullptr),
44  m_modelAxesCheckerAfter (nullptr),
45  m_modelCoords (nullptr)
46 {
47  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::DlgSettingsAxesChecker";
48 
49  QWidget *subPanel = createSubPanel ();
50  finishPanel (subPanel);
51 }
52 
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,
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 (static_cast<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_CHECK_PTR (m_checker);
298  m_checker->prepareForDisplay (polygon,
299  ZERO_RADIUS_SINCE_NO_POINTS,
300  *m_modelAxesCheckerAfter,
301  *m_modelCoords,
302  mainWindow().cmdMediator()->document().documentAxesPointsRequired());
303 }
const int Y_TOP
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.
const int X_RIGHT
const int TICKS_PER_AXIS
void setCmdMediator(CmdMediator &cmdMediator)
Store CmdMediator for easy access by the leaf class.
const int AXIS_WIDTH
#define LOG4CPP_INFO_S(logger)
Definition: convenience.h:18
const int Y_BOTTOM
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.
const int RECT_WIDTH
void setLineColor(ColorPalette lineColor)
Set method for line color.
virtual void load(CmdMediator &cmdMediator)
Load settings from Document.
#define ENGAUGE_CHECK_PTR(ptr)
#endif
Definition: EngaugeAssert.h:27
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:135
CheckerMode
Options for axes checker mode. Specifically, how long the checker is displayed after a change...
Definition: CheckerMode.h:13
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.
log4cpp::Category * mainCat
Definition: Logger.cpp:14
static int MINIMUM_PREVIEW_HEIGHT
Dialog layout constant that guarantees preview has sufficent room.
const int TICK_MARK_LENGTH
void enableOk(bool enable)
Let leaf subclass control the Ok button.
const int RECT_HEIGHT
Command queue stack.
Definition: CmdMediator.h:23
const int MINIMUM_HEIGHT
const int X_LEFT
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.
#define ENGAUGE_ASSERT(cond)
Drop in replacement for Q_ASSERT if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) define ENGAUGE...
Definition: EngaugeAssert.h:20