Isis 3 Programmer Reference
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(triggered()), 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 }
void showRectangle()
Enables the rectangle shape.
void showLine()
Enables the line.
void reset()
Resets the selection.
void showCircle()
Enables the circle shape.
QString toolIconDir() const
Returns the icon directory.
void showSegmentedLine()
Enables the segmented line shape.
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:108
void showRotatedRectangle()
Enables the rotated rectangle shape.
bool m_showIndicatorColors
Show colors?
void showAngle()
Enables the angle shape.
RubberBandComboBox(Tool *tool, unsigned int bandingOptions, unsigned int defaultOption, bool showIndicatorColors=false)
RubberBandComboBox constructor.
void showPolygon()
Enables the polygon shape.
void selectionChanged(int index)
This slot is called whenever the rubberband shape selection has changed.
Defines an angle and provides unit conversions.
Definition: Angle.h:62
unsigned int getDefault(unsigned int defaultOption, unsigned int bandingOptions)
This is used to figure out which option should be defaulted.
void disable()
This is called when something is not using me, so turn off events, reset & repaint to clear the clear...
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
Base class for the Qisis tools.
Definition: Tool.h:81
void showEllipse()
Enables the ellipse shape.
QStringList m_bandingOptionStrings
List of rubberband options.