Engauge Digitizer  2
 All Classes Functions Variables Typedefs Enumerations Friends Pages
StatusBar.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 "EngaugeAssert.h"
8 #include "Logger.h"
9 #include <QFrame>
10 #include <QHBoxLayout>
11 #include <QLineEdit>
12 #include <QStatusBar>
13 #include <QTextEdit>
14 #include <QTimer>
15 #include <QWhatsThis>
16 #include "StatusBar.h"
17 #include "ZoomFactor.h"
18 #include "ZoomLabels.h"
19 
20 const int TEMPORARY_MESSAGE_LIFETIME = 5000; // Milliseconds. Two seconds is too fast even when the text is anticipated
21 
22 const int MIN_WIDTH_ZOOM = 110;
23 const int MIN_WIDTH_COMBO_UNITS = 160;
24 const int MIN_SIZE_EDIT_COORDS = 250; // Need lots of space in case date/time and degrees/minutes/seconds are used simultaneously
25 const int MAX_HEIGHT_EDIT_COORDS = 24;
26 
27 StatusBar::StatusBar(QStatusBar &statusBar) :
28  m_statusBar (statusBar),
29  m_statusBarMode (STATUS_BAR_MODE_ALWAYS),
30  m_timer (nullptr)
31 {
32  createZoom ();
33  createZoomMaps ();
34  createGroupUnits ();
35 
36  connect (&m_statusBar, SIGNAL (messageChanged (const QString &)), this, SLOT (slotStatusBarChanged (const QString &)));
37 
38  m_statusBar.setMaximumHeight (60);
39  m_statusBar.hide();
40 }
41 
42 StatusBar::~StatusBar ()
43 {
44  delete m_timer;
45 }
46 
47 void StatusBar::createGroupUnits ()
48 {
49  m_cmbUnits = new QComboBox;
50  m_cmbUnits->setEnabled (false); // Disabled until file is opened
51  m_cmbUnits->addItem (labelCoordsScreen (), QVariant (STATUS_BAR_UNITS_COORDS_SCREEN));
52  m_cmbUnits->addItem (labelCoordsGraph (), QVariant (STATUS_BAR_UNITS_COORDS_GRAPH));
53  m_cmbUnits->addItem (labelResolutionGraph (), QVariant (STATUS_BAR_UNITS_RESOLUTION_GRAPH));
54  m_cmbUnits->setCurrentText (labelCoordsGraph ());
55  m_cmbUnits->setMinimumWidth (MIN_WIDTH_COMBO_UNITS);
56  m_cmbUnits->setToolTip (tr ("Select cursor coordinate values to display."));
57  m_cmbUnits->setWhatsThis (tr("Select Cursor Coordinate Values\n\n"
58  "Values at cursor coordinates to display. Coordinates are in screen (pixels) or "
59  "graph units. Resolution (which is the number of graph units per pixel) is "
60  "in graph units. Graph units are only available after axis points have been defined."));
61  connect (m_cmbUnits, SIGNAL (activated(const QString &)), this, SLOT (slotComboUnits (const QString &))); // activated() ignores code changes
62 
63  m_editCoords = new QTextEdit;
64  m_editCoords->setEnabled (false); // Disabled until file is opened
65  m_editCoords->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
66  m_editCoords->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
67  m_editCoords->setMinimumSize (MIN_SIZE_EDIT_COORDS, MAX_HEIGHT_EDIT_COORDS);
68  m_editCoords->setMaximumHeight (MAX_HEIGHT_EDIT_COORDS);
69  m_editCoords->setReadOnly(true);
70  m_editCoords->setToolTip (tr ("Cursor coordinate values."));
71  m_editCoords->setWhatsThis (tr ("Cursor Coordinate Values\n\n"
72  "Values at cursor coordinates. Coordinates are in screen (pixels) or "
73  "graph units. Resolution (which is the number of graph units per pixel) is "
74  "in graph units. Graph units are only available after axis points have been defined."));
75 
76  m_groupUnits = new QFrame;
77  m_groupUnits->setFrameStyle (QFrame::Box);
78  QPalette *palette = new QPalette;
79  palette->setColor (QPalette::Foreground, Qt::gray);
80  m_groupUnits->setPalette (*palette);
81 
82  QHBoxLayout *groupLayout = new QHBoxLayout;
83  m_groupUnits->setLayout (groupLayout);
84  groupLayout->setContentsMargins (0, 0, 0, 0);
85  groupLayout->addWidget (m_cmbUnits);
86  groupLayout->addWidget (m_editCoords);
87  groupLayout->setMargin (2);
88 
89  m_statusBar.addPermanentWidget (m_groupUnits);
90 }
91 
92 void StatusBar::createZoom ()
93 {
94  m_cmbZoom = new QComboBox ();
95  m_cmbZoom->setEnabled (false); // Disabled until file is opened
96  m_cmbZoom->setMinimumWidth (MIN_WIDTH_ZOOM);
97  m_cmbZoom->addItem (LABEL_ZOOM_16_TO_1);
98  m_cmbZoom->addItem (LABEL_ZOOM_16_TO_1_FARTHER);
99  m_cmbZoom->addItem (LABEL_ZOOM_8_TO_1_CLOSER);
100  m_cmbZoom->addItem (LABEL_ZOOM_8_TO_1);
101  m_cmbZoom->addItem (LABEL_ZOOM_8_TO_1_FARTHER);
102  m_cmbZoom->addItem (LABEL_ZOOM_4_TO_1_CLOSER);
103  m_cmbZoom->addItem (LABEL_ZOOM_4_TO_1);
104  m_cmbZoom->addItem (LABEL_ZOOM_4_TO_1_FARTHER);
105  m_cmbZoom->addItem (LABEL_ZOOM_2_TO_1_CLOSER);
106  m_cmbZoom->addItem (LABEL_ZOOM_2_TO_1);
107  m_cmbZoom->addItem (LABEL_ZOOM_2_TO_1_FARTHER);
108  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_1_CLOSER);
109  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_1);
110  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_1_FARTHER);
111  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_2_CLOSER);
112  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_2);
113  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_2_FARTHER);
114  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_4_CLOSER);
115  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_4);
116  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_4_FARTHER);
117  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_8_CLOSER);
118  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_8);
119  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_8_FARTHER);
120  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_16_CLOSER);
121  m_cmbZoom->addItem (LABEL_ZOOM_1_TO_16);
122  m_cmbZoom->addItem (LABEL_ZOOM_FILL);
123  m_cmbZoom->setCurrentText (LABEL_ZOOM_1_TO_1);
124  m_cmbZoom->setMaximumWidth (80);
125  m_cmbZoom->setToolTip (tr ("Select zoom."));
126  m_cmbZoom->setWhatsThis (tr("Select Zoom\n\n"
127  "Points can be more accurately placed by zooming in."));
128  // Zoom combobox must use currentTextChanged rather than activated or else fill-zoom-at-startup never takes effect
129  connect (m_cmbZoom, SIGNAL (currentTextChanged(const QString &)), this, SLOT (slotComboZoom (const QString &)));
130 
131  m_statusBar.addPermanentWidget (m_cmbZoom);
132 }
133 
134 void StatusBar::createZoomMaps ()
135 {
136  m_zoomMapToLabel [ZOOM_16_TO_1] = LABEL_ZOOM_16_TO_1;
137  m_zoomMapToLabel [ZOOM_16_TO_1_FARTHER] = LABEL_ZOOM_16_TO_1_FARTHER;
138  m_zoomMapToLabel [ZOOM_8_TO_1_CLOSER] = LABEL_ZOOM_8_TO_1_CLOSER;
139  m_zoomMapToLabel [ZOOM_8_TO_1] = LABEL_ZOOM_8_TO_1;
140  m_zoomMapToLabel [ZOOM_8_TO_1_FARTHER] = LABEL_ZOOM_8_TO_1_FARTHER;
141  m_zoomMapToLabel [ZOOM_4_TO_1_CLOSER] = LABEL_ZOOM_4_TO_1_CLOSER;
142  m_zoomMapToLabel [ZOOM_4_TO_1] = LABEL_ZOOM_4_TO_1;
143  m_zoomMapToLabel [ZOOM_4_TO_1_FARTHER] = LABEL_ZOOM_4_TO_1_FARTHER;
144  m_zoomMapToLabel [ZOOM_2_TO_1_CLOSER] = LABEL_ZOOM_2_TO_1_CLOSER;
145  m_zoomMapToLabel [ZOOM_2_TO_1] = LABEL_ZOOM_2_TO_1;
146  m_zoomMapToLabel [ZOOM_2_TO_1_FARTHER] = LABEL_ZOOM_2_TO_1_FARTHER;
147  m_zoomMapToLabel [ZOOM_1_TO_1_CLOSER] = LABEL_ZOOM_1_TO_1_CLOSER;
148  m_zoomMapToLabel [ZOOM_1_TO_1] = LABEL_ZOOM_1_TO_1;
149  m_zoomMapToLabel [ZOOM_1_TO_1_FARTHER] = LABEL_ZOOM_1_TO_1_FARTHER;
150  m_zoomMapToLabel [ZOOM_1_TO_2_CLOSER] = LABEL_ZOOM_1_TO_2_CLOSER;
151  m_zoomMapToLabel [ZOOM_1_TO_2] = LABEL_ZOOM_1_TO_2;
152  m_zoomMapToLabel [ZOOM_1_TO_2_FARTHER] = LABEL_ZOOM_1_TO_2_FARTHER;
153  m_zoomMapToLabel [ZOOM_1_TO_4_CLOSER] = LABEL_ZOOM_1_TO_4_CLOSER;
154  m_zoomMapToLabel [ZOOM_1_TO_4] = LABEL_ZOOM_1_TO_4;
155  m_zoomMapToLabel [ZOOM_1_TO_4_FARTHER] = LABEL_ZOOM_1_TO_4_FARTHER;
156  m_zoomMapToLabel [ZOOM_1_TO_8_CLOSER] = LABEL_ZOOM_1_TO_8_CLOSER;
157  m_zoomMapToLabel [ZOOM_1_TO_8] = LABEL_ZOOM_1_TO_8;
158  m_zoomMapToLabel [ZOOM_1_TO_8_FARTHER] = LABEL_ZOOM_1_TO_8_FARTHER;
159  m_zoomMapToLabel [ZOOM_1_TO_16_CLOSER] = LABEL_ZOOM_1_TO_16_CLOSER;
160  m_zoomMapToLabel [ZOOM_1_TO_16] = LABEL_ZOOM_1_TO_16;
161  m_zoomMapToLabel [ZOOM_FILL] = LABEL_ZOOM_FILL;
162 
163  m_zoomMapFromLabel [LABEL_ZOOM_16_TO_1] = ZOOM_16_TO_1;
164  m_zoomMapFromLabel [LABEL_ZOOM_16_TO_1_FARTHER] = ZOOM_16_TO_1_FARTHER;
165  m_zoomMapFromLabel [LABEL_ZOOM_8_TO_1_CLOSER] = ZOOM_8_TO_1_CLOSER;
166  m_zoomMapFromLabel [LABEL_ZOOM_8_TO_1] = ZOOM_8_TO_1;
167  m_zoomMapFromLabel [LABEL_ZOOM_8_TO_1_FARTHER] = ZOOM_8_TO_1_FARTHER;
168  m_zoomMapFromLabel [LABEL_ZOOM_4_TO_1_CLOSER] = ZOOM_4_TO_1_CLOSER;
169  m_zoomMapFromLabel [LABEL_ZOOM_4_TO_1] = ZOOM_4_TO_1;
170  m_zoomMapFromLabel [LABEL_ZOOM_4_TO_1_FARTHER] = ZOOM_4_TO_1_FARTHER;
171  m_zoomMapFromLabel [LABEL_ZOOM_2_TO_1_CLOSER] = ZOOM_2_TO_1_CLOSER;
172  m_zoomMapFromLabel [LABEL_ZOOM_2_TO_1] = ZOOM_2_TO_1;
173  m_zoomMapFromLabel [LABEL_ZOOM_2_TO_1_FARTHER] = ZOOM_2_TO_1_FARTHER;
174  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_1_CLOSER] = ZOOM_1_TO_1_CLOSER;
175  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_1] = ZOOM_1_TO_1;
176  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_1_FARTHER] = ZOOM_1_TO_1_FARTHER;
177  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_2_CLOSER] = ZOOM_1_TO_2_CLOSER;
178  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_2] = ZOOM_1_TO_2;
179  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_2_FARTHER] = ZOOM_1_TO_2_FARTHER;
180  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_4_CLOSER] = ZOOM_1_TO_4_CLOSER;
181  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_4] = ZOOM_1_TO_4;
182  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_4_FARTHER] = ZOOM_1_TO_4_FARTHER;
183  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_8_CLOSER] = ZOOM_1_TO_8_CLOSER;
184  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_8] = ZOOM_1_TO_8;
185  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_8_FARTHER] = ZOOM_1_TO_8_FARTHER;
186  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_16_CLOSER] = ZOOM_1_TO_16_CLOSER;
187  m_zoomMapFromLabel [LABEL_ZOOM_1_TO_16] = ZOOM_1_TO_16;
188  m_zoomMapFromLabel [LABEL_ZOOM_FILL] = ZOOM_FILL;
189 }
190 
191 QString StatusBar::labelCoordsGraph () const
192 {
193  return QString ("%1:").arg (QObject::tr ("Coordinates (graph)"));
194 }
195 
196 QString StatusBar::labelCoordsScreen () const
197 {
198  return QString ("%1:").arg (QObject::tr ("Coordinates (pixels)"));
199 }
200 
201 QString StatusBar::labelResolutionGraph () const
202 {
203  return QString ("%1:").arg (QObject::tr ("Resolution (graph)"));
204 }
205 
206 void StatusBar::setCoordinates (const QString &coordsScreen,
207  const QString &coordsGraph,
208  const QString &resolutionGraph)
209 {
210 // LOG4CPP_DEBUG_S ((*mainCat)) << "StatusBar::setCoordinates"
211 // << " screen=" << coordsScreen.toLatin1 ().data ()
212 // << " graph=" << coordsGraph.toLatin1 ().data ()
213 // << " resolution=" << resolutionGraph.toLatin1 ().data ();
214 
215  if (m_cmbUnits->isEnabled ()) {
216 
217  m_coordsScreen = coordsScreen;
218  m_coordsGraph = coordsGraph;
219  m_resolutionGraph = resolutionGraph;
220 
221  updateCoordsText();
222  }
223 }
224 
225 void StatusBar::setStatusBarMode(StatusBarMode statusBarMode)
226 {
227  m_statusBarMode = statusBarMode;
228  if (m_statusBarMode == STATUS_BAR_MODE_ALWAYS) {
229  m_statusBar.show();
230  } else {
231  m_statusBar.hide();
232  }
233 }
234 
235 void StatusBar::showTemporaryMessage(const QString &message)
236 {
237  LOG4CPP_DEBUG_S ((*mainCat)) << "StatusBar::showTemporaryMessage message=" << message.toLatin1 ().data ();
238 
239  if (m_statusBarMode != STATUS_BAR_MODE_NEVER) {
240  if (m_statusBarMode == STATUS_BAR_MODE_TEMPORARY) {
241  // Calling m_statusBar.show here will have no effect since this is called while processing a signal. Use a timer to
242  // show the status bar as soon as possible
243  m_timer = new QTimer;
244  connect (m_timer, SIGNAL (timeout ()), this, SLOT (slotTimeout()));
245  m_timer->setSingleShot(true);
246  m_timer->start (0);
247  }
248  m_statusBar.showMessage (message, TEMPORARY_MESSAGE_LIFETIME);
249  }
250 }
251 
252 void StatusBar::slotComboUnits (const QString &text)
253 {
254  LOG4CPP_DEBUG_S ((*mainCat)) << "StatusBar::slotComboUnits text=" << text.toLatin1 ().data ();
255 
256  updateCoordsText();
257 }
258 
259 void StatusBar::slotComboZoom (const QString &text)
260 {
261  LOG4CPP_DEBUG_S ((*mainCat)) << "StatusBar::slotComboZoom text=" << text.toLatin1 ().data ();
262 
263  ENGAUGE_ASSERT (m_zoomMapFromLabel.contains (text));
264  ZoomFactor zoomFactor = m_zoomMapFromLabel [text];
265  emit signalZoom (zoomFactor);
266 }
267 
268 void StatusBar::slotStatusBarChanged(const QString &message)
269 {
270  LOG4CPP_DEBUG_S ((*mainCat)) << "StatusBar::slotStatusBarChanged message=" << message.toLatin1 ().data ();
271 
272  if (m_statusBarMode == STATUS_BAR_MODE_TEMPORARY) {
273  m_statusBar.hide();
274  }
275 }
276 
277 void StatusBar::slotTimeout()
278 {
279  LOG4CPP_INFO_S ((*mainCat)) << "StatusBar::slotTimeout";
280 
281  delete m_timer;
282  m_timer = nullptr;
283 
284  m_statusBar.show();
285 }
286 
287 void StatusBar::slotZoom(int zoom)
288 {
289  LOG4CPP_INFO_S ((*mainCat)) << "StatusBar::slotZoom zoom=" << zoom;
290 
291  // Show string for the numeric zoom value
292  ZoomFactor zoomFactor = static_cast<ZoomFactor> (zoom);
293  ENGAUGE_ASSERT (m_zoomMapToLabel.contains (zoomFactor));
294  m_cmbZoom->setCurrentText (m_zoomMapToLabel [zoomFactor]);
295 }
296 
297 void StatusBar::updateCoordsText()
298 {
299  if (m_cmbUnits->currentText() == labelCoordsScreen ()) {
300  m_editCoords->setText (m_coordsScreen);
301  } else if (m_cmbUnits->currentText() == labelCoordsGraph ()) {
302  m_editCoords->setText (m_coordsGraph);
303  } else {
304  m_editCoords->setText (m_resolutionGraph);
305  }
306 }
307 
309 {
310  if (!m_cmbUnits->isEnabled ()) {
311 
312  // First file has just been read in, so enable the widgets
313  m_cmbZoom->setEnabled (true);
314  m_cmbUnits->setEnabled (true);
315  m_editCoords->setEnabled (true);
316  }
317 }
void setStatusBarMode(StatusBarMode statusBarMode)
Set the status bar visibility mode.
Definition: StatusBar.cpp:225
StatusBar(QStatusBar &statusBar)
Single constructor that accepts the previously-constructed standard QStatusBar.
Definition: StatusBar.cpp:27
void setCoordinates(const QString &coordsScreen, const QString &coordsGraph, const QString &resolutionGraph)
Populate the coordinates fields. Unavailable values are empty. Html-encoding to highlight with colors...
Definition: StatusBar.cpp:206
void slotZoom(int)
Receive zoom selection from MainWindow.
Definition: StatusBar.cpp:287
void wakeUp()
Enable all widgets in the status bar. This is called just after a Document becomes active...
Definition: StatusBar.cpp:308
void signalZoom(int)
Send zoom factor, that was just selected in the status bar, to MainWindow.
StatusBarMode statusBarMode() const
Current mode for status bar visibility. This is tracked locally so this class knows when to hide/show...
Definition: StatusBar.h:45
void showTemporaryMessage(const QString &message)
Show temporary message in status bar. After a short interval the message will disappear.
Definition: StatusBar.cpp:235