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