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
20namespace 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
325
326
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}
This widget encompasses the entire mosaic scene.
void refit()
This method refits t:he items in the graphics view.
Base class for the MosaicTools.
Definition MosaicTool.h:37
QPixmap getIcon(QString iconName) const
returns the path to the icon directory.
bool isActive() const
Returns the activeness of this toool.
Definition MosaicTool.h:50
MosaicZoomTool(MosaicSceneWidget *)
MosaicZoomTool constructor.
void updateTool()
This method updates the line edits text to the correct zoom value.
QWidget * getToolBarWidget()
Creates the widget to add to the tool bar.
void rubberBandComplete(QRectF r, Qt::MouseButton s)
This method is called when the RubberBandTool is complete.
void zoomFitHeight()
Slot for the "Fit to Heighth" menu item on the Fit button.
void zoomOut2X(QPointF center=QPointF())
Zoom out 2 times.
QAction * getPrimaryAction()
This method returns an action that is used to activate this tool.
void zoomFit()
Fits the in the graphics view.
void zoomFitWidth()
Slot for the "Fit to Width" menu item on the Fit button.
void zoomActual(QPointF center=QPointF())
Zoom back to 1 to 1.
void zoomManual()
This method zooms by the value input in the line edit next to the zoom tools.
void zoomIn2X(QPointF center=QPointF())
Zooms in 2 times.
void updateResolutionBox()
Updates the text in the screen resolution display box to the current screen resolution,...
void zoomBy(double factor, QPointF center=QPointF())
Zoom IN by the given factor.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16