1 /***************************************************************************
2     File                 : RangeSelectorTool.cpp
3     Project              : QtiPlot
4     --------------------------------------------------------------------
5     Copyright            : (C) 2006,2007 by Ion Vasilief, Knut Franke
6     Email (use @ for *)  : ion_vasilief*yahoo.fr, knut.franke*gmx.de
7     Description          : Plot tool for selecting ranges on curves.
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *  This program is free software; you can redistribute it and/or modify   *
14  *  it under the terms of the GNU General Public License as published by   *
15  *  the Free Software Foundation; either version 2 of the License, or      *
16  *  (at your option) any later version.                                    *
17  *                                                                         *
18  *  This program is distributed in the hope that it will be useful,        *
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
21  *  GNU General Public License for more details.                           *
22  *                                                                         *
23  *   You should have received a copy of the GNU General Public License     *
24  *   along with this program; if not, write to the Free Software           *
25  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
26  *   Boston, MA  02110-1301  USA                                           *
27  *                                                                         *
28  ***************************************************************************/
29 #include "RangeSelectorTool.h"
30 #include "Graph.h"
31 #include "PlotCurve.h"
32 #include "MultiLayer.h"
33 #include <ErrorBarsCurve.h>
34 #include <ApplicationWindow.h>
35 
36 #include <qwt_symbol.h>
37 #include <QPoint>
38 #include <QApplication>
39 #include <QClipboard>
40 #include <QMessageBox>
41 #include <QEvent>
42 #include <QLocale>
43 #include <QTextStream>
44 #include <QWidget>
45 #include <QCheckBox>
46 #include <QDialogButtonBox>
47 
RangeSelectorTool(Graph * graph,const QObject * status_target,const char * status_slot)48 RangeSelectorTool::RangeSelectorTool(Graph *graph, const QObject *status_target, const char *status_slot)
49 	: QwtPlotPicker(graph->canvas()),
50 	PlotToolInterface(graph)
51 {
52 	d_selection_dialog = NULL;
53 	d_selected_curve = NULL;
54 	for (int i = 0; i < d_graph->curveCount(); i++) {
55 		d_selected_curve = d_graph->curve(i);
56 		if (d_selected_curve && d_selected_curve->rtti() == QwtPlotItem::Rtti_PlotCurve
57 				&& d_selected_curve->dataSize() > 0)
58 			break;
59 		d_selected_curve = NULL;
60 	}
61 	if (!d_selected_curve) {
62 		QMessageBox::critical(d_graph, tr("QtiPlot - Warning"),
63 				tr("All the curves on this plot are empty!"));
64 		return;
65 	}
66 
67     d_enabled = true;
68 	d_visible = true;
69 	d_active_point = 0;
70 	d_inactive_point = d_selected_curve->dataSize() - 1;
71 	int marker_size = 20;
72 
73 	d_active_marker.setSymbol(QwtSymbol(QwtSymbol::Cross, QBrush(QColor(255,255,255,0)),//QBrush(QColor(255,255,0,128)),
74 				QPen(Qt::red,2), QSize(marker_size,marker_size)));
75 	d_active_marker.setLineStyle(QwtPlotMarker::VLine);
76 	d_active_marker.setLinePen(QPen(Qt::red, 1, Qt::DashLine));
77 	d_inactive_marker.setSymbol(QwtSymbol(QwtSymbol::Cross, QBrush(QColor(255,255,255,0)), //QBrush(QColor(255,255,0,128)),
78 				QPen(Qt::black,2), QSize(marker_size,marker_size)));
79 	d_inactive_marker.setLineStyle(QwtPlotMarker::VLine);
80 	d_inactive_marker.setLinePen(QPen(Qt::black, 1, Qt::DashLine));
81 	d_active_marker.setValue(d_selected_curve->x(d_active_point),
82 			d_selected_curve->y(d_active_point));
83 	d_inactive_marker.setValue(d_selected_curve->x(d_inactive_point),
84 			d_selected_curve->y(d_inactive_point));
85 	d_active_marker.attach(d_graph);
86 	d_inactive_marker.attach(d_graph);
87 
88 	setTrackerMode(QwtPicker::AlwaysOn);
89 	setSelectionFlags(QwtPicker::PointSelection | QwtPicker::ClickSelection);
90 	d_graph->canvas()->setCursor(QCursor(QPixmap(":/vizor.png"), -1, -1));
91 	d_graph->canvas()->setFocus();
92 	d_graph->replot();
93 
94 	if (status_target)
95 		connect(this, SIGNAL(statusText(const QString&)), status_target, status_slot);
96 	emit statusText(tr("Click or use Ctrl+arrow key to select range (arrows select active cursor)!"));
97 }
98 
~RangeSelectorTool()99 RangeSelectorTool::~RangeSelectorTool()
100 {
101 	if (d_selection_dialog)
102 		delete d_selection_dialog;
103 
104 	d_active_marker.detach();
105 	d_inactive_marker.detach();
106 	d_graph->canvas()->unsetCursor();
107 	d_graph->replot();
108 }
109 
pointSelected(const QPoint & pos)110 void RangeSelectorTool::pointSelected(const QPoint &pos)
111 {
112 	int dist, point;
113 	QwtPlotItem *item = d_graph->closestCurve(pos.x(), pos.y(), dist, point);
114 	if (!item || item->rtti() == QwtPlotItem::Rtti_PlotSpectrogram || dist >= 5) // 5 pixels tolerance
115 		return;
116 
117 	QwtPlotCurve *curve = (QwtPlotCurve *)item;
118 	if (curve == d_selected_curve)
119 		setActivePoint(point);
120 	else {
121         d_selected_curve = curve;
122 
123         d_active_point = point;
124 		d_active_marker.setValue(d_selected_curve->x(d_active_point), d_selected_curve->y(d_active_point));
125 
126         d_active_point > 0 ? d_inactive_point = 0 : d_inactive_point = d_selected_curve->dataSize() - 1;
127 		d_inactive_marker.setValue(curve->x(d_inactive_point), curve->y(d_inactive_point));
128 		emitStatusText();
129 		emit changed();
130 	}
131 	d_graph->replot();
132 }
133 
setSelectedCurve(QwtPlotCurve * curve)134 void RangeSelectorTool::setSelectedCurve(QwtPlotCurve *curve)
135 {
136 	if (!curve || d_selected_curve == curve || !d_enabled)
137 		return;
138 	d_selected_curve = curve;
139 	d_active_point = 0;
140 	d_inactive_point = d_selected_curve->dataSize() - 1;
141 	d_active_marker.setValue(d_selected_curve->x(d_active_point), d_selected_curve->y(d_active_point));
142 	d_inactive_marker.setValue(d_selected_curve->x(d_inactive_point), d_selected_curve->y(d_inactive_point));
143 	emitStatusText();
144 	emit changed();
145 }
146 
setActivePoint(int point)147 void RangeSelectorTool::setActivePoint(int point)
148 {
149 	if (!d_enabled || point == d_active_point)
150 		return;
151 	d_active_point = point;
152 	d_active_marker.setValue(d_selected_curve->x(d_active_point), d_selected_curve->y(d_active_point));
153 	emitStatusText();
154 	emit changed();
155 }
156 
emitStatusText()157 void RangeSelectorTool::emitStatusText()
158 {
159     QLocale locale = d_graph->multiLayer()->locale();
160 	if (((PlotCurve *)d_selected_curve)->type() == Graph::Function ||
161 		((PlotCurve *)d_selected_curve)->type() == Graph::Histogram){
162 		 double x = d_selected_curve->x(d_active_point);
163 		 double y = d_selected_curve->y(d_active_point);
164          emit statusText(QString("%1 <=> %2[%3]: x=%4; y=%5; dx=%6; dy=%7")
165 			.arg(d_active_marker.xValue() > d_inactive_marker.xValue() ? tr("Right") : tr("Left"))
166 			.arg(d_selected_curve->title().text())
167 			.arg(d_active_point + 1)
168 			.arg(locale.toString(x, 'G', 16))
169 			.arg(locale.toString(y, 'G', 16))
170 			.arg(locale.toString(fabs(x - d_selected_curve->x(d_inactive_point)), 'G', 16))
171 			.arg(locale.toString(fabs(y - d_selected_curve->y(d_inactive_point)), 'G', 16)));
172     } else if (((PlotCurve *)d_selected_curve)->type() == Graph::ErrorBars){
173          emit statusText(QString("%1 <=> %2[%3]: x=%4; y=%5; err=%6")
174 			.arg(d_active_marker.xValue() > d_inactive_marker.xValue() ? tr("Right") : tr("Left"))
175 			.arg(d_selected_curve->title().text())
176 			.arg(d_active_point + 1)
177 			.arg(locale.toString(d_selected_curve->x(d_active_point), 'G', 16))
178 			.arg(locale.toString(d_selected_curve->y(d_active_point), 'G', 16))
179 			.arg(locale.toString(((ErrorBarsCurve*)d_selected_curve)->errorValue(d_active_point), 'G', 16)));
180     } else {
181 		DataCurve *c = (DataCurve*)d_selected_curve;
182 		Table *t = c->table();
183 		Table *xt = c->xTable();
184 		if (!t || !xt)
185 			return;
186 
187 		int row = c->tableRow(d_active_point);
188 		double x = c->x(d_active_point);
189 		double y = c->y(d_active_point);
190 
191 		ApplicationWindow *app = d_graph->multiLayer()->applicationWindow();
192 		int prec = 15;
193 		if (app)
194 			prec = app->d_decimal_digits;
195 
196 		int xcol = xt->colIndex(c->xColumnName());
197 		QString xs = locale.toString(x - c->xOffset(), 'G', prec);
198 		if (xt->columnType(xcol) != Table::Numeric)
199 			xs = xt->text(row, xcol);
200 
201 		int ycol = t->colIndex(c->title().text());
202 		QString ys = locale.toString(y - c->yOffset(), 'G', prec);
203 		if (t->columnType(ycol) != Table::Numeric)
204 			ys = t->text(row, ycol);
205 
206 		emit statusText(QString("%1 <=> %2[%3]: x=%4; y=%5; dx=%6; dy=%7")
207 			.arg(d_active_marker.xValue() > d_inactive_marker.xValue() ? tr("Right") : tr("Left"))
208 			.arg(c->title().text())
209 			.arg(row + 1)
210 			.arg(xs)
211 			.arg(ys)
212 			.arg(locale.toString(fabs(x - c->x(d_inactive_point)), 'G', prec))
213 			.arg(locale.toString(fabs(y - c->y(d_inactive_point)), 'G', prec)));
214     }
215 }
216 
switchActiveMarker()217 void RangeSelectorTool::switchActiveMarker()
218 {
219 	QwtDoublePoint tmp = d_active_marker.value();
220 	d_active_marker.setValue(d_inactive_marker.value());
221 	d_inactive_marker.setValue(tmp);
222 	int tmp2 = d_active_point;
223 	d_active_point = d_inactive_point;
224 	d_inactive_point = tmp2;
225 	d_graph->replot();
226 
227 	emitStatusText();
228 }
229 
eventFilter(QObject * obj,QEvent * event)230 bool RangeSelectorTool::eventFilter(QObject *obj, QEvent *event)
231 {
232 	switch(event->type()) {
233 		case QEvent::KeyPress:
234 			if (keyEventFilter((QKeyEvent*)event))
235 				return true;
236 			break;
237 		default:
238 			break;
239 	}
240 	return QwtPlotPicker::eventFilter(obj, event);
241 }
242 
keyEventFilter(QKeyEvent * ke)243 bool RangeSelectorTool::keyEventFilter(QKeyEvent *ke)
244 {
245 	switch(ke->key()) {
246 		case Qt::Key_Up:
247 			{
248 				int n_curves = d_graph->curveCount();
249 				int start = d_graph->curveIndex(d_selected_curve) + 1;
250 				for (int i = start; i < start + n_curves; ++i)
251 					if (d_graph->curve(i % n_curves)->dataSize() > 0) {
252 						setSelectedCurve(d_graph->curve(i % n_curves));
253 						break;
254 					}
255 				d_graph->replot();
256 				return true;
257 			}
258 		case Qt::Key_Down:
259 			{
260 				int n_curves = d_graph->curveCount();
261 				int start = d_graph->curveIndex(d_selected_curve) + n_curves - 1;
262 				for (int i = start; i > start - n_curves; --i)
263 					if (d_graph->curve(i % n_curves)->dataSize() > 0) {
264 						setSelectedCurve(d_graph->curve(i % n_curves));
265 						break;
266 					}
267 				d_graph->replot();
268 				return true;
269 			}
270 		case Qt::Key_Right:
271 		case Qt::Key_Plus:
272 			{
273 				if (ke->modifiers() & Qt::ControlModifier) {
274 					int n_points = d_selected_curve->dataSize();
275 					setActivePoint((d_active_point + 1) % n_points);
276 					d_graph->replot();
277 				} else
278 					switchActiveMarker();
279 				return true;
280 			}
281 		case Qt::Key_Left:
282 		case Qt::Key_Minus:
283 			{
284 				if (ke->modifiers() & Qt::ControlModifier) {
285 					int n_points = d_selected_curve->dataSize();
286 					setActivePoint((d_active_point - 1 + n_points) % n_points);
287 					d_graph->replot();
288 				} else
289 					switchActiveMarker();
290 				return true;
291 			}
292 		default:
293 			break;
294 	}
295 	return false;
296 }
297 
cutSelection()298 void RangeSelectorTool::cutSelection()
299 {
300 	if (!d_selected_curve)
301         return;
302 
303 	if (mightNeedMultipleSelection())
304 		showSelectionDialog(Cut);
305 	else {
306 		copySelectedCurve();
307 		clearSelectedCurve();
308 	}
309 }
310 
copySelection()311 void RangeSelectorTool::copySelection()
312 {
313     if (!d_selected_curve)
314         return;
315 
316 	if (mightNeedMultipleSelection())
317 		showSelectionDialog();
318 	else
319 		copySelectedCurve();
320 }
321 
clearSelection()322 void RangeSelectorTool::clearSelection()
323 {
324     if (!d_selected_curve)
325         return;
326 
327 	if (mightNeedMultipleSelection())
328 		showSelectionDialog(Delete);
329 	else
330 		clearSelectedCurve();
331 }
332 
copySelectedCurve()333 void RangeSelectorTool::copySelectedCurve()
334 {
335     if (!d_selected_curve)
336         return;
337 
338 	int start_point = QMIN(d_active_point, d_inactive_point);
339 	int end_point = QMAX(d_active_point, d_inactive_point);
340 	QLocale locale = d_graph->multiLayer()->locale();
341 	ApplicationWindow *app = d_graph->multiLayer()->applicationWindow();
342 	int prec = 15;
343 	if (app)
344 		prec = app->d_decimal_digits;
345 
346 	QString text;
347 	for (int i = start_point; i <= end_point; i++){
348 		text += locale.toString(d_selected_curve->x(i), 'G', prec) + "\t";
349 		text += locale.toString(d_selected_curve->y(i), 'G', prec) + "\n";
350 	}
351 	QApplication::clipboard()->setText(text);
352 }
353 
mightNeedMultipleSelection()354 bool RangeSelectorTool::mightNeedMultipleSelection()
355 {
356 	int count = 0;
357 	if (((PlotCurve*)d_selected_curve)->type() != Graph::Function){
358 		QString xCol = ((DataCurve*)d_selected_curve)->xColumnName();
359 		for (int i = 0; i < d_graph->curveCount(); i++){
360 			PlotCurve *curve = (PlotCurve*)d_graph->curve(i);
361 			if (curve->type() != Graph::Function &&
362 				((DataCurve *)curve)->xColumnName() == xCol)
363 				count++;
364 		}
365 	}
366 	return count > 1 ? true : false;
367 }
368 
cutMultipleSelection()369 void RangeSelectorTool::cutMultipleSelection()
370 {
371 	copyMultipleSelection();
372 	clearMultipleSelection();
373 }
374 
copyMultipleSelection()375 void RangeSelectorTool::copyMultipleSelection()
376 {
377 	if (d_selection_dialog)
378 		d_selection_dialog->hide();
379 
380 	int start_point = QMIN(d_active_point, d_inactive_point);
381 	int end_point = QMAX(d_active_point, d_inactive_point);
382 	QLocale locale = d_graph->multiLayer()->locale();
383 	QString text;
384 	QList <PlotCurve*> cvs;
385 	for (int j = 0; j < d_selection_lst.count(); j++){
386 		QCheckBox *box = d_selection_lst[j];
387 		if (box->isChecked())
388 			cvs << (PlotCurve*)d_graph->curve(box->text());
389 	}
390 
391 	int curves = cvs.size();
392 	for (int i = start_point; i <= end_point; i++){
393 		text += locale.toString(d_selected_curve->x(i), 'G', 16);
394 		for (int j = 0; j < curves; j++){
395 			PlotCurve *curve = cvs[j];
396 			if (curve->type() == Graph::ErrorBars)
397 				text += "\t" + locale.toString(((ErrorBarsCurve*)curve)->errorValue(i), 'G', 16);
398 			else
399 				text += "\t" + locale.toString(curve->y(i), 'G', 16);
400 		}
401 		text += "\n";
402 	}
403 
404 	QApplication::clipboard()->setText(text);
405 }
406 
clearMultipleSelection()407 void RangeSelectorTool::clearMultipleSelection()
408 {
409 	if (d_selection_dialog)
410 		d_selection_dialog->hide();
411 
412 	int start_point = QMIN(d_active_point, d_inactive_point);
413 	int start_row = ((DataCurve*)d_selected_curve)->tableRow(start_point);
414 	int end_point = QMAX(d_active_point, d_inactive_point);
415 	int end_row = ((DataCurve*)d_selected_curve)->tableRow(end_point);
416 
417 	for (int j = 0; j < d_selection_lst.count(); j++){
418 		QCheckBox *box = d_selection_lst[j];
419 		if (box->isChecked()){
420 			PlotCurve *curve = (PlotCurve*)d_graph->curve(box->text());
421 			if (!curve || curve->type() == Graph::Function)
422 				continue;
423 
424 			Table *t = ((DataCurve*)curve)->table();
425 			if (!t)
426 				continue;
427 			QString name = curve->title().text();
428 			int col = t->colIndex(name);
429 			if (t->isReadOnlyColumn(col)){
430 				QMessageBox::warning(d_graph, tr("QtiPlot - Warning"),
431 				tr("The column '%1' is read-only! Operation aborted!").arg(name));
432 				continue;
433 			}
434 
435 			for (int i = start_row; i <= end_row; i++)
436 				t->setText(i, col, "");
437 			t->notifyChanges();
438 		}
439 	}
440 
441 	bool ok_update = (end_point - start_point + 1) < d_selected_curve->dataSize() ? true : false;
442 	if (ok_update){
443 		d_active_point = 0;
444 		d_inactive_point = d_selected_curve->dataSize() - 1;
445 		d_active_marker.setValue(d_selected_curve->x(d_active_point), d_selected_curve->y(d_active_point));
446 		d_inactive_marker.setValue(d_selected_curve->x(d_inactive_point), d_selected_curve->y(d_inactive_point));
447 		emitStatusText();
448 		emit changed();
449 		d_graph->replot();
450 	}
451 }
452 
showSelectionDialog(RangeEditOperation op)453 void RangeSelectorTool::showSelectionDialog(RangeEditOperation op)
454 {
455 	d_selection_lst.clear();
456 
457 	if (d_selection_dialog)
458 		delete d_selection_dialog;
459 
460 	d_selection_dialog = new QDialog(0, Qt::Tool);
461 	d_selection_dialog->setAttribute(Qt::WA_DeleteOnClose);
462 	if (op > Copy)
463 		d_selection_dialog->setWindowTitle(tr("Remove data from curves?"));
464 	else
465 		d_selection_dialog->setWindowTitle(tr("Copy data to clipboard?"));
466 
467 	d_selection_dialog->setModal(true);
468 	d_selection_dialog->setActiveWindow();
469 
470 	QVBoxLayout *vb = new QVBoxLayout(d_selection_dialog);
471 
472 	QString xCol = ((DataCurve*)d_selected_curve)->xColumnName();
473 	for (int i = 0; i < d_graph->curveCount(); i++){
474 		PlotCurve *curve = (PlotCurve*)d_graph->curve(i);
475 		if (curve->type() != Graph::Function &&
476 			((DataCurve *)curve)->xColumnName() == xCol){
477 			QCheckBox *box = new QCheckBox(curve->title().text());
478 			box->setChecked(true);
479 			vb->addWidget(box);
480 			d_selection_lst << box;
481 
482 			QList<ErrorBarsCurve *> errorBars = ((DataCurve *)curve)->errorBarsList();
483 			foreach(ErrorBarsCurve *err, errorBars){
484 				box = new QCheckBox(err->title().text());
485 				box->setChecked(true);
486 				vb->addWidget(box);
487 				d_selection_lst << box;
488 			}
489 		}
490 	}
491 	vb->addStretch();
492 
493 	QDialogButtonBox *btnBox = new QDialogButtonBox ();
494 
495 	QPushButton *closeBtn = btnBox->addButton(QDialogButtonBox::Ok);
496 	switch (op){
497 		case Copy:
498 			connect(closeBtn, SIGNAL(clicked()), this, SLOT(copyMultipleSelection()));
499 		break;
500 
501 		case Cut:
502 			connect(closeBtn, SIGNAL(clicked()), this, SLOT(cutMultipleSelection()));
503 		break;
504 
505 		case Delete:
506 			connect(closeBtn, SIGNAL(clicked()), this, SLOT(clearMultipleSelection()));
507 		break;
508 	}
509 
510 	QPushButton *cancelBtn = btnBox->addButton(QDialogButtonBox::Cancel);
511 	connect(cancelBtn, SIGNAL(clicked()), d_selection_dialog, SLOT(close()));
512 	vb->addWidget(btnBox);
513 
514 	d_selection_dialog->show();
515 }
516 
clearSelectedCurve()517 void RangeSelectorTool::clearSelectedCurve()
518 {
519 	if (!d_selected_curve)
520 		return;
521 
522 	if (((PlotCurve *)d_selected_curve)->type() != Graph::Function){
523         Table *t = ((DataCurve*)d_selected_curve)->table();
524         if (!t)
525             return;
526 
527 		if (t->isReadOnlyColumn(t->colIndex(((DataCurve *)d_selected_curve)->xColumnName()))){
528     		QMessageBox::warning(d_graph, tr("QtiPlot - Warning"),
529         	tr("The column '%1' is read-only! Operation aborted!").arg(((DataCurve *)d_selected_curve)->xColumnName()));
530 			return;
531 		} else if (t->isReadOnlyColumn(t->colIndex(d_selected_curve->title().text()))){
532     		QMessageBox::warning(d_graph, tr("QtiPlot - Warning"),
533 			tr("The column '%1' is read-only! Operation aborted!").arg(d_selected_curve->title().text()));
534 			return;
535    		}
536 
537         int start_point = QMIN(d_active_point, d_inactive_point);
538         int start_row = ((DataCurve*)d_selected_curve)->tableRow(start_point);
539         int end_point = QMAX(d_active_point, d_inactive_point);
540         int end_row = ((DataCurve*)d_selected_curve)->tableRow(end_point);
541         int col = t->colIndex(d_selected_curve->title().text());
542         bool ok_update = (end_point - start_point + 1) < d_selected_curve->dataSize() ? true : false;
543         for (int i = start_row; i <= end_row; i++){
544             t->setText(i, col, "");
545         }
546         t->notifyChanges();
547 
548         if (ok_update){
549             d_active_point = 0;
550             d_inactive_point = d_selected_curve->dataSize() - 1;
551             d_active_marker.setValue(d_selected_curve->x(d_active_point), d_selected_curve->y(d_active_point));
552             d_inactive_marker.setValue(d_selected_curve->x(d_inactive_point), d_selected_curve->y(d_inactive_point));
553             emitStatusText();
554             emit changed();
555             d_graph->replot();
556         }
557     }
558 }
559 
560 // Paste text from the clipboard
pasteSelection()561 void RangeSelectorTool::pasteSelection()
562 {
563 	QString text = QApplication::clipboard()->text();
564 	if (text.isEmpty())
565 		return;
566 
567     if (((PlotCurve *)d_selected_curve)->type() == Graph::Function ||
568 		((PlotCurve *)d_selected_curve)->type() == Graph::Graph::ErrorBars)
569         return;
570 
571     Table *t = ((DataCurve*)d_selected_curve)->table();
572     if (!t)
573         return;
574 
575 	if (t->isReadOnlyColumn(t->colIndex(((DataCurve *)d_selected_curve)->xColumnName()))){
576     	QMessageBox::warning(d_graph, tr("QtiPlot - Warning"),
577         tr("The column '%1' is read-only! Operation aborted!").arg(((DataCurve *)d_selected_curve)->xColumnName()));
578 		return;
579 	} else if (t->isReadOnlyColumn(t->colIndex(d_selected_curve->title().text()))){
580     	QMessageBox::warning(d_graph, tr("QtiPlot - Warning"),
581 		tr("The column '%1' is read-only! Operation aborted!").arg(d_selected_curve->title().text()));
582 		return;
583    	}
584 
585 	QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
586 
587 	QTextStream ts( &text, QIODevice::ReadOnly );
588     int start_point = QMIN(d_active_point, d_inactive_point);
589     int start_row = ((DataCurve*)d_selected_curve)->tableRow(start_point);
590     int end_point = QMAX(d_active_point, d_inactive_point);
591     int end_row = ((DataCurve*)d_selected_curve)->tableRow(end_point);
592     int col = t->colIndex(d_selected_curve->title().text());
593 
594     int prec; char f;
595     t->columnNumericFormat(col, &f, &prec);
596     QLocale locale = d_graph->multiLayer()->locale();
597     for (int i = start_row; i <= end_row; i++){
598         QString s = ts.readLine();
599         if (s.isEmpty())
600             continue;
601 
602         QStringList cellTexts = s.split("\t");
603         if (cellTexts.count() >= 2){
604             bool numeric;
605             double value = locale.toDouble(cellTexts[1], &numeric);
606 			if (numeric)
607                 t->setText(i, col, locale.toString(value, f, prec));
608 			else
609                 t->setText(i, col, cellTexts[1]);
610         }
611 
612         if(ts.atEnd())
613             break;
614     }
615 
616     t->notifyChanges();
617 
618     d_active_marker.setValue(d_selected_curve->x(d_active_point), d_selected_curve->y(d_active_point));
619     d_inactive_marker.setValue(d_selected_curve->x(d_inactive_point), d_selected_curve->y(d_inactive_point));
620     emitStatusText();
621     emit changed();
622     d_graph->replot();
623 
624 	QApplication::restoreOverrideCursor();
625 }
626 
setCurveRange()627 void RangeSelectorTool::setCurveRange()
628 {
629     if (!d_selected_curve)
630         return;
631 
632     if (((PlotCurve *)d_selected_curve)->type() != Graph::Function){
633         ((DataCurve*)d_selected_curve)->setRowRange(QMIN(d_active_point, d_inactive_point),
634                                     QMAX(d_active_point, d_inactive_point));
635         d_graph->updatePlot();
636         d_graph->notifyChanges();
637     }
638 }
639 
setEnabled(bool on)640 void RangeSelectorTool::setEnabled(bool on)
641 {
642     d_enabled = on;
643     if (on)
644 		d_graph->canvas()->setCursor(QCursor(QPixmap(":/vizor.png"), -1, -1));
645 }
646 
setVisible(bool on)647 void RangeSelectorTool::setVisible(bool on)
648 {
649 	if (d_visible == on)
650 		return;
651 
652 	d_visible = on;
653 
654     if (on){
655 		setTrackerMode(QwtPicker::AlwaysOn);
656 		d_graph->canvas()->setCursor(QCursor(QPixmap(":/vizor.png"), -1, -1));
657 		d_active_marker.attach(d_graph);
658 		d_inactive_marker.attach(d_graph);
659 	} else {
660 		d_enabled = false;
661 		setTrackerMode(QwtPicker::AlwaysOff);
662         d_active_marker.detach();
663 		d_inactive_marker.detach();
664 		d_graph->canvas()->unsetCursor();
665 	}
666 	d_graph->replot();
667 }
668