Isis 3 Programmer Reference
CubePlotCurve.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "CubePlotCurve.h"
10
11#include <iostream>
12
13#include <QAction>
14#include <QApplication>
15#include <QBuffer>
16#include <QByteArray>
17#include <QClipboard>
18#include <QDataStream>
19#include <QDrag>
20#include <QFileInfo>
21#include <QEvent>
22#include <QMenu>
23#include <QMimeData>
24#include <QMouseEvent>
25#include <QPainter>
26#include <QString>
27
28#include <qwt_legend.h>
29#include <qwt_text.h>
30
31#include "Cube.h"
32#include "CubeViewport.h"
33#include "FileName.h"
34#include "IException.h"
35#include "IString.h"
36#include "CubePlotCurveConfigureDialog.h"
37
38namespace Isis {
50 PlotCurve(xUnits, yUnits) {
51 m_legendItem = NULL;
53 }
54
55
63 CubePlotCurve::CubePlotCurve(const QByteArray &parentAndChildData) :
64 PlotCurve(Unknown, Unknown) {
65 // Copy will get a new legend item widget when attached to the plot in PlotWindow
66 m_legendItem = NULL;
67
68 QByteArray classData = fromByteArray(parentAndChildData);
69
70 QString expectedHeader("PLOT_TOOL_CURVE_V1");
71 int headerKeySize = expectedHeader.toUtf8().size();
72
73 if (classData.size() > headerKeySize) {
74 int dataPos = 0;
75 const char *rawClassData = classData.data();
76
77 QString givenKey = QString::fromUtf8(classData.data() + dataPos,
78 headerKeySize);
79 dataPos += headerKeySize;
80 if (givenKey != expectedHeader) {
81 IString msg = "The given byte array does not contain the required "
82 "header";
83 throw IException(IException::Programmer, msg, _FILEINFO_);
84 }
85
86 int numSourceCubes = *(((int *)(rawClassData + dataPos)));
87 dataPos += sizeof(int);
88
89 for (int i = 0; i < numSourceCubes; i++) {
90 int sourceCubeSize = *(((int *)(rawClassData + dataPos)));
91 dataPos += sizeof(int);
92 QString data = QString::fromUtf8(classData.data() + dataPos,
93 sourceCubeSize);
94 m_sourceCube << data;
95 dataPos += sourceCubeSize;
96 }
97
98 int pointListSize = *(((int *)(rawClassData + dataPos)));
99 dataPos += sizeof(int);
100
101 for (int i = 0; i < pointListSize; i ++) {
102 int npts = *(((int *)(rawClassData + dataPos)));
103 dataPos += sizeof(int);
104
105 QList<QPointF> points;
106 for (int pt = 0; pt < npts; pt++) {
107 double x = *((double *)(rawClassData + dataPos));
108 dataPos += sizeof(double);
109
110 double y = *((double *)(rawClassData + dataPos));
111 dataPos += sizeof(double);
112
113 points.append(QPointF(x, y));
114 }
115 m_pointList.append(points);
116 }
117
118 }
119 else {
120 IString msg = "The given byte array is not large enough to contain the "
121 "required header";
122 throw IException(IException::Programmer, msg, _FILEINFO_);
123 }
124 }
125
126
138 bool blockWidgetFromEvent = false;
139
140 switch (e->type()) {
141 case QEvent::MouseButtonPress: {
142 mousePressEvent((QMouseEvent *)e);
143 blockWidgetFromEvent = true;
144 break;
145 }
146
147 case QEvent::MouseButtonDblClick:
148 case QEvent::MouseButtonRelease:
149 blockWidgetFromEvent = true;
150 break;
151
152
153 default:
154 break;
155 }
156
157 return blockWidgetFromEvent;
158 }
159
160
169 void CubePlotCurve::paint(CubeViewport *vp, QPainter *painter) {
170 if (m_sourceCube.contains(vp->cube()->fileName())) {
171 int i = m_sourceCube.indexOf(vp->cube()->fileName());
172 QPen customPen;
173 customPen.setColor(pen().color());
174 customPen.setWidth(pen().width());
175
176 if (pen().style() != Qt::NoPen)
177 customPen.setStyle(pen().style());
178
179 painter->setPen(customPen);
180 QList< QList <QPointF> > allPoints = sourceVertices();
181 QList<QPointF> points = allPoints.at(i);
182
183 for (int p = 1; p <= points.size(); p++) {
184 int sample1;
185 int sample2;
186 int line1;
187 int line2;
188
189 if (p != points.size()) {
190 vp->cubeToViewport(points[p - 1].x(), points[p - 1].y(), sample1, line1);
191 vp->cubeToViewport(points[p].x(), points[p].y(), sample2, line2);
192 }
193 else {
194 vp->cubeToViewport(points[p - 1].x(), points[p - 1].y(),
195 sample1, line1);
196 vp->cubeToViewport(points[0].x(), points[0].y(), sample2, line2);
197 }
198
199 painter->drawLine(QPoint(sample1, line1), QPoint(sample2, line2));
200 }
201 }
202 }
203
204
211 QList< QList <QPointF> > CubePlotCurve::sourceVertices() const {
212 return m_pointList;
213 }
214
215
223 return m_legendItem;
224 }
225
226
236
237
246 m_renameAutomatically = allowed;
247 }
248
249
257 m_sourceCube = other.m_sourceCube;
258 m_pointList = other.m_pointList;
259 emit needsRepaint();
260 }
261
262
263 void CubePlotCurve::clearSource() {
264
265 if (m_originalName != "" && !m_sourceCube.empty() && m_renameAutomatically) {
266 setTitle(m_originalName);
267 }
268 else if (m_originalName == "") {
269 m_originalName = title().text();
270 }
271
272 m_sourceCube.clear();
273 m_pointList.clear();
274
275 }
276
277
278 void CubePlotCurve::addSource(CubeViewport *cvp, QList<QPoint> screenPoints,
279 int band) {
280
281 if (cvp) {
282 m_sourceCube << cvp->cube()->fileName();
283
285 setTitle(title().text() + " - " +
286 QFileInfo(m_sourceCube.at(m_sourceCube.size()-1)).baseName());
287
288 if (band != -1) {
289 setTitle(title().text() + "+" + IString(band).ToQt());
290 }
291 }
292
293 QList<QPointF> points;
294 foreach (QPoint screenpoint, screenPoints) {
295 double sample = 0.0;
296 double line = 0.0;
297
298 cvp->viewportToCube(screenpoint.x(), screenpoint.y(), sample, line);
299
300 points.append(QPointF(sample, line));
301 }
302 m_pointList.append(points);
303
304 emit needsRepaint();
305 }
306
307 }
308
321 void CubePlotCurve::setSource(CubeViewport *cvp, QList<QPoint> screenPoints,
322 int band) {
323
324 clearSource();
325 addSource(cvp, screenPoints, band);
326// emit needsRepaint();
327 }
328
329
330 void CubePlotCurve::setSource(QList<CubeViewport *> cvps,
331 QList< QList<QPoint> > screenPoints,
332 QList<int> band) {
333 for (int i = 0; i < cvps.size(); i++) {
334 addSource(cvps.at(i), screenPoints.at(i), band.at(i));
335 }
336// emit needsRepaint();
337 }
338
339
345 m_legendItem->installEventFilter(this);
346 // if (!m_legendItem) {
348 // m_legendItem->installEventFilter(this);
349 // connect(m_legendItem, SIGNAL(destroyed(QObject *)),
350 // this, SLOT(updateLegendItemWidget()));
351 //}
352 }
353
354
362 QMimeData *CubePlotCurve::createMimeData() const {
363 QMimeData *mimeData = new QMimeData;
364 mimeData->setData("application/isis3-plot-curve",
365 toByteArray());
366 return mimeData;
367 }
368
369
376 QByteArray CubePlotCurve::toByteArray() const {
377 QByteArray classData;
378
379 classData.append(PlotCurve::toByteArray());
380
381 QString header("PLOT_TOOL_CURVE_V1");
382 int size = header.size();
383 classData.append(header);
384
385 size = m_sourceCube.size();
386 classData.append((char *)&size, sizeof(int));
387
388 for (int i = 0; i < size; i++) {
389 int sourceCubeSize = m_sourceCube.at(i).toUtf8().size();
390 classData.append((char *)&sourceCubeSize, sizeof(int));
391 classData.append(m_sourceCube.at(i).toUtf8());
392 }
393
394 size = m_pointList.size();
395 classData.append((char *)&size, sizeof(int));
396
397 for (int i = 0; i < size; i ++) {
398 QList<QPointF> points = m_pointList[i];
399 int npts = points.size();
400 classData.append((char *)&npts, sizeof(int));
401
402 for (int pt = 0; pt < npts; pt++) {
403 QPointF data = points[pt];
404 double x = data.x();
405 double y = data.y();
406
407 classData.append((char *)&x, sizeof(double));
408 classData.append((char *)&y, sizeof(double));
409 }
410 }
411
412 return classData;
413 }
414
415
423 void CubePlotCurve::mousePressEvent(QMouseEvent *event) {
424 bool deleteThisCurve = false;
425 if (event->button() == Qt::LeftButton) {
426 QDrag *drag = new QDrag(m_legendItem);
427
428 // The icon for drag & drop sometimes gets in the way of the image,
429 // so let's move the image a little more to the right of the cursor
430 // than usual.
431 QPoint newHotSpot = drag->hotSpot();
432 newHotSpot.setX(newHotSpot.x() * 2);
433 drag->setHotSpot(newHotSpot);
434
435 drag->setMimeData(createMimeData());
436 drag->setPixmap( m_legendItem->grab(m_legendItem->rect()) );
437
438 Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction,
439 Qt::CopyAction);
440
441 if (dropAction == Qt::MoveAction) {
442 deleteThisCurve = true;
443 }
444 }
445 else if (event->button() == Qt::RightButton) {
446 QMenu contextMenu;
447
448 QAction *cutAct = new QAction(QIcon::fromTheme("edit-cut"), "Cut", this);
449 contextMenu.addAction(cutAct);
450 QAction *copyAct = new QAction(QIcon::fromTheme("edit-copy"), "Copy",
451 this);
452 // copyAct
453 contextMenu.addAction(copyAct);
454
455 contextMenu.addSeparator();
456
457 QAction *deleteAct = new QAction(QIcon::fromTheme("edit-delete"), "Delete",
458 this);
459 contextMenu.addAction(deleteAct);
460
461 contextMenu.addSeparator();
462
463 QString configureIconFile =
464 FileName("$ISISROOT/appdata/images/icons/plot_configure.png").expanded();
465 QAction *configureAct = new QAction(QPixmap(configureIconFile),
466 "Configure...", this);
467 contextMenu.addAction(configureAct);
468
469 QAction *chosenAct = contextMenu.exec(
470 m_legendItem->mapToGlobal(event->pos()));
471
472 if (chosenAct == cutAct || chosenAct == copyAct) {
473 QApplication::clipboard()->setMimeData(createMimeData());
474
475 if (chosenAct == cutAct) {
476 deleteThisCurve = true;
477 }
478 }
479 // handle the configure action dialog
480 // opens the dialog with only the right-clicked CubePlotCurve
481 else if (chosenAct == configureAct) {
482 CubePlotCurveConfigureDialog configure(this);
483 configure.exec();
484 emit needsRepaint();
485 }
486 else if (chosenAct == deleteAct) {
487 deleteThisCurve = true;
488 }
489 }
490
491 if (deleteThisCurve) {
492 setColor(QColor(255, 255, 255, 0));
493 emit needsRepaint();
494
495 QwtPlot *plotToReplot = plot();
496
497 connect(this, SIGNAL(removing()),
498 this, SLOT(deleteLater()), Qt::QueuedConnection);
499 connect(this, SIGNAL(removing()),
500 plotToReplot, SLOT(replot()), Qt::QueuedConnection);
501 emit removing();
502 }
503 }
504}
This should be an inner class for CubePlotCurve, but Qt doesn't support having a QObject as an inner ...
This is a plot curve with information relating it to a particular cube or region of a cube.
void needsRepaint()
This is emitted when the curve is modified in such a way that it would paint a viewport differently.
CubePlotCurve(Units xUnits, Units yUnits)
This constructs a CubePlotCurve... a subclass of PlotCurve.
QList< QList< QPointF > > sourceVertices() const
This method returns a list of points which are the vertices of the selected area (by the rubberband) ...
void copySource(const CubePlotCurve &other)
This copies the source data from another CubePlotCurve.
void enableAutoRenaming(bool)
This enables/disables the plot curve from changing it's title when the source data changes.
void paint(CubeViewport *vp, QPainter *painter)
Use information inside of the plot curve to paint onto a cube viewport.
QString m_originalName
This is the curve's name before any automatic renaming happened.
void mousePressEvent(QMouseEvent *e)
Handle various events on the legend item.
QStringList sourceCube() const
This method returns the cube view port associated with the curve.
bool m_renameAutomatically
This indicates if we are allowed to modify the title of this curve when the source (origin) data chan...
void removing()
This is emitted just before the cube plot curve is deleted.
QStringList m_sourceCube
The cube that the data is coming from.
QByteArray toByteArray() const
Serialize this plot curve into a binary byte array.
QMimeData * createMimeData() const
This converts the plot curve into a binary, clipboard-compatible storage format (QMimeData).
virtual QWidget * legendItem() const
This method is necessary for getting the correct (event filter altered) legend item.
QPointer< QWidget > m_legendItem
This is the widget legend item associated with this curve.
void setSource(CubeViewport *cvp, QList< QPoint > screenPoints, int band=-1)
Tell this plot curve from where its data originated.
void updateLegendItemWidget(QWidget *legendItem)
This creates a legend item and overrides events from it.
bool eventFilter(QObject *o, QEvent *e)
This will start the drag & drop operation for these curves.
QList< QList< QPointF > > m_pointList
List of vertices in sample,line coordinates from the rubber band.
Widget to display Isis cubes for qt apps.
File name manipulation and expansion.
Definition FileName.h:100
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition FileName.cpp:196
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Adds specific functionality to C++ strings.
Definition IString.h:165
void setColor(const QColor &color)
Set the color of this curve and it's markers.
Definition PlotCurve.cpp:96
QColor color() const
This method returns the color of the curve.
Definition PlotCurve.cpp:55
QByteArray fromByteArray(const QByteArray &classData)
Construct the plot curve given the past results of toByteArray(...).
Units
These are all the possible units for the x or y data in a plot curve.
Definition PlotCurve.h:54
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16