scidavis  2.3.0
About: SciDAVis is a free application for Scientific Data Analysis and Visualization (a fork off of QtiPlot).
  Fossies Dox: scidavis-2.3.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

DataPickerTool.cpp
Go to the documentation of this file.
1 
13 
31 #include "DataPickerTool.h"
32 #include "Graph.h"
33 #include "Plot.h"
34 #include "FunctionCurve.h"
35 #include "PlotCurve.h"
36 #include "QwtErrorPlotCurve.h"
37 #include "ApplicationWindow.h"
38 #include "core/column/Column.h"
39 
40 #include <qwt_symbol.h>
41 #include <qwt_plot_picker.h>
42 #include <qwt_plot_curve.h>
43 #include <qwt_scale_draw.h>
44 #include <QMessageBox>
45 #include <QLocale>
46 #include <QKeyEvent>
47 #include <QMouseEvent>
48 
49 DataPickerTool::DataPickerTool(Graph *graph, ApplicationWindow *app, Mode mode, const QObject *status_target, const char *status_slot) :
50  QwtPlotPicker(graph->plotWidget()->canvas()),
51  PlotToolInterface(graph),
52  d_app(app),
53  d_mode(mode),
54  d_move_mode(Free)
55 {
56  d_selected_curve = NULL;
57 
58  d_selection_marker.setSymbol(QwtSymbol(QwtSymbol::Ellipse, QBrush(QColor(255,255,0,128)), QPen(Qt::black,2), QSize(20,20)));
59  d_selection_marker.setLineStyle(QwtPlotMarker::Cross);
60  d_selection_marker.setLinePen(QPen(Qt::red,1));
61 
62  setTrackerMode(QwtPicker::AlwaysOn);
63  if (d_mode == Move) {
64  setSelectionFlags(QwtPicker::PointSelection | QwtPicker::DragSelection);
65  d_graph->plotWidget()->canvas()->setCursor(Qt::PointingHandCursor);
66  } else {
67  setSelectionFlags(QwtPicker::PointSelection | QwtPicker::ClickSelection);
68  d_graph->plotWidget()->canvas()->setCursor(QCursor(QPixmap(":/vizor.xpm"), -1, -1));
69  }
70 
71  if (status_target)
72  connect(this, SIGNAL(statusText(const QString&)), status_target, status_slot);
73  switch(d_mode) {
74  case Display:
75  emit statusText(tr("Click on plot or move cursor to display coordinates!"));
76  break;
77  case Move:
78  emit statusText(tr("Please, click on plot and move cursor!"));
79  break;
80  case Remove:
81  emit statusText(tr("Select point and double click to remove it!"));
82  break;
83  }
84 }
85 
87 {
88  d_selection_marker.detach();
89  d_graph->plotWidget()->canvas()->unsetCursor();
90 }
91 
92 void DataPickerTool::append(const QPoint &pos)
93 {
94  int dist, point_index;
95  const int curve = d_graph->plotWidget()->closestCurve(pos.x(), pos.y(), dist, point_index);
96  if (curve <= 0 || dist >= 5) { // 5 pixels tolerance
97  setSelection(NULL, 0);
98  return;
99  }
100  setSelection((QwtPlotCurve *)d_graph->plotWidget()->curve(curve), point_index);
101  if (!d_selected_curve) return;
102 
103  QwtPlotPicker::append(transform(QwtDoublePoint(d_selected_curve->x(d_selected_point),
105 }
106 
107 void DataPickerTool::setSelection(QwtPlotCurve *curve, int point_index)
108 {
109  if (curve == d_selected_curve && point_index == d_selected_point)
110  return;
111 
112  d_selected_curve = curve;
113  d_selected_point = point_index;
114 
115  if (!d_selected_curve) {
116  d_selection_marker.detach();
117  d_graph->plotWidget()->replot();
118  return;
119  }
120 
121  setAxis(d_selected_curve->xAxis(), d_selected_curve->yAxis());
122 
123  d_move_target_pos = QPoint(plot()->transform(xAxis(), d_selected_curve->x(d_selected_point)),
124  plot()->transform(yAxis(), d_selected_curve->y(d_selected_point)));
125 
126  if (((PlotCurve *)d_selected_curve)->type() == Graph::Function)
127  {
128  emit statusText(QString("%1[%2]: x=%3; y=%4")
129  .arg(d_selected_curve->title().text())
130  .arg(d_selected_point + 1)
132  .arg(QLocale().toString(d_selected_curve->y(d_selected_point), 'G', d_app->d_decimal_digits)));
133  }
134  else
135  {
136  int row = ((DataCurve*)d_selected_curve)->tableRow(d_selected_point);
137 
138  Table *t = ((DataCurve*)d_selected_curve)->table();
139  int xCol = t->colIndex(((DataCurve*)d_selected_curve)->xColumnName());
140  int yCol = t->colIndex(d_selected_curve->title().text());
141 
142  emit statusText(QString("%1[%2]: x=%3; y=%4")
143  .arg(d_selected_curve->title().text())
144  .arg(row + 1)
145  .arg(t->text(row, xCol))
146  .arg(t->text(row, yCol)));
147  }
148 
149  QwtDoublePoint selected_point_value(d_selected_curve->x(d_selected_point), d_selected_curve->y(d_selected_point));
150  d_selection_marker.setValue(selected_point_value);
151  if (d_selection_marker.plot() == NULL)
153  d_graph->plotWidget()->replot();
154 }
155 
156 bool DataPickerTool::eventFilter(QObject *obj, QEvent *event)
157 {
158  switch(event->type()) {
159  case QEvent::MouseButtonDblClick:
160  switch(d_mode) {
161  case Remove:
162  removePoint();
163  return true;
164  default:
165  if (d_selected_curve)
167  return true;
168  }
169  case QEvent::MouseMove:
170  if (((QMouseEvent *)event)->modifiers() == Qt::ControlModifier)
172  else if (((QMouseEvent *)event)->modifiers() == Qt::AltModifier)
174  else
175  d_move_mode = Free;
176  break;
177 
178  case QEvent::KeyPress:
179  if (keyEventFilter((QKeyEvent*)event))
180  return true;
181  break;
182  default:
183  break;
184  }
185  return QwtPlotPicker::eventFilter(obj, event);
186 }
187 
189 {
190  const int delta = 5;
191  switch(ke->key()) {
192  case Qt::Key_Enter:
193  case Qt::Key_Return:
194  if (d_selected_curve)
196  return true;
197 
198  case Qt::Key_Up:
199  if (d_graph && d_selected_curve)
200  {
201  int n_curves = d_graph->curves();
202  int start = d_graph->curveIndex(d_selected_curve) + 1;
203  QwtPlotCurve *c;
204  for (int i = start; i < start + n_curves; ++i)
205  if ((c=d_graph->curve(i % n_curves))->dataSize() > 0) {
206  setSelection(c, qMin(c->dataSize()-1, d_selected_point));
207  break;
208  }
209  d_graph->plotWidget()->replot();
210  }
211  return true;
212 
213  case Qt::Key_Down:
214  if (d_graph && d_selected_curve)
215  {
216  int n_curves = d_graph->curves();
217  int start = d_graph->curveIndex(d_selected_curve) + n_curves - 1;
218  QwtPlotCurve *c;
219  for (int i = start; i > start - n_curves; --i)
220  if ((c=d_graph->curve(i % n_curves))->dataSize() > 0) {
221  setSelection(c, qMin(c->dataSize()-1, d_selected_point));
222  break;
223  }
224  d_graph->plotWidget()->replot();
225  }
226  return true;
227 
228  case Qt::Key_Right:
229  case Qt::Key_Plus:
230  if (d_graph)
231  {
232  if (d_selected_curve) {
233  int n_points = d_selected_curve->dataSize();
235  d_graph->plotWidget()->replot();
236  }
237  else
238  setSelection(d_graph->curve(0), 0);
239  }
240  return true;
241 
242  case Qt::Key_Left:
243  case Qt::Key_Minus:
244  if (d_graph)
245  {
246  if (d_selected_curve) {
247  int n_points = d_selected_curve->dataSize();
248  setSelection(d_selected_curve, (d_selected_point - 1 + n_points) % n_points);
249  d_graph->plotWidget()->replot();
250  }
251  else
253  }
254  return true;
255 
256  // The following keys represent a direction, they are
257  // organized on the keyboard.
258  case Qt::Key_1:
259  if (d_mode == Move) {
260  moveBy(-delta, delta);
261  return true;
262  }
263  break;
264  case Qt::Key_2:
265  if (d_mode == Move) {
266  moveBy(0, delta);
267  return true;
268  }
269  break;
270  case Qt::Key_3:
271  if (d_mode == Move) {
272  moveBy(delta, delta);
273  return true;
274  }
275  break;
276  case Qt::Key_4:
277  if (d_mode == Move) {
278  moveBy(-delta, 0);
279  return true;
280  }
281  break;
282  case Qt::Key_6:
283  if (d_mode == Move) {
284  moveBy(delta, 0);
285  return true;
286  }
287  break;
288  case Qt::Key_7:
289  if (d_mode == Move) {
290  moveBy(-delta, -delta);
291  return true;
292  }
293  break;
294  case Qt::Key_8:
295  if (d_mode == Move) {
296  moveBy(0, -delta);
297  return true;
298  }
299  break;
300  case Qt::Key_9:
301  if (d_mode == Move) {
302  moveBy(delta, -delta);
303  return true;
304  }
305  break;
306  default:
307  break;
308  }
309  return false;
310 }
311 
313 {
314  if ( !d_selected_curve )
315  return;
316  if (((PlotCurve *)d_selected_curve)->type() == Graph::Function){
317  QMessageBox::critical(const_cast<Graph*>(d_graph), tr("Remove point error"),
318  tr("Sorry, but removing points of a function is not possible."));
319  return;
320  }
321 
322  Table *t = ((DataCurve *)d_selected_curve)->table();
323  if (!t)
324  return;
325 
326  int col = t->colIndex(d_selected_curve->title().text());
327  if (t->columnType(col) == Table::Numeric)
328  {
329  t->column(col)->setValueAt(((DataCurve *)d_selected_curve)->tableRow(d_selected_point), 0.0);
330  t->column(col)->setInvalid(((DataCurve *)d_selected_curve)->tableRow(d_selected_point), true);
331  }
332  else {
333  QMessageBox::warning(const_cast<Graph*>(d_graph), tr("Warning"),
334  tr("This operation cannot be performed on curves plotted from columns having a non-numerical format."));
335  }
336 
337  d_selection_marker.detach();
338  d_graph->plotWidget()->replot();
339  d_graph->setFocus();
340  d_selected_curve = NULL;
341 }
342 
343 void DataPickerTool::move(const QPoint &point)
344 {
345  if (d_mode == Move && d_selected_curve){
346  switch (d_move_mode){
347  case Free:
348  d_move_target_pos = point;
349  break;
350  case Vertical:
351  d_move_target_pos.setY(point.y());
352  break;
353  case Horizontal:
354  d_move_target_pos.setX(point.x());
355  break;
356  }
357  double new_x_val = d_graph->plotWidget()->invTransform(d_selected_curve->xAxis(), d_move_target_pos.x());
358  double new_y_val = d_graph->plotWidget()->invTransform(d_selected_curve->yAxis(), d_move_target_pos.y());
359  d_selection_marker.setValue(new_x_val, new_y_val);
360  if (d_selection_marker.plot() == NULL)
362  d_graph->replot();
363 
364  int row = ((DataCurve *)d_selected_curve)->tableRow(d_selected_point);
365  emit statusText(QString("%1[%2]: x=%3; y=%4")
366  .arg(d_selected_curve->title().text())
367  .arg(row + 1)
368  .arg(QLocale().toString(new_x_val, 'G', d_app->d_decimal_digits))
369  .arg(QLocale().toString(new_y_val, 'G', d_app->d_decimal_digits)) );
370  }
371 
372  QwtPlotPicker::move(d_move_target_pos);
373 }
374 
375 bool DataPickerTool::end(bool ok)
376 {
377  if (d_mode == Move && d_selected_curve) {
378  if ( ((PlotCurve *)d_selected_curve)->type() == Graph::Function)
379  {
380  QMessageBox::critical(d_graph, tr("Move point error"),
381  tr("Sorry, but moving points of a function is not possible."));
382  return QwtPlotPicker::end(ok);
383  }
384  Table *t = ((DataCurve *)d_selected_curve)->table();
385  if (!t)
386  return QwtPlotPicker::end(ok);
387  double new_x_val = d_graph->plotWidget()->invTransform(d_selected_curve->xAxis(), d_move_target_pos.x());
388  double new_y_val = d_graph->plotWidget()->invTransform(d_selected_curve->yAxis(), d_move_target_pos.y());
389  int row = ((DataCurve *)d_selected_curve)->tableRow(d_selected_point);
390  int xcol = t->colIndex(((DataCurve *)d_selected_curve)->xColumnName());
391  int ycol = t->colIndex(d_selected_curve->title().text());
392  if (t->columnType(xcol) == Table::Numeric && t->columnType(ycol) == Table::Numeric)
393  {
394  t->column(xcol)->setValueAt(row, new_x_val);
395  t->column(ycol)->setValueAt(row, new_y_val);
396  d_app->updateCurves(t, d_selected_curve->title().text());
398  }
399  else
400  QMessageBox::warning(d_graph, tr("Warning"),
401  tr("This operation cannot be performed on curves plotted from columns having a non-numerical format."));
402  }
403  return QwtPlotPicker::end(ok);
404 }
405 
406 void DataPickerTool::moveBy(int dx, int dy)
407 {
408  if ( !d_selected_curve )
409  return;
410  move(d_move_target_pos + QPoint(dx, dy));
411  end(true);
412 }
413 
414 QwtText DataPickerTool::trackerText(const QwtDoublePoint &point) const {
415  return plot()->axisScaleDraw(xAxis())->label(point.x()).text() +
416  ", " +
417  plot()->axisScaleDraw(yAxis())->label(point.y()).text();
418 }
419 
PlotToolInterface
Definition: PlotToolInterface.h:60
Table::Numeric
@ Numeric
Definition: Table.h:57
Plot.h
Table::column
Column * column(int index) const
Return column number 'index'.
Definition: Table.h:121
Table::text
QString text(int row, int col)
Definition: Table.cpp:931
FunctionCurve.h
Plot::closestCurve
int closestCurve(int xpos, int ypos, int &dist, int &point)
Definition: Plot.cpp:427
DataPickerTool::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *event)
Definition: DataPickerTool.cpp:156
Graph::Function
@ Function
Definition: Graph.h:131
Column.h
Plot::curve
QwtPlotCurve * curve(int index)
Definition: Plot.cpp:418
ApplicationWindow::updateCurves
void updateCurves(Table *t, const QString &name)
Definition: ApplicationWindow.cpp:3011
DataPickerTool::d_move_target_pos
QPoint d_move_target_pos
Definition: DataPickerTool.h:79
DataPickerTool::d_move_mode
MoveMode d_move_mode
Definition: DataPickerTool.h:78
toString
S toString(const QString &x)
Deal with conversion between QString and std::string/std::wstring in a generic way.
DataPickerTool::setSelection
void setSelection(QwtPlotCurve *curve, int point_index)
Definition: DataPickerTool.cpp:107
Table
MDI window providing a spreadsheet table with column logic.
Definition: Table.h:51
DataPickerTool::removePoint
void removePoint()
Definition: DataPickerTool.cpp:312
DataPickerTool::keyEventFilter
bool keyEventFilter(QKeyEvent *ke)
Definition: DataPickerTool.cpp:188
QwtErrorPlotCurve.h
DataPickerTool::d_app
ApplicationWindow * d_app
Definition: DataPickerTool.h:73
Graph::replot
void replot()
Definition: Graph.h:249
Graph::plotWidget
Plot * plotWidget() const
Accessor method for d_plot.
Definition: Graph.h:155
DataPickerTool::d_mode
Mode d_mode
Definition: DataPickerTool.h:75
python-sipcmd.dist
dist
Definition: python-sipcmd.py:52
DataPickerTool::Remove
@ Remove
Definition: DataPickerTool.h:47
DataPickerTool::move
virtual void move(const QPoint &point)
Definition: DataPickerTool.cpp:343
Graph::curves
int curves() const
Definition: Graph.h:193
DataPickerTool::d_selected_curve
QwtPlotCurve * d_selected_curve
Definition: DataPickerTool.h:76
PlotCurve.h
PlotCurve
Abstract 2D plot curve class.
Definition: PlotCurve.h:37
ApplicationWindow
SciDAVis's main window.
Definition: ApplicationWindow.h:122
DataPickerTool::Display
@ Display
Definition: DataPickerTool.h:47
DataPickerTool::statusText
void statusText(const QString &)
PlotToolInterface::d_graph
Graph * d_graph
Definition: PlotToolInterface.h:66
Graph.h
ApplicationWindow::modifiedProject
void modifiedProject()
Set the project status to modifed.
Definition: ApplicationWindow.cpp:7590
DataPickerTool::selected
void selected(QwtPlotCurve *, int)
Emitted whenever a new data point has been selected.
DataPickerTool::Vertical
@ Vertical
Definition: DataPickerTool.h:48
DataPickerTool::d_selection_marker
QwtPlotMarker d_selection_marker
Definition: DataPickerTool.h:74
DataPickerTool::Move
@ Move
Definition: DataPickerTool.h:47
DataPickerTool::moveBy
void moveBy(int dx, int dy)
Definition: DataPickerTool.cpp:406
DataPickerTool::end
virtual bool end(bool ok)
Definition: DataPickerTool.cpp:375
DataPickerTool::trackerText
virtual QwtText trackerText(const QwtDoublePoint &point) const
Definition: DataPickerTool.cpp:414
DataPickerTool::d_selected_point
int d_selected_point
Definition: DataPickerTool.h:77
DataCurve
Definition: PlotCurve.h:52
DataPickerTool::~DataPickerTool
virtual ~DataPickerTool()
Definition: DataPickerTool.cpp:86
Graph
A 2D-plotting widget.
Definition: Graph.h:119
Table::colIndex
int colIndex(const QString &name)
Definition: Table.cpp:1017
Table::columnType
int columnType(int col)
Definition: Table.cpp:1305
DataPickerTool::Free
@ Free
Definition: DataPickerTool.h:48
DataPickerTool::DataPickerTool
DataPickerTool(Graph *graph, ApplicationWindow *app, Mode mode, const QObject *status_target=NULL, const char *status_slot="")
Definition: DataPickerTool.cpp:49
ApplicationWindow.h
ApplicationWindow::d_decimal_digits
int d_decimal_digits
default precision to be used for all other operations than fitting
Definition: ApplicationWindow.h:956
Graph::curve
QwtPlotCurve * curve(int index) const
get curve by index
Definition: Graph.cpp:2821
DataPickerTool::append
virtual void append(const QPoint &point)
Definition: DataPickerTool.cpp:92
Graph::curveIndex
int curveIndex(long key) const
Definition: Graph.h:199
DataPickerTool::Mode
Mode
Definition: DataPickerTool.h:47
DataPickerTool.h
Column::setValueAt
void setValueAt(int row, double new_value)
Set the content of row 'row'.
Definition: Column.cpp:229
DataPickerTool::Horizontal
@ Horizontal
Definition: DataPickerTool.h:48
Column::setInvalid
void setInvalid(Interval< int > i, bool invalid=true)
Set an interval invalid or valid.
Definition: Column.cpp:162