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