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 
58 void DlgSettingsAxesChecker::createControls (QGridLayout *layout,
59  int &row)
60 {
61  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::createControls";
62 
63  QGroupBox *groupBox = new QGroupBox (tr ("Axes Checker Lifetime"));
64  layout->addWidget (groupBox, row++, 1, 1, 2);
65 
66  QGridLayout *layoutLifetime = new QGridLayout;
67  groupBox->setLayout (layoutLifetime);
68 
69  int rowLifetime = 0;
70  m_btnNever = new QRadioButton (tr ("Do not show"), groupBox);
71  m_btnNever->setWhatsThis (tr ("Never show axes checker."));
72  layoutLifetime->addWidget (m_btnNever, rowLifetime++, 0, 1, 2);
73 
74  m_btnNSeconds = new QRadioButton (tr ("Show for a number of seconds"), groupBox);
75  m_btnNSeconds->setWhatsThis (tr ("Show axes checker for a number of seconds after changing axes points."));
76  layoutLifetime->addWidget (m_btnNSeconds, rowLifetime, 0, 1, 1);
77 
78  m_cmbSeconds = new QComboBox;
79  for (int seconds = 1; seconds <= 10; seconds++) {
80  m_cmbSeconds->addItem (QString::number (seconds), QVariant (seconds));
81  }
82  layoutLifetime->addWidget (m_cmbSeconds, rowLifetime++, 1);
83  connect (m_cmbSeconds, SIGNAL (activated (const QString &)), this, SLOT (slotSeconds (const QString &))); // activated() ignores code changes
84 
85  m_btnForever = new QRadioButton (tr ("Show always"), groupBox);
86  m_btnForever->setWhatsThis (tr ("Always show axes checker."));
87  layoutLifetime->addWidget (m_btnForever, rowLifetime++, 0, 1, 2);
88 
89  m_groupMode = new QButtonGroup;
90  m_groupMode->addButton (m_btnNever);
91  m_groupMode->addButton (m_btnNSeconds);
92  m_groupMode->addButton (m_btnForever);
93  connect (m_groupMode, SIGNAL (buttonReleased (QAbstractButton*)), this, SLOT (slotGroupMode (QAbstractButton*)));
94 
95  QLabel *labelLineColor = new QLabel (tr ("Line color:"));
96  layout->addWidget (labelLineColor, row, 1);
97 
98  m_cmbLineColor = new QComboBox;
99  m_cmbLineColor->setWhatsThis (tr ("Select a color for the highlight lines drawn at each axis point"));
100  populateColorComboWithoutTransparent (*m_cmbLineColor);
101  connect (m_cmbLineColor, SIGNAL (activated (const QString &)), this, SLOT (slotLineColor (const QString &))); // activated() ignores code changes
102  layout->addWidget (m_cmbLineColor, row++, 2);
103 }
104 
105 void DlgSettingsAxesChecker::createOptionalSaveDefault (QHBoxLayout * /* layout */)
106 {
107 }
108 
109 void DlgSettingsAxesChecker::createPoints ()
110 {
111  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::createPoints";
112 
113  QBrush AXES_BRUSH (Qt::gray);
114 
115  m_checker = new Checker (*m_scenePreview);
116 
117  // Create an invisible rectangular item that will guarantee a margin all around the outside, since otherwise QGraphicsView
118  // will zoom in on the points
119  QGraphicsRectItem *itemRect = new QGraphicsRectItem (0,
120  0,
121  RECT_WIDTH,
122  RECT_HEIGHT);
123  itemRect->setPen (Qt::NoPen);
124  m_scenePreview->addItem (itemRect);
125 
126  // For a realistic background, draw a rectangle underneath (lower z value), and some tick marks
127  QGraphicsRectItem *frameBox = new QGraphicsRectItem (X_LEFT,
128  Y_BOTTOM,
129  X_RIGHT - X_LEFT,
130  Y_TOP - Y_BOTTOM);
131  frameBox->setPen (QPen (AXES_BRUSH, AXIS_WIDTH));
132  frameBox->setZValue (-1);
133  m_scenePreview->addItem (frameBox);
134  for (int x = X_LEFT; x < X_RIGHT; x += (X_RIGHT - X_LEFT) / TICKS_PER_AXIS) {
135  QGraphicsLineItem *tick = new QGraphicsLineItem (x, Y_BOTTOM, x, Y_BOTTOM + TICK_MARK_LENGTH);
136  tick->setPen (QPen (AXES_BRUSH, AXIS_WIDTH));
137  tick->setZValue (-1);
138  m_scenePreview->addItem (tick);
139  }
140  for (int y = Y_TOP; y < Y_BOTTOM; y += (Y_BOTTOM - Y_TOP) / TICKS_PER_AXIS) {
141  QGraphicsLineItem *tick = new QGraphicsLineItem (X_LEFT, y, X_LEFT + TICK_MARK_LENGTH, y);
142  tick->setPen (QPen (AXES_BRUSH, AXIS_WIDTH));
143  tick->setZValue (-1);
144  m_scenePreview->addItem (tick);
145  }
146 }
147 
148 void DlgSettingsAxesChecker::createPreview (QGridLayout *layout,
149  int &row)
150 {
151  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::createPreview";
152 
153  QLabel *labelPreview = new QLabel (tr ("Preview"));
154  layout->addWidget (labelPreview, row++, 0, 1, 4);
155 
156  m_scenePreview = new QGraphicsScene (this);
157  m_viewPreview = new ViewPreview (m_scenePreview,
158  ViewPreview::VIEW_ASPECT_RATIO_VARIABLE,
159  this);
160  m_viewPreview->setWhatsThis (tr ("Preview window that shows how current settings affect the displayed axes checker"));
161  m_viewPreview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
162  m_viewPreview->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
163  m_viewPreview->setMinimumHeight (MINIMUM_PREVIEW_HEIGHT);
164 
165  layout->addWidget (m_viewPreview, row++, 0, 1, 4);
166 }
167 
169 {
170  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::createSubPanel";
171 
172  QWidget *subPanel = new QWidget ();
173  QGridLayout *layout = new QGridLayout (subPanel);
174  subPanel->setLayout (layout);
175 
176  layout->setColumnStretch(0, 1); // Empty first column
177  layout->setColumnStretch(1, 0); // X
178  layout->setColumnStretch(2, 0); // Y
179  layout->setColumnStretch(3, 1); // Empty first column
180 
181  int row = 0;
182  createControls (layout, row);
183  createPreview (layout, row);
184 
185  createPoints ();
186 
187  return subPanel;
188 }
189 
191 {
192  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::handleOk";
193 
195  cmdMediator ().document(),
196  *m_modelAxesCheckerBefore,
197  *m_modelAxesCheckerAfter);
198  cmdMediator ().push (cmd);
199 
200  hide ();
201 }
202 
204 {
205  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::load";
206 
207  setCmdMediator (cmdMediator);
208 
209  // Flush old data
210  if (m_modelAxesCheckerBefore != 0) {
211  delete m_modelAxesCheckerBefore;
212  }
213  if (m_modelAxesCheckerAfter != 0) {
214  delete m_modelAxesCheckerAfter;
215  }
216  if (m_modelCoords != 0) {
217  delete m_modelCoords;
218  }
219 
220  // Save new data
221  m_modelAxesCheckerBefore = new DocumentModelAxesChecker (cmdMediator.document());
222  m_modelAxesCheckerAfter = new DocumentModelAxesChecker (cmdMediator.document());
223  m_modelCoords = new DocumentModelCoords (cmdMediator.document());
224 
225  // Populate controls
226  CheckerMode checkerMode = m_modelAxesCheckerAfter->checkerMode();
227  m_btnNever->setChecked (checkerMode == CHECKER_MODE_NEVER);
228  m_btnNSeconds->setChecked (checkerMode == CHECKER_MODE_N_SECONDS);
229  m_btnForever->setChecked (checkerMode == CHECKER_MODE_FOREVER);
230  int indexSeconds = m_cmbSeconds->findData (QVariant (m_modelAxesCheckerAfter->checkerSeconds()));
231  ENGAUGE_ASSERT (indexSeconds >= 0);
232  m_cmbSeconds->setCurrentIndex(indexSeconds);
233 
234  int indexLineColor = m_cmbLineColor->findData (QVariant (m_modelAxesCheckerAfter->lineColor()));
235  ENGAUGE_ASSERT (indexLineColor >= 0);
236  m_cmbLineColor->setCurrentIndex (indexLineColor);
237 
238  updateControls ();
239  enableOk (false); // Disable Ok button since there not yet any changes
240  updatePreview();
241 }
242 
244 {
245  if (!smallDialogs) {
246  setMinimumHeight (MINIMUM_HEIGHT);
247  }
248 }
249 
250 void DlgSettingsAxesChecker::slotGroupMode (QAbstractButton*)
251 {
252  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::slotGroupMode";
253 
254  if (m_btnNever->isChecked ()) {
255  m_modelAxesCheckerAfter->setCheckerMode(CHECKER_MODE_NEVER);
256  } else if (m_btnNSeconds->isChecked ()) {
257  m_modelAxesCheckerAfter->setCheckerMode(CHECKER_MODE_N_SECONDS);
258  } else {
259  m_modelAxesCheckerAfter->setCheckerMode(CHECKER_MODE_FOREVER);
260  }
261 
262  updateControls ();
263  updatePreview();
264 }
265 
266 void DlgSettingsAxesChecker::slotLineColor(const QString &)
267 {
268  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::slotLineColor";
269 
270  m_modelAxesCheckerAfter->setLineColor ((ColorPalette) m_cmbLineColor->currentData().toInt());
271  updateControls();
272  updatePreview();
273 }
274 
275 void DlgSettingsAxesChecker::slotSeconds (const QString &)
276 {
277  LOG4CPP_INFO_S ((*mainCat)) << "DlgSettingsAxesChecker::slotLineColor";
278 
279  m_modelAxesCheckerAfter->setCheckerSeconds(m_cmbSeconds->currentData().toInt());
280  updateControls();
281 }
282 
283 void DlgSettingsAxesChecker::updateControls ()
284 {
285  enableOk (true);
286 
287  m_cmbSeconds->setEnabled (m_btnNSeconds->isChecked ());
288 }
289 
290 void DlgSettingsAxesChecker::updatePreview()
291 {
292  const int ZERO_RADIUS_SINCE_NO_POINTS = 0;
293 
294  QVector<QPointF> points;
295  points.push_back (QPointF (X_LEFT, Y_TOP));
296  points.push_back (QPointF (X_LEFT, Y_BOTTOM));
297  points.push_back (QPointF (X_RIGHT, Y_BOTTOM));
298 
299  QPolygonF polygon (points);
300 
301  ENGAUGE_ASSERT (m_checker != 0);
302  m_checker->prepareForDisplay (polygon,
303  ZERO_RADIUS_SINCE_NO_POINTS,
304  *m_modelAxesCheckerAfter,
305  *m_modelCoords,
306  mainWindow().cmdMediator()->document().documentAxesPointsRequired());
307 }
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:130
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:89
CmdMediator & cmdMediator()
Provide access to Document information wrapped inside CmdMediator.