PARP Research Group University of Murcia, Spain


src/qvgui/qvplot.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #include <qvgui/qvplot.h>
00026 #include <qwt_plot_layout.h>
00027 #include <qwt_scale_draw.h>
00028 #include <qwt_scale_widget.h>
00029 #include <qwt_legend.h>
00030 #include <qwt_legend_item.h>
00031 #include <qwt_plot_canvas.h>
00032 #include <qpainter.h>
00033 
00034 /*QColor QVPlot::colors[] = {
00035                 Qt::red,
00036                 Qt::green,
00037                 Qt::blue,
00038                 Qt::cyan,
00039                 Qt::magenta,
00040                 Qt::darkRed,
00041                 Qt::darkGreen,
00042                 Qt::darkBlue,
00043                 Qt::darkCyan,
00044                 Qt::darkMagenta
00045                 };*/
00046 
00048 // auxiliar classes functionality
00049 QVPlot::PieMarker::PieMarker(QVPlot *plot): qvplot(plot)
00050         {
00051         setZ(1000);
00052         setRenderHint(QwtPlotItem::RenderAntialiased, true);
00053         }
00054 
00055 int QVPlot::PieMarker::rtti() const
00056         {
00057         return QwtPlotItem::Rtti_PlotUserItem;
00058         }
00059 
00060 void QVPlot::PieMarker::draw(QPainter *p, const QwtScaleMap &, const QwtScaleMap &, const QRect &rect) const
00061         {
00062         const int margin = 5;
00063         int diameter = ( (rect.height() > rect.width()) ? rect.width(): rect.height() ) / 4;
00064 
00065         QRect pieRect;
00066         pieRect.setX(rect.right() - margin - diameter);
00067         pieRect.setY(rect.top() + margin);
00068 
00069         pieRect.setHeight(diameter);
00070         pieRect.setWidth(diameter);
00071 
00072         int angle = (int)(5760 * 0.75);
00073 
00074         double sum = 0;
00075         for(int i = 0; i < qvplot->linkCont.size(); i++)
00076                 for(int j = 0; j < qvplot->linkCont[i].properties.size(); j++)
00077                         for(int k = 0; k < qvplot->linkCont[i].properties[j].curves.size(); k++)
00078                                 if (qvplot->linkCont[i].properties[j].curves[k].plot->style() != QwtPlotCurve::NoCurve)
00079                                         sum += qvplot->linkCont[i].properties[j].curves[k].history[0];
00080 
00081 
00082         for(int i = 0; i < qvplot->linkCont.size(); i++)
00083                 for(int j = 0; j < qvplot->linkCont[i].properties.size(); j++)
00084                         for(int k = 0; k < qvplot->linkCont[i].properties[j].curves.size(); k++)
00085                                 {
00086                                 const QwtPlotCurve *curve = qvplot->linkCont[i].properties[j].curves[k].plot;
00087                                 if ( (curve->style() != QwtPlotCurve::NoCurve) && (curve->dataSize() > 0) )
00088                                         {
00089                                         const int value = (int)(5760 * qvplot->linkCont[i].properties[j].curves[k].history[0] / sum);
00090                                         p->save();
00091                                         p->setBrush(QBrush(curve->pen().color(), Qt::SolidPattern));
00092                                         if ( value != 0 )
00093                                                 p->drawPie(pieRect, -angle, -value);
00094                                         p->restore();
00095                 
00096                                         angle += value;
00097                                         }
00098                                 }
00099         }
00100 
00102 
00103 QVPlot::QVPlot(const QString name, bool decorations, bool havePie, bool brush, bool _autoShow, bool time, int step, QWidget *parent): QwtPlot(parent),
00104         QVPropertyContainer(name), byTime(time), iterationIndex(1), decorations(decorations), hPie(havePie), doBrush(brush), nStep(step), initied(false),
00105         autoShow(_autoShow), timer(0), haveCurves(FALSE), activeWorkers(0), usedColors(0)
00106         {
00107         qDebug() << "QVPlot::QVPlot()";
00108         if (qvApp == NULL)
00109                 {
00110                 QString str = "QVPlot::QVPlot(): the QVPlot cannot be created before the QVApplication instance. Aborting now.";
00111                 std::cerr << qPrintable(str) << std::endl;
00112                 exit(1);
00113                 }
00114         // if its a --help call, do nothing
00115         if (qvApp->forHelp()) return;
00116         else QwtPlot(parent);
00117 
00118 
00119         setWindowTitle("Plot for " + getName());
00120         resize(400,200);
00121         setAutoReplot(false);
00122 
00123         for ( int i = 0; i < MAX_HISTORY; i++ ) timeData[i] = i;
00124 
00125         plotLayout()->setAlignCanvasToScales(true);
00126 
00127         if (decorations)
00128                 {
00129                 QwtLegend *legend = new QwtLegend;
00130                 legend->setItemMode(QwtLegend::CheckableItem);
00131                 insertLegend(legend, QwtPlot::RightLegend);
00132                 }
00133         else
00134                 {
00135                 enableAxis(0,false);
00136                 enableAxis(1,false);
00137                 enableAxis(2,false);
00138                 }
00139 
00140         class TimeScaleDraw: public QwtScaleDraw
00141                 {
00142                 public:
00143                         TimeScaleDraw(const int stp): baseTime(), step(stp) { }
00144                         virtual QwtText label(double v) const { return baseTime.addSecs( (int)((v-MAX_HISTORY)*step/100)).toString(); }
00145                 private:
00146                         QTime baseTime;
00147                         int step;
00148                 };
00149         class IterScaleDraw: public QwtScaleDraw
00150                 {
00151                 public:
00152                         IterScaleDraw(const int stp): step(stp) { }
00153                         virtual QwtText label(double v) const   { return QString::number((int)(v-MAX_HISTORY)*step); }
00154                 private:
00155                         int step;
00156                 };
00157         if (byTime)     setAxisScaleDraw(QwtPlot::xBottom, new TimeScaleDraw(nStep));
00158         else            setAxisScaleDraw(QwtPlot::xBottom, new IterScaleDraw(nStep));
00159 
00160         setAxisScale(QwtPlot::xBottom, 0, MAX_HISTORY);
00161         setAxisLabelRotation(QwtPlot::xBottom, -50.0);
00162         setAxisLabelAlignment(QwtPlot::xBottom, Qt::AlignLeft | Qt::AlignBottom);
00163 
00164         /* In situations, when there is a label at the most right position of the
00165         scale, additional space is needed to display the overlapping part
00166         of the label would be taken by reducing the width of scale and canvas.
00167         To avoid this "jumping canvas" effect, we add a permanent margin.
00168         We don't need to do the same for the left border, because there
00169         is enough space for the overlapping label below the left scale. */
00170 
00171         QwtScaleWidget *scaleWidget = axisWidget(QwtPlot::xBottom);
00172         const int fmh = QFontMetrics(scaleWidget->font()).height();
00173         scaleWidget->setMinBorderDist(0, fmh / 2);
00174 
00175         setAxisTitle(QwtPlot::yLeft, "Value");
00176         if (byTime)     setAxisTitle(QwtPlot::xBottom, "Time");
00177         else            setAxisTitle(QwtPlot::xBottom, "Iterations");
00178         }
00179 
00180 QVPlot::~QVPlot()
00181 {
00182         stop();
00184 }
00185 
00186 bool QVPlot::linkProperty(QString, QVPropertyContainer *, QString, LinkType)
00187         {
00188                 std::cerr << "ERROR: QVPlot::linkProperty(): a QVPlot has not output properties to be linked" << std::endl;
00189                 return FALSE;
00190         }
00191 
00192 bool QVPlot::linkProperty(QString sourcePropertyName, QVPropertyContainer &destinyContainer, QString destinyPropertyName, LinkType linkType)
00193         {
00194                 return linkProperty(sourcePropertyName, &destinyContainer, destinyPropertyName, linkType);
00195         }
00196 
00197 bool QVPlot::linkProperty(QVPropertyContainer *, QString, LinkType)
00198         {
00199                 std::cerr << "ERROR: QVPlot::linkProperty(): a QVPlot has not output properties to be linked" << std::endl;
00200                 return FALSE;
00201         }
00202 
00203 bool QVPlot::linkProperty(QVPropertyContainer &destinyContainer, QString destinyPropertyName, LinkType linkType)
00204         {
00205                 return linkProperty(&destinyContainer, destinyPropertyName, linkType);
00206         }
00207 
00208 bool QVPlot::linkProperty(QString, QVPropertyContainer *, LinkType)
00209         {
00210                 std::cerr << "ERROR: QVPlot::linkProperty(): a QVPlot has not output properties to be linked" << std::endl;
00211                 return FALSE;
00212         }
00213 
00214 bool QVPlot::linkProperty(QString sourcePropertyName, QVPropertyContainer &destinyContainer, LinkType linkType)
00215         {
00216                 return linkProperty(sourcePropertyName, &destinyContainer, linkType);
00217         }
00218 
00219 void QVPlot::linkProperty(QVPropertyContainer *, LinkType)
00220         {
00221                 std::cerr << "ERROR: QVPlot::linkProperty(): a QVPlot has not output properties to be linked" << std::endl;
00222         }
00223 
00224 void QVPlot::linkProperty(QVPropertyContainer &container, LinkType linkType)
00225         {
00226                 linkProperty(&container, linkType);
00227         }
00228 
00229 bool QVPlot::unlinkProperty(QString, QVPropertyContainer *, QString)
00230         {
00231                 std::cerr << "ERROR: QVPlot::linkProperty(): a QVPlot has not output properties to be unlinked" << std::endl;
00232                 return FALSE;
00233         }
00234 
00235 bool QVPlot::unlinkProperty(QString origName, QVPropertyContainer &destCont, QString destName)
00236         {
00237                 return unlinkProperty(origName, &destCont, destName);
00238         }
00239 
00240 void QVPlot::unlink()
00241         {
00242                 std::cerr << "ERROR: QVPlot::linkProperty(): a QVPlot has not output properties to be unlinked" << std::endl;
00243         }
00244 
00245 bool QVPlot::linkUnspecifiedInputProperty(QVPropertyContainer *sourceContainer, QString sourcePropName, LinkType linkType)
00246         {
00247         if (initied)
00248                 {
00249                 std::cerr << "Warning: a worker can't be linked before plot was initied." << std::endl;
00250                 return false;
00251                 }
00252 
00253         if (linkType == SynchronousLink) {
00254                 std::cerr << "ERROR: QVPlot::linkUnspecifiedInputProperty(): the linkType must be AsynchronousLink, the link will not be done" << std::endl;
00255                 return false;
00256         }
00257 
00258         QVWorker* worker;
00259         if((worker = dynamic_cast<QVWorker*>(sourceContainer)) != NULL)
00260                 {
00261                 bool newWorker = false;
00262                 if (!pcl_Workers.contains(worker))
00263                         {
00264                         pcl_Workers << worker;
00265                         if ( (!byTime) && (!QVPropertyContainer::areSynchronized(pcl_Workers)) )
00266                                 {
00267                                 pcl_Workers.removeLast();
00268                                 std::cerr << "Warning: linked property's worker must be synchronized with previous plot's linked workers." << std::endl;
00269                                 return false;
00270                                 }
00271                         activeWorkers++;
00272                         newWorker = true;
00273                         }
00274         
00275                 QString myPropertyName = QString("%1").arg(worker->getId()) + ": " + sourcePropName;
00276                 addPropertyFromQVariant(myPropertyName, inputFlag, worker->getPropertyQVariantValue(sourcePropName), worker->getPropertyInfo(sourcePropName));
00277                 bool result = worker->linkProperty(sourcePropName, this, myPropertyName, QVWorker::AsynchronousLink);
00278         
00279                 if (newWorker)
00280                         {
00281                         linkCont << LinkedContainer(worker->getId());
00282         
00283                         // este tipo de bloqueo pos iteraciones puede retardar al worker
00284                         QObject::connect(worker, SIGNAL(endIteration(uint, int)), this, SLOT(update(uint, int)), Qt::BlockingQueuedConnection);
00285                         QObject::connect(worker, SIGNAL(statusUpdate(QVWorker::TWorkerStatus)), this, SLOT(workerChange(QVWorker::TWorkerStatus)));
00286                         }
00287         
00288                 for (int i = 0; i < linkCont.size(); i++)
00289                         if (linkCont[i].id == worker->getId())
00290                                 {
00291                                 linkCont[i].properties.append(Property(myPropertyName));
00292                                 break;
00293                                 }
00294         
00295                 return result;
00296                 }
00297         else
00298                 {
00299                 std::cerr << "ERROR: QVPlot::linkUnspecifiedInputProperty(): the sourceContainer container must be a QVWorker, the link will not be done" << std::endl;
00300                 return false;
00301                 }
00302         }
00303 
00304 bool QVPlot::treatUnlinkInputProperty(QString destPropName, QVPropertyContainer *sourceCont, QString)
00305         {
00306         for (int i = 0; i < linkCont.size(); i++)
00307                 if (linkCont[i].id == sourceCont->getId())
00308                         {
00309                         int pos = -1;
00310                         for (int j = 0; j < linkCont[i].properties.size(); j++)
00311                                 if (linkCont[i].properties[j].name == destPropName)
00312                                         pos = j;
00313         
00314                         if (pos >= 0)
00315                                 {
00316                                 linkCont[i].properties.removeAt(pos);
00317                                 }
00318         
00319                         if (linkCont[i].properties.size() == 0)
00320                                 {
00321                                 linkCont.removeAt(i);
00322                                 pcl_Workers.removeAll(sourceCont);
00323                                 activeWorkers--;
00324 
00325                                 QVWorker* worker;
00326                                 if((worker = dynamic_cast<QVWorker*>(sourceCont)) != NULL)
00327                                         {
00328                                         QObject::disconnect(worker, SIGNAL(endIteration(uint, int)), this, SLOT(update(uint, int)));
00329                                         QObject::disconnect(worker, SIGNAL(statusUpdate(QVWorker::TWorkerStatus)), this, SLOT(workerChange(QVWorker::TWorkerStatus)));
00330                                         }
00331                                 }
00332                                 break;
00333                         }
00334 
00335         removeProperty(destPropName);
00336         return true;
00337         }
00338 
00339 void QVPlot::init()
00340         {
00341         if (initied)
00342                 {
00343                 std::cerr << "Warning: a plot can't be initied more than one time." << std::endl;
00344                 return;
00345                 }
00346 
00347         if (hPie)
00348                 {
00349                 pie = new PieMarker(this);
00350                 pie->attach(this);
00351                 }
00352 
00353         readInputProperties();
00354         for(int i = 0; i < linkCont.size(); i++)
00355                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00356                         {
00357                         const QStringList curvNames = getPropertyCurvNames(linkCont[i].properties[j].name);
00358 
00359                         for(int k = curvNames.size()-1; k >= 0; k--)
00360                                 {
00361                                 QString finalName = curvNames.at(k) + QString(" (%1)").arg(linkCont[i].id);
00362 
00363                                 QwtPlotCurve * qwtpc = new QwtPlotCurve(finalName);
00364                                 qwtpc->setRenderHint(QwtPlotItem::RenderAntialiased);
00365                                 QColor color = nextColor();
00366                                 qwtpc->setPen(color);
00367                                 if (doBrush) qwtpc->setBrush(color);
00368                                 qwtpc->setVisible(true);
00369                                 qwtpc->attach(this);
00370 
00371                                 if (byTime) linkCont[i].properties[j].curves.prepend(Curve(finalName, qwtpc, 1));
00372                                 else        linkCont[i].properties[j].curves.prepend(Curve(finalName, qwtpc, linkCont.size()+1));
00373                                 haveCurves = TRUE;
00374                                 }
00375 
00376                         // and conect the legend items chechek signal
00377                         updateLegendItems();
00378                         }
00379 
00380         if (byTime) timer = startTimer(nStep * 10); // nStep * 10 ms
00381 
00382         initied = true;
00383         }
00384 
00385 void QVPlot::stop()
00386         {
00387         if (byTime && initied) killTimer(timer);
00388         initied = false;
00389         }
00390 
00391 QColor QVPlot::nextColor()
00392         {
00393         QColor color = qvColors[usedColors % 10];
00394         usedColors++;
00395         return color;
00396         }
00397 
00398 void QVPlot::timerEvent(QTimerEvent *)
00399         {
00400         if (!initied) 
00401                 {
00402                 std::cerr << "Warning: a plot can't be advanced before it was initied." << std::endl;
00403                 return;
00404                 }
00405 
00406         // if there are data of flags, advance the Plot
00407         if (haveCurves) advancePlot();
00408         for (int i = 0; i < linkCont.size(); i++) linkCont[i].meanItems = 0;
00409         }
00410 
00411 void QVPlot::workerChange(QVWorker::TWorkerStatus status)
00412         {
00413         if ( (status == QVWorker::Finished) && (activeWorkers > 0) ) activeWorkers--;
00414         }
00415 
00416 void QVPlot::update(uint id, int)
00417         {
00418         // First must be initied
00419         if (!initied) 
00420                 {
00421                 std::cerr << "Warning: a plot can't be advanced before it was initied." << std::endl;
00422                 return;
00423                 }
00424 
00425         if (byTime)
00426                 {
00427                 readInputProperties();
00428                 for(int i = 0; i < linkCont.size(); i++)
00429                         if (linkCont[i].id == id)
00430                                 {
00431                                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00432                                         {
00433                                         insertNewFlags(i, j);
00434                 
00435                                         const QList<double> values = getPropertyCurvValues(linkCont[i].properties[j].name);
00436                                         if (values.size() != linkCont[i].properties[j].curves.size())
00437                                                 {
00438                                                 std::cerr << "QVPlot internal error: flags insert." << std::endl;
00439                                                 return;
00440                                                 }
00441                 
00442                                         for (int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00443                                                 if (linkCont[i].meanItems < 1)
00444                                                         linkCont[i].properties[j].curves[k].temp[0] = values[k];
00445                                                 else
00446                                                         linkCont[i].properties[j].curves[k].temp[0] =
00447                                                         (linkCont[i].properties[j].curves[k].temp[0]*linkCont[i].meanItems+values[k]) / (linkCont[i].meanItems + 1);
00448                                         linkCont[i].meanItems++;
00449                                         }
00450                                 break;
00451                                 }
00452                 }
00453         else
00454                 {
00455                 readInputProperties();
00456                 for(int i = 0; i < linkCont.size(); i++)
00457                         if (linkCont[i].id == id)
00458                                 {
00459                                 linkCont[i].iter++;
00460                                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00461                                         {
00462                                         insertNewFlags(i, j);
00463                 
00464                                         const QList<double> values = getPropertyCurvValues(linkCont[i].properties[j].name);
00465                                         if (values.size() != linkCont[i].properties[j].curves.size())
00466                                                 {
00467                                                 std::cerr << "QVPlot internal error: flags insert." << std::endl;
00468                                                 return;
00469                                                 }
00470 
00471                                         // update worker's properties values for its iteration in the "temp" buffer (add the new value)
00472                                         for (int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00473                                                 linkCont[i].properties[j].curves[k].temp[(linkCont[i].iter % (linkCont.size()+1))] += values[k];
00474                                         }
00475                                 break;
00476                                 }
00477 
00478                 int updateWorkers = 0;
00479                 for (int i = 0; i < linkCont.size(); i++)
00480                         if (linkCont[i].iter >= iterationIndex) updateWorkers++;
00481 
00482                 // If has completed the current iteration column
00483                 if (updateWorkers >= activeWorkers)
00484                         {
00485                         // If has completed nStep iterations
00486                         if ((iterationIndex % nStep) == 0)
00487                                 {
00488                                 // obtain the mean to it
00489                                 for(int i = 0; i < linkCont.size(); i++)
00490                                         {
00491                                         linkCont[i].meanItems++;
00492                                         for(int j = 0; j < linkCont[i].properties.size(); j++)
00493                                                 for (int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00494                                                         linkCont[i].properties[j].curves[k].temp[(iterationIndex % (linkCont.size()+1))] /= linkCont[i].meanItems;
00495                                         linkCont[i].meanItems = 0;
00496                                         }
00497 
00498                                 // Advance the plot
00499                                 if (haveCurves) advancePlot();
00500                                 }
00501                         else
00502                                 {
00503                                 for(int i = 0; i < linkCont.size(); i++)
00504                                         {
00505                                         linkCont[i].meanItems++;
00506                                         for(int j = 0; j < linkCont[i].properties.size(); j++)
00507                                                 for (int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00508                                                         linkCont[i].properties[j].curves[k].temp[((iterationIndex+1) % (linkCont.size()+1))] +=
00509                                                         linkCont[i].properties[j].curves[k].temp[(iterationIndex % (linkCont.size()+1))];
00510                                         }
00511                                 }
00512                         // And reset the column
00513                         for(int i = 0; i < linkCont.size(); i++)
00514                                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00515                                         for (int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00516                                                 linkCont[i].properties[j].curves[k].temp[(iterationIndex % (linkCont.size()+1))] = 0;
00517                         iterationIndex++;
00518                         }
00519                 }
00520         }
00521 
00522 void QVPlot::insertNewFlags(int cont, int prop)
00523         {
00524         const QStringList curvNames = getPropertyCurvNames(linkCont[cont].properties[prop].name);
00525         if ( (linkCont.size() > cont) && (linkCont[cont].properties.size() > prop) && (curvNames.size() > linkCont[cont].properties[prop].curves.size()) )
00526                 {
00527                 const QList<int> curvOrders = getPropertyCurvOrders(linkCont[cont].properties[prop].name);
00528                 for (int i = 0; i < curvOrders.size(); i++)
00529                         if (curvOrders.at(i) > linkCont[cont].properties[prop].curves.size())
00530                                 {
00531                                 QString finalName = curvNames.at(i) + QString(" (%1)").arg(linkCont[cont].id);
00532 
00533                                 QwtPlotCurve * qwtpc = new QwtPlotCurve(finalName);
00534                                 qwtpc->setRenderHint(QwtPlotItem::RenderAntialiased);
00535                                 QColor color = nextColor();
00536                                 qwtpc->setPen(color);
00537                                 if (doBrush) qwtpc->setBrush(color);
00538                                 qwtpc->setVisible(true);
00539 
00540                                 if (byTime) linkCont[cont].properties[prop].curves.insert(i, Curve(finalName, qwtpc, 1));
00541                                 else        linkCont[cont].properties[prop].curves.insert(i, Curve(finalName, qwtpc, linkCont.size()+1));
00542                                 haveCurves = TRUE;
00543                                 }
00544 
00545                 for(int i = linkCont.size()-1; i >= 0; i--)
00546                         for(int j = linkCont[i].properties.size()-1; j >= 0; j--)
00547                                 for (int k = linkCont[i].properties[j].curves.size()-1; k >= 0; k--)
00548                                         {
00549                                         linkCont[i].properties[j].curves[k].plot->detach();
00550                                         linkCont[i].properties[j].curves[k].plot->attach(this);
00551                                         }
00552 
00553                 // and reconect the legend items chechek signal
00554                 updateLegendItems();
00555                 }
00556         }
00557 
00558 void QVPlot::advancePlot()
00559         {
00560         if (!haveCurves)
00561                 {
00562                 std::cerr << "QVPlot internal error: early call to advancePlot." << std::endl;
00563                 return;
00564                 }
00565 
00566         // increments the values to scroll the window
00567         for ( int j = 0; j < MAX_HISTORY; j++ ) timeData[j]++;
00568 
00569         double max = 0;
00570         double brush[MAX_HISTORY]; for (int i = 0; i < MAX_HISTORY; i++) brush[i] = 0;
00571 
00572         // for each curve
00573         for(int i = 0; i < linkCont.size(); i++)
00574                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00575                         for(int k = 0; k < linkCont[i].properties[j].curves.size(); k++) {
00576                                  // scroll the curve values
00577                                 for (int l = 0; l < MAX_HISTORY-1; l++)
00578                                         linkCont[i].properties[j].curves[k].history[l] = linkCont[i].properties[j].curves[k].history[l+1];
00579 
00580                                 // update the new value
00581                                 if (byTime)     linkCont[i].properties[j].curves[k].history[MAX_HISTORY-1] = linkCont[i].properties[j].curves[k].temp[0];
00582                                 else            linkCont[i].properties[j].curves[k].history[MAX_HISTORY-1] = linkCont[i].properties[j].curves[k].temp[(iterationIndex%(linkCont.size()+1))];
00583 
00584                                 // if is visible, update the plot values
00585                                 if (linkCont[i].properties[j].curves[k].plot->style() != QwtPlotCurve::NoCurve) {
00586                                         if (doBrush) { // if is in brush mode, update the increment, sets the brush value, calculate the max value, and set the curve's plot
00587                                                 for (int l = 0; l < MAX_HISTORY; l++) {
00588                                                         brush[l] += linkCont[i].properties[j].curves[k].history[l];
00589                                                         linkCont[i].properties[j].curves[k].brushHistory[l] = brush[l];
00590                                                         if (max < linkCont[i].properties[j].curves[k].brushHistory[l]) max = linkCont[i].properties[j].curves[k].brushHistory[l];
00591                                                 }
00592                                                 linkCont[i].properties[j].curves[k].plot->setRawData(timeData, linkCont[i].properties[j].curves[k].brushHistory, MAX_HISTORY);
00593                                         }
00594                                         else { // if isn't in brush mode, calculate the max value, and set the curve's plot
00595                                                 for (int l = 0; l < MAX_HISTORY; l++) {
00596                                                         if (max < linkCont[i].properties[j].curves[k].history[l]) max = linkCont[i].properties[j].curves[k].history[l];
00597                                                 }
00598                                                 linkCont[i].properties[j].curves[k].plot->setRawData(timeData, linkCont[i].properties[j].curves[k].history, MAX_HISTORY);
00599                                         }
00600                                 }
00601                         }
00602         max = 1.1 *max;
00603 
00604         setAxisScale(QwtPlot::yLeft, 0, max);
00605         setAxisScale(QwtPlot::xBottom, timeData[MAX_HISTORY - 1], timeData[0]);
00606 
00607         // and replot
00608         replot();
00609         }
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 void QVPlot::updateLegendItems()
00621         {
00622         if (decorations)
00623                 foreach(QWidget *widgetItem, legend()->legendItems())
00624                         {
00625                         QwtLegendItem *legendItem;
00626                         if((legendItem = dynamic_cast<QwtLegendItem*>(widgetItem)) != NULL)
00627                                 QObject::connect(legendItem, SIGNAL(checked(bool)), this, SLOT(legendItemCheked(bool)));
00628                         }
00629         }
00630 
00631 void QVPlot::legendItemCheked(bool)
00632         {
00633         if (decorations)
00634                 foreach(QWidget *widgetItem, legend()->legendItems())
00635                         {
00636                         QwtLegendItem *legendItem;
00637                         if ((legendItem = dynamic_cast<QwtLegendItem*>(widgetItem)) != NULL)
00638                                 if (legendItem->isChecked())
00639                                         hideStat(legendItem->text().text());
00640                                 else
00641                                         showStat(legendItem->text().text());
00642                         }
00643         }
00644 
00645 void QVPlot::hideStat(const QString labelText)
00646         {
00647         for(int i = 0; i < linkCont.size(); i++)
00648                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00649                         for(int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00650                                 if (linkCont[i].properties[j].curves[k].name == labelText) {
00651                                         linkCont[i].properties[j].curves[k].plot->setStyle(QwtPlotCurve::NoCurve);
00652                                         return;
00653                                 }
00654         }
00655 
00656 void QVPlot::showStat(const QString labelText)
00657         {
00658         for(int i = 0; i < linkCont.size(); i++)
00659                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00660                         for(int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00661                                 if (linkCont[i].properties[j].curves[k].name == labelText)
00662                                         {
00663                                         linkCont[i].properties[j].curves[k].plot->setStyle(QwtPlotCurve::Lines);
00664                                         return;
00665                                         }
00666         }



QVision framework. PARP research group, copyright 2007, 2008.