Isis 3 Programmer Reference
MosaicZoomTool.cpp
1 #include "MosaicZoomTool.h"
2 
3 #include <float.h>
4 #include <iomanip>
5 #include <iostream>
6 
7 #include <QDoubleSpinBox>
8 #include <QGraphicsSceneMouseEvent>
9 #include <QHBoxLayout>
10 #include <QLabel>
11 #include <QMenu>
12 #include <QScrollBar>
13 #include <QToolButton>
14 
15 #include "IString.h"
16 #include "MosaicGraphicsView.h"
17 #include "MosaicSceneWidget.h"
18 #include "Projection.h"
19 
20 namespace Isis {
28  p_scaleBox = NULL;
29 
30  m_zoomInAction = new QAction(this);
31  m_zoomInAction->setIcon(getIcon("viewmag+.png"));
32  m_zoomInAction->setText("Zoom In");
33  m_zoomInAction->setToolTip("Zoom in on the mosaic scene");
34  m_zoomInAction->setShortcut(Qt::Key_Plus);
35  QString text =
36  "<b>Function:</b> Zoom in 2X at the center of the active viewport \
37  <p><b>Shortcut:</b> +</p> \
38  <p><b>Mouse:</b> LeftButton zooms in 2X under pointer</p> \
39  <p><b>Modifiers:</b> Shortcuts and mouse clicks can be augmented \
40  using the Ctrl or Alt key for 4X and 8X zooms, respectively</p> \
41  <p><b>Hint:</b> Left click and drag for a local zoom which scales data \
42  in the marquee to the view</p>";
43  m_zoomInAction->setWhatsThis(text);
44  connect(m_zoomInAction, SIGNAL(triggered()), this, SLOT(zoomIn2X()));
45 
46  m_zoomOutAction = new QAction(this);
47  m_zoomOutAction->setIcon(getIcon("viewmag-.png"));
48  m_zoomOutAction->setText("Zoom Out");
49  m_zoomOutAction->setToolTip("Zoom out on the mosaic scene");
50  m_zoomOutAction->setShortcut(Qt::Key_Minus);
51  text =
52  "<b>Function:</b> Zoom out 2X at the center of the view \
53  <p><b>Shortcut:</b> +</p> \
54  <p><b>Mouse:</b> RightButton zooms out 2X under pointer</p> \
55  <p><b>Modifiers:</b> Shortcuts and mouse clicks can be augmented \
56  using the Ctrl or Alt key for 4X and 8X zooms, respectively</p> \
57  <p><b>Hint:</b> Left click and drag for a local zoom which scales data \
58  in the marquee to the view</p>";
59  m_zoomOutAction->setWhatsThis(text);
60  connect(m_zoomOutAction, SIGNAL(triggered()), this, SLOT(zoomOut2X()));
61 
62  m_zoomFitAction = new QAction(this);
63  m_zoomFitAction->setIcon(getIcon("viewmagfit.png"));
64  m_zoomFitAction->setText("Fit in View");
65  m_zoomFitAction->setToolTip("Zoom to where all of the cubes are visible in "
66  "the mosaic scene");
67  m_zoomFitAction->setShortcut(Qt::Key_Asterisk);
68  text =
69  "<b>Function:</b> Fit the entire mosaic inside the view. \
70  <p><b>Shortcut:</b> *</p> \
71  <p><b>Hint:</b> Many shortcuts for the zoom tool and other tools \
72  are easily available on the numeric keypad </p>";
73  m_zoomFitAction->setWhatsThis(text);
74  connect(m_zoomFitAction, SIGNAL(triggered()), this, SLOT(zoomFit()));
75  }
76 
77 
84  if(p_scaleBox) {
85  // Using these two points we can calculated the scene's width.
86  QPointF point1 = getWidget()->getView()->mapToScene(0, 0);
87  QPointF point2 = getWidget()->getView()->mapToScene(
88  (int)getWidget()->getView()->width(), 0);
89  double newWidth = point2.x() - point1.x();
90 
91  // The scene width divided by the viewport's width gives us the screen res.
92  p_screenResolution = newWidth / getWidget()->getView()->viewport()->width();
93 
94  // Update the text box display
95  p_scaleBox->setValue(p_screenResolution);
96  //------------------------------------------------------------------------
97  // This sets the up and down arrows (on the text box) so that each time a
98  // user clicks them, a resonable amount of zoom happens.
99  //------------------------------------------------------------------------
100  p_scaleBox->setSingleStep(p_screenResolution * .05);
101  }
102  }
103 
104 
105  QList<QAction *> MosaicZoomTool::getViewActions() {
106  QList<QAction *> viewActs;
107 
108  viewActs.append(m_zoomInAction);
109  viewActs.append(m_zoomOutAction);
110  viewActs.append(m_zoomFitAction);
111 
112  return viewActs;
113  }
114 
115 
117  QAction *action = new QAction(this);
118  action->setIcon(getIcon("viewmag.png"));
119  action->setToolTip("Zoom (z)");
120  action->setShortcut(Qt::Key_Z);
121  QString text =
122  "<b>Function:</b> Zoom in or out of the current cube.<br><br>"
123  "This tool gives you a <b>click</b> to zoom by 2X and center on the "
124  "point you clicked on, a <b>right-click</b> to zoom out by 2X and center "
125  "on the point you clicked on, a <b>click and drag</b> box to best fit "
126  "the given area into the visible screen, a <b>right-click and drag</b> "
127  "box to zoom out and center on the center (smaller box means zoom out "
128  "more), and disables context menus on the mosaic scene."
129  "<p><b>Shortcut:</b> z</p> ";
130  action->setWhatsThis(text);
131  return action;
132  }
133 
134 
144  QWidget *hbox = new QWidget;
145 
146  QToolButton *zoomInButton = new QToolButton(hbox);
147  zoomInButton->setAutoRaise(true);
148  zoomInButton->setDefaultAction(m_zoomInAction);
149  zoomInButton->setIconSize(QSize(22, 22));
150 
151  QToolButton *zoomOutButton = new QToolButton(hbox);
152  zoomOutButton->setAutoRaise(true);
153  zoomOutButton->setDefaultAction(m_zoomOutAction);
154  zoomOutButton->setIconSize(QSize(22, 22));
155 
156  QToolButton *zoomFitButton = new QToolButton(hbox);
157  zoomFitButton->setAutoRaise(true);
158  zoomFitButton->setDefaultAction(m_zoomFitAction);
159  zoomFitButton->setIconSize(QSize(22, 22));
160 
161  p_scaleBox = new QDoubleSpinBox();
162  p_scaleBox->setRange(DBL_MIN, DBL_MAX);
163  p_scaleBox->setDecimals(8);
164  connect(p_scaleBox, SIGNAL(editingFinished()), this, SLOT(zoomManual()));
165 
166  QLabel *resolutionLabel = new QLabel("Meters per pixel");
167 
168  QHBoxLayout *layout = new QHBoxLayout(hbox);
169  layout->setMargin(0);
170  layout->addWidget(zoomInButton);
171  layout->addWidget(zoomOutButton);
172 
173  //-------------------------------------------
174  // These two actions are not quite ready yet.
175  // layout->addWidget(zoomActButton);
176  //-------------------------------------------
177  layout->addWidget(zoomFitButton);
178  layout->addWidget(p_scaleBox);
179  layout->addWidget(resolutionLabel);
180  layout->addStretch(1);
181  hbox->setLayout(layout);
182  return hbox;
183  }
184 
185 
186  void MosaicZoomTool::mouseButtonRelease(QPointF mouseLoc, Qt::MouseButton s) {
187  if(!isActive())
188  return;
189 
190  if(s == Qt::LeftButton)
191  zoomIn2X(mouseLoc);
192  else if(s == Qt::RightButton)
193  zoomOut2X(mouseLoc);
194  }
195 
196 
197  void MosaicZoomTool::mouseWheel(QPointF mouseLoc, int delta) {
198  static const double sensitivity = 60.0; // this causes factor of 2 changes
199  double scale = delta / sensitivity;
200 
201  if(delta < 0)
202  scale = 1.0 / (-delta / sensitivity);
203 
204  scale = limitZoomBy(scale);
205 
206  QPoint screenMouseLoc(getWidget()->getView()->mapFromScene(mouseLoc));
207  QPoint screenCenter(
208  getWidget()->getView()->viewport()->size().width() / 2,
209  getWidget()->getView()->viewport()->size().height() / 2);
210 
211  // We're going to do this by zooming on the mouse and then
212  // undo-ing the center in screen pixels.
213  zoomBy(scale, mouseLoc);
214 
215  // The new center screen pixel is:
216  // center - mouseLoc
217  QPoint desiredScreenCenter =
218  screenCenter + (screenCenter - screenMouseLoc);
219  QPointF newCenterPoint =
220  getWidget()->getView()->mapToScene(desiredScreenCenter);
221  getWidget()->getView()->centerOn(newCenterPoint);
222  }
223 
224 
229  void MosaicZoomTool::zoomIn2X(QPointF center) {
230  zoomBy(2.0, center);
231  }
232 
233 
238  void MosaicZoomTool::zoomOut2X(QPointF center) {
239  zoomBy(1.0 / 2.0, center);
240  }
241 
242 
247  void MosaicZoomTool::zoomActual(QPointF center) {
248  zoomBy(1.1, center);
249  }
250 
251 
252  double MosaicZoomTool::limitZoomBy(double factor) {
253  QMatrix matrix = getWidget()->getView()->matrix();
254  matrix = matrix.scale(factor, factor).inverted();
255 
256  int smallerDimension = getWidget()->getView()->width();
257  int largerDimension = getWidget()->getView()->height();
258 
259  if(smallerDimension > largerDimension) {
260  int tmp = smallerDimension;
261  smallerDimension = largerDimension;
262  largerDimension = tmp;
263  }
264 
265  QPointF point1 = matrix.map(QPointF(0, 0));
266  QPointF point2 = matrix.map(QPointF(smallerDimension, 0));
267 
268  // If the factor cannot be done, find the one that can
269  // This max zoom in factor isn't right; I haven't found the number
270  // that corresponds to the Qt bug(?) causing us to not pan correctly on
271  // the zoom in.
272  if((point2.x() - point1.x()) < 1) {
273  QMatrix origMatrix = getWidget()->getView()->matrix();
274  factor = smallerDimension / (origMatrix.m11() * 1.0);
275  }
276 
277  point1 = matrix.map(QPointF(0, 0));
278  point2 = matrix.map(QPointF(largerDimension, 0));
279 
280  if((point2.x() - point1.x()) > 1E10) {
281  QMatrix origMatrix = getWidget()->getView()->matrix();
282  factor = largerDimension / (origMatrix.m11() * 1E10);
283  }
284 
285  return factor;
286  }
287 
288 
295  void MosaicZoomTool::zoomBy(double factor, QPointF center) {
296  factor = limitZoomBy(factor);
297 
298  getWidget()->getView()->scale(factor, factor);
299 
300  if(!center.isNull()) {
301  getWidget()->getView()->centerOn(center);
302  }
303 
305  }
306 
307 
313  getWidget()->refit();
315  }
316 
317 
323 
324  }
325 
326 
333 
334  }
335 
336 
347  if(p_scaleBox) {
348  double x = p_screenResolution / p_scaleBox->value();
349  zoomBy(x);
350  }
351  }
352 
353 
360  if(isActive()) {
361  getWidget()->setCubesSelectable(false);
362  getWidget()->getView()->setContextMenuPolicy(Qt::NoContextMenu);
363  getWidget()->enableRubberBand(true);
364  }
365  else {
366  getWidget()->setCubesSelectable(true);
367  getWidget()->getView()->setContextMenuPolicy(Qt::DefaultContextMenu);
368  getWidget()->enableRubberBand(false);
369  }
370 
372  }
373 
374 
382  void MosaicZoomTool::rubberBandComplete(QRectF r, Qt::MouseButton s) {
383  if(!isActive())
384  return;
385 
386  double meters_pixel = 0.0;
387 
388  //--------------------------------------------------------------------
389  // We only user width or height to determine the desired meters/pixel.
390  // Which ever is larger.
391  //--------------------------------------------------------------------
392  if(r.width() > r.height()) {
393  meters_pixel = r.width() / getWidget()->getView()->viewport()->width();
394  }
395  else {
396  meters_pixel = r.height() / getWidget()->getView()->viewport()->height();
397  }
398 
399  // calculate the scale.
400  double scale = p_screenResolution / meters_pixel;
401 
402  // zooming in.
403  if(s == Qt::LeftButton) {
404  zoomBy(scale, r.center());
405  }
406 
407  // zooming out.
408  if(s == Qt::RightButton) {
409  zoomBy(1 / scale, r.center());
410  }
411 
413  }
414 
415 }
Isis::MosaicZoomTool::getToolBarWidget
QWidget * getToolBarWidget()
Creates the widget to add to the tool bar.
Definition: MosaicZoomTool.cpp:143
Isis::MosaicZoomTool::zoomManual
void zoomManual()
This method zooms by the value input in the line edit next to the zoom tools.
Definition: MosaicZoomTool.cpp:346
QWidget
Isis::MosaicTool::getIcon
QPixmap getIcon(QString iconName) const
returns the path to the icon directory.
Definition: MosaicTool.cpp:115
Isis::MosaicZoomTool::updateTool
void updateTool()
This method updates the line edits text to the correct zoom value.
Definition: MosaicZoomTool.cpp:359
QList< QAction * >
Isis::MosaicZoomTool::zoomBy
void zoomBy(double factor, QPointF center=QPointF())
Zoom IN by the given factor.
Definition: MosaicZoomTool.cpp:295
Isis::MosaicSceneWidget::refit
void refit()
This method refits t:he items in the graphics view.
Definition: MosaicSceneWidget.cpp:1485
Isis::MosaicZoomTool::getPrimaryAction
QAction * getPrimaryAction()
This method returns an action that is used to activate this tool.
Definition: MosaicZoomTool.cpp:116
Isis::MosaicSceneWidget
This widget encompasses the entire mosaic scene.
Definition: MosaicSceneWidget.h:153
Isis::MosaicTool
Base class for the MosaicTools.
Definition: MosaicTool.h:37
Isis::MosaicZoomTool::rubberBandComplete
void rubberBandComplete(QRectF r, Qt::MouseButton s)
This method is called when the RubberBandTool is complete.
Definition: MosaicZoomTool.cpp:382
Isis::MosaicZoomTool::updateResolutionBox
void updateResolutionBox()
Updates the text in the screen resolution display box to the current screen resolution,...
Definition: MosaicZoomTool.cpp:83
Isis::MosaicZoomTool::MosaicZoomTool
MosaicZoomTool(MosaicSceneWidget *)
MosaicZoomTool constructor.
Definition: MosaicZoomTool.cpp:27
Isis::MosaicZoomTool::zoomFit
void zoomFit()
Fits the in the graphics view.
Definition: MosaicZoomTool.cpp:312
Isis::MosaicZoomTool::zoomFitHeight
void zoomFitHeight()
Slot for the "Fit to Heighth" menu item on the Fit button.
Definition: MosaicZoomTool.cpp:332
Isis::MosaicTool::isActive
bool isActive() const
Returns the activeness of this toool.
Definition: MosaicTool.h:50
Isis::MosaicZoomTool::zoomOut2X
void zoomOut2X(QPointF center=QPointF())
Zoom out 2 times.
Definition: MosaicZoomTool.cpp:238
Isis::MosaicZoomTool::zoomFitWidth
void zoomFitWidth()
Slot for the "Fit to Width" menu item on the Fit button.
Definition: MosaicZoomTool.cpp:322
QAction
Isis::MosaicZoomTool::zoomIn2X
void zoomIn2X(QPointF center=QPointF())
Zooms in 2 times.
Definition: MosaicZoomTool.cpp:229
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::MosaicZoomTool::zoomActual
void zoomActual(QPointF center=QPointF())
Zoom back to 1 to 1.
Definition: MosaicZoomTool.cpp:247