00001
00022 #include <qwt_plot_canvas.h>
00023 #include <qwt_legend.h>
00024 #include <qwt_scale_div.h>
00025 #include <QApplication>
00026 #include <QFileDialog>
00027 #include <QInputDialog>
00028 #include <QMenu>
00029 #include <QContextMenuEvent>
00030 #include <QtSvg/QSvgGenerator>
00031 #include <QPainter>
00032 #include <QPrinter>
00033
00034 #include "DGVPlot.h"
00035 #include "DGVFile.h"
00036
00037 DGVPlot::DGVPlot(QWidget *parent) : QwtPlot(parent)
00038 {
00039 loaded = false;
00040 linePlot = true;
00041
00042
00043 const QColor bgColor(Qt::white);
00044 QPalette p = palette();
00045 p.setColor(backgroundRole(), bgColor);
00046 setPalette(p);
00047
00048 antialiased = false;
00049 plotSize = 0;
00050 }
00051
00052 DGVPlot::~DGVPlot()
00053 {
00054
00055 }
00056
00057 void DGVPlot::setName(QString filename)
00058 {
00059 name = filename;
00060 setWindowTitle(strippedNamePrefix());
00061 }
00062
00063 inline void DGVPlot::setToLinePlot(bool lines)
00064 {
00065 linePlot = lines;
00066 }
00067
00068 void DGVPlot::setData(Array<imageType,1> &xData, Array<imageType,1> &yData)
00069 {
00070 xArray.resize(1);
00071 yArray.resize(1);
00072
00073 plotSize = xData.size();
00074 xArray(0).resize(xData.shape());
00075 yArray(0).resize(yData.shape());
00076 xArray(0) = xData;
00077 yArray(0) = yData;
00078 loaded = true;
00079 }
00080
00081 void DGVPlot::setData(Array< Array<imageType,1>, 1 > &xData, Array< Array<imageType,1>, 1 > &yData)
00082 {
00083 xArray.resize(xData.shape());
00084 yArray.resize(yData.shape());
00085
00086 for(int j = 0; j < xArray.size(); j ++)
00087 {
00088 plotSize = xArray(j).size();
00089 xArray(j).resize(xData(j).shape());
00090 yArray(j).resize(yData(j).shape());
00091 xArray(j) = xData(j);
00092 yArray(j) = yData(j);
00093 }
00094 loaded = true;
00095 }
00096
00097 void DGVPlot::createCurvePlots(Array< Array<imageType,1>, 1 > &xData, Array< Array<imageType,1>, 1 > &yData, QString plotTitle)
00098 {
00099 QString curveName;
00100 Qt::GlobalColor colourCount;
00101 QwtPlotCurve *tmpCurve = NULL;
00102
00103 curves.resize(xData.size());
00104
00105 QwtPlot::setTitle(plotTitle);
00106 QwtPlot::insertLegend(new QwtLegend(), QwtPlot::RightLegend);
00107 for(int j = 0; j < xData.size(); j ++)
00108 {
00109 curveName = "Sel " + curveName.setNum(j);
00110
00111 tmpCurve = curves(j) = new QwtPlotCurve(curveName);
00112 if(antialiased)
00113 tmpCurve->setRenderHint(QwtPlotItem::RenderAntialiased);
00114 if(linePlot)
00115 tmpCurve->setStyle(QwtPlotCurve::Lines);
00116 else
00117 tmpCurve->setStyle(QwtPlotCurve::Dots);
00118 colourCount = static_cast<Qt::GlobalColor>((7+j)%20);
00119 tmpCurve->setPen(QColor(colourCount));
00120 tmpCurve->setData(&(xData(j)(0)), &(yData(j)(0)), xData(j).size());
00121 tmpCurve->attach(this);
00122 }
00123 QwtPlot::setAutoReplot(true);
00124 QwtPlot::replot();
00125 }
00126
00127 void DGVPlot::createCurvePlot(Array<imageType,1> xData, Array<imageType,1> yData, QString plotTitle)
00128 {
00129 Qt::GlobalColor colourCount;
00130 QwtPlotCurve *tmpCurve = NULL;
00131
00132 curves.resize(1);
00133
00134 QwtPlot::setTitle(plotTitle);
00135 QwtPlot::setWindowTitle(plotTitle);
00136
00137 tmpCurve = curves(0) = new QwtPlotCurve;
00138 if(antialiased)
00139 tmpCurve->setRenderHint(QwtPlotItem::RenderAntialiased);
00140 colourCount = static_cast<Qt::GlobalColor>(7);
00141 if(linePlot)
00142 tmpCurve->setStyle(QwtPlotCurve::Lines);
00143 else
00144 tmpCurve->setStyle(QwtPlotCurve::Dots);
00145 tmpCurve->setPen(QColor(colourCount));
00146 tmpCurve->setData(&(xData(0)), &(yData(0)), xData.size());
00147 tmpCurve->attach(this);
00148
00149 QwtPlot::setAutoReplot(true);
00150 QwtPlot::replot();
00151 }
00152
00153 void DGVPlot::generatePlot()
00154 {
00155 if(loaded)
00156 {
00157 createCurvePlots(xArray, yArray, name);
00158 }
00159 }
00160
00161 bool DGVPlot::loadGNU(QString filename)
00162 {
00163 DGVFile inFile;
00164 Array<imageType,1> tuple;
00165 bool ok;
00166
00167 QString sep = QInputDialog::getText(this, tr("Values Separator"), tr("Separator (a space normally): "), QLineEdit::Normal,
00168 " ", &ok);
00169
00170 if(ok)
00171 {
00172 setName(filename);
00173 inFile.setSeparator(sep);
00174 inFile.setCommentSymbol("#");
00175 if(!inFile.open(filename,"r"))
00176 return false;
00177
00178 inFile.readNextLineAsDoubles(tuple);
00179 while(tuple.size() == 0)
00180 inFile.readNextLineAsDoubles(tuple);
00181
00182 if(tuple.size() == 2)
00183 {
00184 xArray.resize(1);
00185 yArray.resize(1);
00186 plotSize = 1;
00187
00188 xArray(0).resizeAndPreserve(plotSize);
00189 xArray(0)(plotSize-1) = tuple(0);
00190 yArray(0).resizeAndPreserve(plotSize);
00191 yArray(0)(plotSize-1) = tuple(1);
00192 while(!inFile.atEnd())
00193 {
00194 qApp->processEvents();
00195
00196 inFile.readNextLineAsDoubles(tuple);
00197 while(tuple.size() == 0 && !inFile.atEnd())
00198 inFile.readNextLineAsDoubles(tuple);
00199
00200 plotSize ++;
00201 xArray(0).resizeAndPreserve(plotSize);
00202 xArray(0)(plotSize-1) = tuple(0);
00203 yArray(0).resizeAndPreserve(plotSize);
00204 yArray(0)(plotSize-1) = tuple(1);
00205 }
00206
00207 cerr << "Load GNU Size: " << xArray(0).size() << endl;
00208 createCurvePlots(xArray, yArray, filename);
00209 inFile.close();
00210 loaded = true;
00211 }
00212 else
00213 {
00214 cerr << "Number of Tuples: " << tuple.size() << " is not supported." << endl;
00215 return false;
00216 }
00217 }
00218 else
00219 return false;
00220
00221 return true;
00222 }
00223
00224 bool DGVPlot::saveGNU(QString filename)
00225 {
00226 if(loaded)
00227 {
00228 DGVFile outFile;
00229 Array<imageType,1> tuple(2);
00230 QString tmpNum1, tmpNum2;
00231 bool ok;
00232
00233 QString sep = QInputDialog::getText(this, tr("Values Separator"), tr("Separator (a space normally): "), QLineEdit::Normal,
00234 " ", &ok);
00235
00236 if(ok)
00237 {
00238 outFile.setSeparator(sep);
00239 outFile.setCommentSymbol("#");
00240 if(!outFile.open(filename,"w"))
00241 return false;
00242
00243
00244 for(int j = 0; j < xArray.size(); j ++)
00245 {
00246 cerr << "Save GNU Size: " << xArray(j).size() << endl;
00247 for(int k = 0; k < xArray(j).size(); k ++)
00248 {
00249 tuple(0) = xArray(j)(k);
00250 tuple(1) = yArray(j)(k);
00251 outFile.writeDoubleArrayAsLine(tuple);
00252 }
00253 }
00254
00255 outFile.close();
00256 return true;
00257 }
00258 else
00259 return false;
00260 }
00261 else
00262 return false;
00263 }
00264
00265
00266 void DGVPlot::save()
00267 {
00268 QPixmap image;
00269
00270 QFileDialog *fileSaver = new QFileDialog(this);
00271 QString filename = fileSaver->getSaveFileName(this,
00272 tr("Select File Name to Save"),
00273 ".",
00274 tr("Images (*.png *.ppm *.jpeg *.jpg *.bmp);;GNUPlot 2D Files (*.dat *.gnu *.gnuplot);;Vector Graphics (*.svg *.ps *.pdf)"));
00275
00276 if (!filename.isEmpty())
00277 {
00278 QFileInfo fi(filename);
00279 QString extension = fi.suffix().toLower();
00280
00281 if(extension == "dat" || extension == "gnu" || extension == "gnuplot")
00282 saveGNU(filename);
00283 else if(extension == "svg")
00284 {
00285 QSvgGenerator svg;
00286 svg.setFileName(filename);
00287 svg.setSize(rect().size());
00288
00289 QPainter painter(&svg);
00290 print(&painter, rect());
00291 painter.end();
00292 }
00293 else if(extension == "ps")
00294 {
00295 QPrinter printer(QPrinter::HighResolution);
00296 printer.setOutputFormat(QPrinter::PostScriptFormat);
00297 printer.setOrientation(QPrinter::Landscape);
00298 printer.setOutputFileName(filename);
00299 printer.setCreator("DGV");
00300
00301 print(printer);
00302 }
00303 else if(extension == "pdf")
00304 {
00305 QPrinter printer(QPrinter::HighResolution);
00306 printer.setOutputFormat(QPrinter::PdfFormat);
00307 printer.setOrientation(QPrinter::Landscape);
00308 printer.setOutputFileName(filename);
00309 printer.setCreator("DGV");
00310
00311 print(printer);
00312 }
00313 else
00314 {
00316
00317
00318
00319
00320 image = QPixmap::grabWidget(this);
00321
00322 image.save(filename,0,100);
00323 }
00324 }
00325 }
00326
00327 void DGVPlot::xLabel()
00328 {
00329 bool ok;
00330 QString text = QInputDialog::getText(this, tr("x-axis Label"),
00331 tr("New Label:"), QLineEdit::Normal,
00332 "x", &ok);
00333 if(ok)
00334 setAxisTitle(xBottom,text);
00335 }
00336
00337 void DGVPlot::yLabel()
00338 {
00339 bool ok;
00340 QString text = QInputDialog::getText(this, tr("y-axis Label"),
00341 tr("New Label:"), QLineEdit::Normal,
00342 "y", &ok);
00343 if(ok)
00344 setAxisTitle(yLeft,text);
00345 }
00346
00347 void DGVPlot::titleLabel()
00348 {
00349 bool ok;
00350 QString text = QInputDialog::getText(this, tr("Title Label"),
00351 tr("New Label:"), QLineEdit::Normal,
00352 "z", &ok);
00353 if(ok)
00354 setTitle(text);
00355 }
00356
00357 void DGVPlot::renameData()
00358 {
00359 bool ok;
00360
00361 QString newName = QInputDialog::getText(this, tr("Rename Data"), tr("New Name: "), QLineEdit::Normal, name, &ok);
00362
00363 if(ok)
00364 setName(newName);
00365 }
00366
00367 void DGVPlot::rescaleAxis(const int axis)
00368 {
00369 bool ok;
00370 #if QWT_VERSION < 0x050200
00371
00372 double scaleMin = QInputDialog::getDouble(this, tr("Rescale"),
00373 tr("New Min:"), axisScaleDiv(axis)->lBound(),
00374 -2147483647, 2147483647, 1, &ok);
00375 double scaleMax = QInputDialog::getDouble(this, tr("Rescale"),
00376 tr("New Max:"), axisScaleDiv(axis)->hBound(),
00377 -2147483647, 2147483647, 1, &ok);
00378 #else
00379 double scaleMin = QInputDialog::getDouble(this, tr("Rescale"),
00380 tr("New Min:"), axisScaleDiv(axis)->lowerBound(),
00381 -2147483647, 2147483647, 1, &ok);
00382 double scaleMax = QInputDialog::getDouble(this, tr("Rescale"),
00383 tr("New Max:"), axisScaleDiv(axis)->upperBound(),
00384 -2147483647, 2147483647, 1, &ok);
00385 #endif
00386
00387 if(ok)
00388 setAxisScale(axis, scaleMin, scaleMax);
00389 }
00390
00391 void DGVPlot::rescaleXAxis()
00392 {
00393 rescaleAxis(2);
00394 }
00395
00396 void DGVPlot::rescaleYAxis()
00397 {
00398 rescaleAxis(0);
00399 }
00400
00401 void DGVPlot::toggleLinePlot()
00402 {
00403 if(linePlotAct->isChecked())
00404 linePlot = true;
00405 else
00406 linePlot = false;
00407
00408 if(linePlot)
00409 {
00410 for(int j = 0; j < curves.size(); j ++)
00411 curves(j)->setStyle(QwtPlotCurve::Lines);
00412 }
00413 else
00414 {
00415 for(int j = 0; j < curves.size(); j ++)
00416 curves(j)->setStyle(QwtPlotCurve::Dots);
00417 }
00418 }
00419
00420 QString DGVPlot::strippedName()
00421 {
00422 return QFileInfo(name).fileName();
00423 }
00424
00425 QString DGVPlot::strippedNamePrefix()
00426 {
00427 return "Plot: " + QFileInfo(name).fileName();
00428 }
00429
00430 void DGVPlot::contextMenuEvent(QContextMenuEvent *event)
00431 {
00432 QMenu menu(this);
00433
00435 saveAct = menu.addAction(tr("&Save"));
00436 saveAct->setShortcut(tr("Ctrl+s"));
00437 connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
00438 menu.addSeparator()->setText("Labels");
00440 xLabelAct = menu.addAction(tr("Set &x Label"));
00441 xLabelAct->setShortcut(tr("Ctrl+x"));
00442 connect(xLabelAct, SIGNAL(triggered()), this, SLOT(xLabel()));
00443 yLabelAct = menu.addAction(tr("Set &y Label"));
00444 yLabelAct->setShortcut(tr("Ctrl+y"));
00445 connect(yLabelAct, SIGNAL(triggered()), this, SLOT(yLabel()));
00446 titleAct = menu.addAction(tr("Set &Title"));
00447 titleAct->setShortcut(tr("Ctrl+t"));
00448 connect(titleAct, SIGNAL(triggered()), this, SLOT(titleLabel()));
00449 xScaleAct = menu.addAction(tr("Rescale x-axis"));
00450 xScaleAct->setShortcut(tr("Ctrl+a"));
00451 connect(xScaleAct, SIGNAL(triggered()), this, SLOT(rescaleXAxis()));
00452 yScaleAct = menu.addAction(tr("Rescale y-axis"));
00453 yScaleAct->setShortcut(tr("Ctrl+b"));
00454 connect(yScaleAct, SIGNAL(triggered()), this, SLOT(rescaleYAxis()));
00455 linePlotAct = menu.addAction(tr("Line Plot"));
00456 linePlotAct->setCheckable(true);
00457 linePlotAct->setChecked(linePlot);
00458 linePlotAct->setShortcut(tr("Ctrl+p"));
00459 connect(linePlotAct, SIGNAL(triggered()), this, SLOT(toggleLinePlot()));
00460 menu.addSeparator();
00462 renameAct = menu.addAction(tr("Rename"));
00463 renameAct->setShortcut(tr("Ctrl+r"));
00464 connect(renameAct, SIGNAL(triggered()), this, SLOT(renameData()));
00465 refreshAct = menu.addAction(tr("Refresh"));
00466 refreshAct->setShortcut(tr("F5"));
00467 connect(refreshAct, SIGNAL(triggered()), this, SLOT(replot()));
00468 closeAct = menu.addAction(tr("&Close"));
00469 closeAct->setShortcut(tr("Ctrl+c"));
00470 connect(closeAct, SIGNAL(triggered()), this, SLOT(close()));
00471
00472 menu.exec(event->globalPos());
00473 }