USGS

Isis 3.0 Object Programmers' Reference

Home

RubberBandComboBox.cpp
1 #include "RubberBandComboBox.h"
2 
3 #include <QAction>
4 
5 #include "Tool.h"
6 
7 namespace Isis {
16  RubberBandComboBox::RubberBandComboBox(Tool *tool, unsigned int bandingOptions,
17  unsigned int defaultOption, bool showIndicatorColors) : QComboBox() {
18  m_tool = tool;
19 
20  m_showIndicatorColors = showIndicatorColors;
21  setDuplicatesEnabled(false);
22  setEditable(false);
23  setIconSize(QSize(24, 24));
24 
25  // We must call setCurrentIndex with the default, or the banding mode won't be set properly. Thus,
26  // we do need a default even if they pass in zero, which means default.
27  defaultOption = getDefault(defaultOption, bandingOptions);
28 
29  QAction *escapeKeyHit = new QAction(this);
30  escapeKeyHit->setShortcut(Qt::Key_Escape);
31  connect(escapeKeyHit, SIGNAL(activated()), m_tool->rubberBandTool(), SLOT(escapeKeyPress()));
32  addAction(escapeKeyHit);
33 
34  // The tool tip and what's this need to be set. The tool tip won't change, but the what's this should detail how to use the
35  // tools. So, set the tool tip and start the what's this. The what's this should only have the available tools, so create it as
36  // we add the tools.
37  setToolTip("Select Measurement Type");
38  QString whatsThis =
39  "<b>Function:</b> This drop down will enable you to switch between drawing various shapes.";
40 
41  m_bandingOptionStrings.push_back("Circle");
42  if((bandingOptions & Circle) == Circle) {
43  QIcon circleIcon(toolIconDir() + "/qview_circle.png");
44  circleIcon.addFile(toolIconDir() + "/qview_circle_active.png", QSize(24, 24), QIcon::Active);
45 
46  addItem(circleIcon, m_bandingOptionStrings[m_bandingOptionStrings.size()-1], QVariant((int)Circle));
47 
48  whatsThis += "<br><br>When <b>Circle</b> is selected, you can draw a perfect circle. To draw a circle, \
49  click at a corner of the circle, drag the mouse until the circle is the correct shape, and release the mouse \
50  to complete the circle.";
51 
52  if((defaultOption & Circle) == Circle) {
53  setCurrentIndex(findText(m_bandingOptionStrings[ m_bandingOptionStrings.size()-1 ]));
54  }
55  }
56 
57  m_bandingOptionStrings.push_back("Ellipse");
58  if((bandingOptions & Ellipse) == Ellipse) {
59  QIcon ellipseIcon(toolIconDir() + "/qview_ellipse.png");
60  ellipseIcon.addFile(toolIconDir() + "/qview_ellipse_active.png", QSize(24, 24), QIcon::Active);
61 
62  addItem(ellipseIcon, m_bandingOptionStrings[m_bandingOptionStrings.size()-1], QVariant((int)Ellipse));
63 
64  whatsThis += "<br><br>When <b>Ellipse</b> is selected, you can draw an ellipse. To draw an ellipse, \
65  click at a corner of the ellipse, drag the mouse until the ellipse is the correct shape, and release the mouse \
66  to complete the ellipse.";
67 
68  if((defaultOption & Ellipse) == Ellipse) {
69  setCurrentIndex(findText(m_bandingOptionStrings[ m_bandingOptionStrings.size()-1 ]));
70  }
71  }
72 
73  m_bandingOptionStrings.push_back("Rectangle");
74  if((bandingOptions & Rectangle) == Rectangle) {
75  QIcon rectangleIcon(toolIconDir() + "/qview_rectangle.png");
76  rectangleIcon.addFile(toolIconDir() + "/qview_rectangle_active.png", QSize(24, 24), QIcon::Active);
77 
78  addItem(rectangleIcon, m_bandingOptionStrings[m_bandingOptionStrings.size()-1], QVariant((int)Rectangle));
79 
80  whatsThis += "<br><br>When <b>Rectangle</b> is selected, you can draw a rectangle. To draw a rectangle, \
81  click a corner of the rectangle, drag the mouse until the rectangle is the correct size and shape, and release the mouse \
82  to complete the rectangle.";
83 
84  if((defaultOption & Rectangle) == Rectangle) {
85  setCurrentIndex(findText(m_bandingOptionStrings[ m_bandingOptionStrings.size()-1 ]));
86  }
87  }
88 
89  m_bandingOptionStrings.push_back("Rotated Rectangle");
90  if((bandingOptions & RotatedRectangle) == RotatedRectangle) {
91  QIcon rotatedRectangleIcon(toolIconDir() + "/qview_rotated_rectangle.png");
92 
93  addItem(rotatedRectangleIcon, m_bandingOptionStrings[m_bandingOptionStrings.size()-1], QVariant((int)RotatedRectangle));
94 
95  whatsThis += "<br><br>When <b>Rotated Rectangle</b> is selected, you can draw a rectangle rotated about its center. To draw a rotated rectangle, \
96  click, drag the mouse to form the first side of the rectangle and determine it's rotation, and release the mouse. \
97  Now, the final side of the rotated rectangle should follow the mouse. \
98  Click again when the rotated rectangle is the correct size to complete the rotated rectangle.";
99 
101  whatsThis += " The data will be calculated starting from the initial (GREEN) side of the rotated rectangle and ending at the opposite \
102  side of the rotated rectangle.";
103  }
104 
105  if((defaultOption & RotatedRectangle) == RotatedRectangle) {
106  setCurrentIndex(findText(m_bandingOptionStrings[ m_bandingOptionStrings.size()-1 ]));
107  }
108  }
109 
110  m_bandingOptionStrings.push_back("Polygon");
111  if((bandingOptions & Polygon) == Polygon) {
112  QIcon polygonIcon(toolIconDir() + "/qview_polygon.png");
113 
114  addItem(polygonIcon, m_bandingOptionStrings[m_bandingOptionStrings.size()-1], QVariant((int)Polygon));
115 
116  whatsThis += "<br><br>When <b>Polygon</b> is selected, you can draw any closed polygon. To begin drawing a polygon, \
117  click where you want the start point. Now, click for any new vertices or click and drag the mouse to form irregular shapes. \
118  When completed, double click the final vertex and the figure will close.";
119 
120  if((defaultOption & Polygon) == Polygon) {
121  setCurrentIndex(findText(m_bandingOptionStrings[ m_bandingOptionStrings.size()-1 ]));
122  }
123  }
124 
125  m_bandingOptionStrings.push_back("Line");
126  if((bandingOptions & Line) == Line) {
127  QIcon lineIcon(toolIconDir() + "/qview_line.png");
128  lineIcon.addFile(toolIconDir() + "/qview_line_active.png", QSize(24, 24), QIcon::Active);
129 
130  addItem(lineIcon, m_bandingOptionStrings[m_bandingOptionStrings.size()-1], QVariant((int)Line));
131 
132  whatsThis += "<br><br>When <b>Line</b> is selected, you can draw a line. "
133  "To draw a line, click the starting point of the line, drag the "
134  "mouse until the line is the correct length in the correct direction,"
135  " and release the mouse. To draw vertical or horizontal lines, press"
136  " and hold the control key while drawing your line";
137 
138  if((defaultOption & Line) == Line) {
139  setCurrentIndex(findText(m_bandingOptionStrings[ m_bandingOptionStrings.size()-1 ]));
140  }
141  }
142 
143  m_bandingOptionStrings.push_back("Segmented Line");
144  if((bandingOptions & SegmentedLine) == SegmentedLine) {
145  QIcon segmentedLineIcon(toolIconDir() + "/qview_segmentedline.png");
146 
147  addItem(segmentedLineIcon, m_bandingOptionStrings[m_bandingOptionStrings.size()-1], QVariant((int)SegmentedLine));
148 
149  whatsThis += "<br><br>When <b>Segmented Line</b> is selected, you can draw any open polygon. To begin drawing a segmented line, \
150  click where you want the start point. Now, click for any new vertices or click and drag the mouse to form irregular shapes. \
151  When completed, double click the final vertex.";
152 
153  if((defaultOption & SegmentedLine) == SegmentedLine) {
154  setCurrentIndex(findText(m_bandingOptionStrings[ m_bandingOptionStrings.size()-1 ]));
155  }
156  }
157 
158  m_bandingOptionStrings.push_back("Angle");
159  if((bandingOptions & Angle) == Angle) {
160  QIcon angleIcon;
161  angleIcon.addFile(toolIconDir() + "/qview_angle.png", QSize(24, 24), QIcon::Normal);
162  //angleIcon.addFile(toolIconDir()+"/qview_angle_active.png", QSize(24,24), QIcon::Active);
163 
164  addItem(angleIcon, m_bandingOptionStrings[m_bandingOptionStrings.size()-1], QVariant((int)Angle));
165 
166  whatsThis += "<br><br>When <b>Angle</b> is selected, you can draw an angle from zero to 180 degrees. To draw an angle, \
167  click where the first corner should go, then click where the vertex should go. Finally, click where the final \
168  side of the angle should end to complete the angle.";
169 
170  if((defaultOption & Angle) == Angle) {
171  setCurrentIndex(findText(m_bandingOptionStrings[ m_bandingOptionStrings.size()-1 ]));
172  }
173  }
174 
175  connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(selectionChanged(int)));
176  connect(this, SIGNAL(activated(int)), this, SLOT(selectionChanged(int)));
177 
178  setWhatsThis(whatsThis);
179  }
180 
181 
190  switch(itemData(index).toInt()) {
191  case Angle:
192  showAngle();
193  break;
194  case Circle:
195  showCircle();
196  break;
197  case Ellipse:
198  showEllipse();
199  break;
200  case Line:
201  showLine();
202  break;
203  case Rectangle:
204  showRectangle();
205  break;
206  case RotatedRectangle:
208  break;
209  case Polygon:
210  showPolygon();
211  break;
212  case SegmentedLine:
214  break;
215  default:
216  // This shouldn't happen
217  m_tool->rubberBandTool()->disable();
218  break;
219  }
220  }
221 
227  selectionChanged(currentIndex());
228  }
229 
230 
240  unsigned int RubberBandComboBox::getDefault(unsigned int defaultOption, unsigned int bandingOptions) {
241  // The default will always be to set
242  // the default selection to the first, and thus the least significant bit in bandingOptions.
243  // We're going to find the least significant bit by shifting left and right the same amount of times,
244  // causing the bits to be truncated, until we see the result isn't the same as the beginning which means
245  // a bit was truncated. When we see this, we know where the least significant bit is so shift a '1' left by
246  // the appropriate amount.
247  if(defaultOption == 0) {
248  defaultOption = bandingOptions;
249  }
250 
251  // Find the least significant bit, that's our default.
252  int power = 0;
253 
254  // While cuting off the next significant bit does nothing, keep going.
255  while(((defaultOption >> (power + 1)) << (power + 1)) == defaultOption) {
256  power ++;
257  }
258 
259  defaultOption = 1 << power;
260 
261  // We are done figuring out the default option.
262  return defaultOption;
263  }
264 }