Isis 3 Programmer Reference
CubePlotCurve.cpp
1 #include "IsisDebug.h"
2 
3 #include "CubePlotCurve.h"
4 
5 #include <iostream>
6 
7 #include <QAction>
8 #include <QApplication>
9 #include <QBuffer>
10 #include <QByteArray>
11 #include <QClipboard>
12 #include <QDataStream>
13 #include <QDrag>
14 #include <QFileInfo>
15 #include <QEvent>
16 #include <QMenu>
17 #include <QMimeData>
18 #include <QMouseEvent>
19 #include <QPainter>
20 #include <QString>
21 
22 #include <qwt_legend.h>
23 
24 #include "Cube.h"
25 #include "CubeViewport.h"
26 #include "FileName.h"
27 #include "IException.h"
28 #include "IString.h"
29 #include "CubePlotCurveConfigureDialog.h"
30 
31 namespace Isis {
43  PlotCurve(xUnits, yUnits) {
44  m_legendItem = NULL;
45  m_renameAutomatically = true;
46  }
47 
48 
56  CubePlotCurve::CubePlotCurve(const QByteArray &parentAndChildData) :
57  PlotCurve(Unknown, Unknown) {
58  // Copy will get a new legend item widget when attached to the plot in PlotWindow
59  m_legendItem = NULL;
60 
61  QByteArray classData = fromByteArray(parentAndChildData);
62 
63  QString expectedHeader("PLOT_TOOL_CURVE_V1");
64  int headerKeySize = expectedHeader.toUtf8().size();
65 
66  if (classData.size() > headerKeySize) {
67  int dataPos = 0;
68  const char *rawClassData = classData.data();
69 
70  QString givenKey = QString::fromUtf8(classData.data() + dataPos,
71  headerKeySize);
72  dataPos += headerKeySize;
73  if (givenKey != expectedHeader) {
74  IString msg = "The given byte array does not contain the required "
75  "header";
77  }
78 
79  int numSourceCubes = *(((int *)(rawClassData + dataPos)));
80  dataPos += sizeof(int);
81 
82  for (int i = 0; i < numSourceCubes; i++) {
83  int sourceCubeSize = *(((int *)(rawClassData + dataPos)));
84  dataPos += sizeof(int);
85  QString data = QString::fromUtf8(classData.data() + dataPos,
86  sourceCubeSize);
87  m_sourceCube << data;
88  dataPos += sourceCubeSize;
89  }
90 
91  int pointListSize = *(((int *)(rawClassData + dataPos)));
92  dataPos += sizeof(int);
93 
94  for (int i = 0; i < pointListSize; i ++) {
95  int npts = *(((int *)(rawClassData + dataPos)));
96  dataPos += sizeof(int);
97 
98  QList<QPointF> points;
99  for (int pt = 0; pt < npts; pt++) {
100  double x = *((double *)(rawClassData + dataPos));
101  dataPos += sizeof(double);
102 
103  double y = *((double *)(rawClassData + dataPos));
104  dataPos += sizeof(double);
105 
106  points.append(QPointF(x, y));
107  }
108  m_pointList.append(points);
109  }
110 
111  ASSERT(dataPos == classData.size());
112  }
113  else {
114  IString msg = "The given byte array is not large enough to contain the "
115  "required header";
117  }
118  }
119 
120 
131  bool CubePlotCurve::eventFilter(QObject *o, QEvent *e) {
132  bool blockWidgetFromEvent = false;
133 
134  switch (e->type()) {
135  case QEvent::MouseButtonPress: {
136  mousePressEvent((QMouseEvent *)e);
137  blockWidgetFromEvent = true;
138  break;
139  }
140 
141  case QEvent::MouseButtonDblClick:
142  case QEvent::MouseButtonRelease:
143  blockWidgetFromEvent = true;
144  break;
145 
146 
147  default:
148  break;
149  }
150 
151  return blockWidgetFromEvent;
152  }
153 
154 
163  void CubePlotCurve::paint(CubeViewport *vp, QPainter *painter) {
164  if (m_sourceCube.contains(vp->cube()->fileName())) {
165  int i = m_sourceCube.indexOf(vp->cube()->fileName());
166  QPen customPen;
167  customPen.setColor(pen().color());
168  customPen.setWidth(pen().width());
169 
170  if (pen().style() != Qt::NoPen)
171  customPen.setStyle(pen().style());
172 
173  painter->setPen(customPen);
174  QList< QList <QPointF> > allPoints = sourceVertices();
175  QList<QPointF> points = allPoints.at(i);
176 
177  for (int p = 1; p <= points.size(); p++) {
178  int sample1;
179  int sample2;
180  int line1;
181  int line2;
182 
183  if (p != points.size()) {
184  vp->cubeToViewport(points[p - 1].x(), points[p - 1].y(), sample1, line1);
185  vp->cubeToViewport(points[p].x(), points[p].y(), sample2, line2);
186  }
187  else {
188  vp->cubeToViewport(points[p - 1].x(), points[p - 1].y(),
189  sample1, line1);
190  vp->cubeToViewport(points[0].x(), points[0].y(), sample2, line2);
191  }
192 
193  painter->drawLine(QPoint(sample1, line1), QPoint(sample2, line2));
194  }
195  }
196  }
197 
198 
206  return m_pointList;
207  }
208 
209 
217  return m_legendItem;
218  }
219 
220 
228  return m_sourceCube;
229  }
230 
231 
240  m_renameAutomatically = allowed;
241  }
242 
243 
251  m_sourceCube = other.m_sourceCube;
252  m_pointList = other.m_pointList;
253  emit needsRepaint();
254  }
255 
256 
257  void CubePlotCurve::clearSource() {
258 
259  if (m_originalName != "" && !m_sourceCube.empty() && m_renameAutomatically) {
260  setTitle(m_originalName);
261  }
262  else if (m_originalName == "") {
263  m_originalName = title().text();
264  }
265 
266  m_sourceCube.clear();
267  m_pointList.clear();
268 
269  }
270 
271 
272  void CubePlotCurve::addSource(CubeViewport *cvp, QList<QPoint> screenPoints,
273  int band) {
274 
275  if (cvp) {
276  m_sourceCube << cvp->cube()->fileName();
277 
278  if (m_renameAutomatically) {
279  setTitle(title().text() + " - " +
280  QFileInfo(m_sourceCube.at(m_sourceCube.size()-1)).baseName());
281 
282  if (band != -1) {
283  setTitle(title().text() + "+" + IString(band).ToQt());
284  }
285  }
286 
287  QList<QPointF> points;
288  foreach (QPoint screenpoint, screenPoints) {
289  double sample = 0.0;
290  double line = 0.0;
291 
292  cvp->viewportToCube(screenpoint.x(), screenpoint.y(), sample, line);
293 
294  points.append(QPointF(sample, line));
295  }
296  m_pointList.append(points);
297 
298  emit needsRepaint();
299  }
300 
301  }
302 
316  int band) {
317 
318  clearSource();
319  addSource(cvp, screenPoints, band);
320 // emit needsRepaint();
321  }
322 
323 
325  QList< QList<QPoint> > screenPoints,
326  QList<int> band) {
327  for (int i = 0; i < cvps.size(); i++) {
328  addSource(cvps.at(i), screenPoints.at(i), band.at(i));
329  }
330 // emit needsRepaint();
331  }
332 
333 
339  m_legendItem->installEventFilter(this);
340  // if (!m_legendItem) {
342  // m_legendItem->installEventFilter(this);
343  // connect(m_legendItem, SIGNAL(destroyed(QObject *)),
344  // this, SLOT(updateLegendItemWidget()));
345  //}
346  }
347 
348 
356  QMimeData *CubePlotCurve::createMimeData() const {
357  QMimeData *mimeData = new QMimeData;
358  mimeData->setData("application/isis3-plot-curve",
359  toByteArray());
360  return mimeData;
361  }
362 
363 
370  QByteArray CubePlotCurve::toByteArray() const {
371  QByteArray classData;
372 
373  classData.append(PlotCurve::toByteArray());
374 
375  QString header("PLOT_TOOL_CURVE_V1");
376  int size = header.size();
377  classData.append(header);
378 
379  size = m_sourceCube.size();
380  classData.append((char *)&size, sizeof(int));
381 
382  for (int i = 0; i < size; i++) {
383  int sourceCubeSize = m_sourceCube.at(i).toUtf8().size();
384  classData.append((char *)&sourceCubeSize, sizeof(int));
385  classData.append(m_sourceCube.at(i).toUtf8());
386  }
387 
388  size = m_pointList.size();
389  classData.append((char *)&size, sizeof(int));
390 
391  for (int i = 0; i < size; i ++) {
392  QList<QPointF> points = m_pointList[i];
393  int npts = points.size();
394  classData.append((char *)&npts, sizeof(int));
395 
396  for (int pt = 0; pt < npts; pt++) {
397  QPointF data = points[pt];
398  double x = data.x();
399  double y = data.y();
400 
401  classData.append((char *)&x, sizeof(double));
402  classData.append((char *)&y, sizeof(double));
403  }
404  }
405 
406  return classData;
407  }
408 
409 
417  void CubePlotCurve::mousePressEvent(QMouseEvent *event) {
418  bool deleteThisCurve = false;
419  if (event->button() == Qt::LeftButton) {
420  QDrag *drag = new QDrag(m_legendItem);
421 
422  // The icon for drag & drop sometimes gets in the way of the image,
423  // so let's move the image a little more to the right of the cursor
424  // than usual.
425  QPoint newHotSpot = drag->hotSpot();
426  newHotSpot.setX(newHotSpot.x() * 2);
427  drag->setHotSpot(newHotSpot);
428 
429  drag->setMimeData(createMimeData());
430  drag->setPixmap( m_legendItem->grab(m_legendItem->rect()) );
431 
432  Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction,
433  Qt::CopyAction);
434 
435  if (dropAction == Qt::MoveAction) {
436  deleteThisCurve = true;
437  }
438  }
439  else if (event->button() == Qt::RightButton) {
440  QMenu contextMenu;
441 
442  QAction *cutAct = new QAction(QIcon::fromTheme("edit-cut"), "Cut", this);
443  contextMenu.addAction(cutAct);
444  QAction *copyAct = new QAction(QIcon::fromTheme("edit-copy"), "Copy",
445  this);
446  // copyAct
447  contextMenu.addAction(copyAct);
448 
449  contextMenu.addSeparator();
450 
451  QAction *deleteAct = new QAction(QIcon::fromTheme("edit-delete"), "Delete",
452  this);
453  contextMenu.addAction(deleteAct);
454 
455  contextMenu.addSeparator();
456 
457  QString configureIconFile =
458  FileName("$base/icons/plot_configure.png").expanded();
459  QAction *configureAct = new QAction(QPixmap(configureIconFile),
460  "Configure...", this);
461  contextMenu.addAction(configureAct);
462 
463  QAction *chosenAct = contextMenu.exec(
464  m_legendItem->mapToGlobal(event->pos()));
465 
466  if (chosenAct == cutAct || chosenAct == copyAct) {
467  QApplication::clipboard()->setMimeData(createMimeData());
468 
469  if (chosenAct == cutAct) {
470  deleteThisCurve = true;
471  }
472  }
473  // handle the configure action dialog
474  // opens the dialog with only the right-clicked CubePlotCurve
475  else if (chosenAct == configureAct) {
476  CubePlotCurveConfigureDialog configure(this);
477  configure.exec();
478  emit needsRepaint();
479  }
480  else if (chosenAct == deleteAct) {
481  deleteThisCurve = true;
482  }
483  }
484 
485  if (deleteThisCurve) {
486  setColor(QColor(255, 255, 255, 0));
487  emit needsRepaint();
488 
489  QwtPlot *plotToReplot = plot();
490 
491  connect(this, SIGNAL(removing()),
492  this, SLOT(deleteLater()), Qt::QueuedConnection);
493  connect(this, SIGNAL(removing()),
494  plotToReplot, SLOT(replot()), Qt::QueuedConnection);
495  emit removing();
496  }
497  }
498 }
bool eventFilter(QObject *o, QEvent *e)
This will start the drag & drop operation for these curves.
QStringList sourceCube() const
This method returns the cube view port associated with the curve.
QStringList m_sourceCube
The cube that the data is coming from.
Cube * cube() const
Definition: CubeViewport.h:348
void copySource(const CubePlotCurve &other)
This copies the source data from another CubePlotCurve.
File name manipulation and expansion.
Definition: FileName.h:116
void setSource(CubeViewport *cvp, QList< QPoint > screenPoints, int band=-1)
Tell this plot curve from where its data originated.
void needsRepaint()
This is emitted when the curve is modified in such a way that it would paint a viewport differently...
Widget to display Isis cubes for qt apps.
Definition: CubeViewport.h:132
void cubeToViewport(double sample, double line, int &x, int &y) const
Turns a cube into a viewport.
QPointer< QWidget > m_legendItem
This is the widget legend item associated with this curve.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
void updateLegendItemWidget(QWidget *legendItem)
This creates a legend item and overrides events from it.
void enableAutoRenaming(bool)
This enables/disables the plot curve from changing it&#39;s title when the source data changes...
QString m_originalName
This is the curve&#39;s name before any automatic renaming happened.
QMimeData * createMimeData() const
This converts the plot curve into a binary, clipboard-compatible storage format (QMimeData).
This is a plot curve with information relating it to a particular cube or region of a cube...
Definition: CubePlotCurve.h:68
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
QColor color() const
This method returns the color of the curve.
Definition: PlotCurve.cpp:56
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
void setColor(const QColor &color)
Set the color of this curve and it&#39;s markers.
Definition: PlotCurve.cpp:97
QList< QList< QPointF > > sourceVertices() const
This method returns a list of points which are the vertices of the selected area (by the rubberband) ...
void mousePressEvent(QMouseEvent *e)
Handle various events on the legend item.
This should be an inner class for CubePlotCurve, but Qt doesn&#39;t support having a QObject as an inner ...
QByteArray fromByteArray(const QByteArray &classData)
Construct the plot curve given the past results of toByteArray(...).
Definition: PlotCurve.cpp:145
virtual QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1208
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
bool m_renameAutomatically
This indicates if we are allowed to modify the title of this curve when the source (origin) data chan...
QList< QList< QPointF > > m_pointList
List of vertices in sample,line coordinates from the rubber band.
CubePlotCurve(Units xUnits, Units yUnits)
This constructs a CubePlotCurve...
void removing()
This is emitted just before the cube plot curve is deleted.
Units
These are all the possible units for the x or y data in a plot curve.
Definition: PlotCurve.h:54
QByteArray toByteArray() const
Serialize this plot curve into a binary byte array.
virtual QWidget * legendItem() const
This method is necessary for getting the correct (event filter altered) legend item.
void paint(CubeViewport *vp, QPainter *painter)
Use information inside of the plot curve to paint onto a cube viewport.