PARP Research Group University of Murcia, Spain


src/qvgui/qvplot.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007, 2008, 2009. 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 != AsynchronousLink) {
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 = sourcePropName + QString(" (%1)").arg(worker->getId());
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);
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);
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         if (activeWorkers < 1)
00567                 return;
00568 
00569         // increments the values to scroll the window
00570         for ( int j = 0; j < MAX_HISTORY; j++ ) timeData[j]++;
00571 
00572         double max = 0;
00573         double brush[MAX_HISTORY]; for (int i = 0; i < MAX_HISTORY; i++) brush[i] = 0;
00574 
00575         // for each curve
00576         for(int i = 0; i < linkCont.size(); i++)
00577                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00578                         for(int k = 0; k < linkCont[i].properties[j].curves.size(); k++) {
00579                                  // scroll the curve values
00580                                 for (int l = 0; l < MAX_HISTORY-1; l++)
00581                                         linkCont[i].properties[j].curves[k].history[l] = linkCont[i].properties[j].curves[k].history[l+1];
00582 
00583                                 // update the new value
00584                                 if (byTime)     linkCont[i].properties[j].curves[k].history[MAX_HISTORY-1] = linkCont[i].properties[j].curves[k].temp[0];
00585                                 else            linkCont[i].properties[j].curves[k].history[MAX_HISTORY-1] = linkCont[i].properties[j].curves[k].temp[(iterationIndex%(linkCont.size()+1))];
00586 
00587                                 // if is visible, update the plot values
00588                                 if (linkCont[i].properties[j].curves[k].plot->style() != QwtPlotCurve::NoCurve) {
00589                                         if (doBrush) { // if is in brush mode, update the increment, sets the brush value, calculate the max value, and set the curve's plot
00590                                                 for (int l = 0; l < MAX_HISTORY; l++) {
00591                                                         brush[l] += linkCont[i].properties[j].curves[k].history[l];
00592                                                         linkCont[i].properties[j].curves[k].brushHistory[l] = brush[l];
00593                                                         if (max < linkCont[i].properties[j].curves[k].brushHistory[l]) max = linkCont[i].properties[j].curves[k].brushHistory[l];
00594                                                 }
00595                                                 linkCont[i].properties[j].curves[k].plot->setRawData(timeData, linkCont[i].properties[j].curves[k].brushHistory, MAX_HISTORY);
00596                                         }
00597                                         else { // if isn't in brush mode, calculate the max value, and set the curve's plot
00598                                                 for (int l = 0; l < MAX_HISTORY; l++) {
00599                                                         if (max < linkCont[i].properties[j].curves[k].history[l]) max = linkCont[i].properties[j].curves[k].history[l];
00600                                                 }
00601                                                 linkCont[i].properties[j].curves[k].plot->setRawData(timeData, linkCont[i].properties[j].curves[k].history, MAX_HISTORY);
00602                                         }
00603                                 }
00604                         }
00605         max = 1.1 *max;
00606 
00607         setAxisScale(QwtPlot::yLeft, 0, max);
00608         setAxisScale(QwtPlot::xBottom, timeData[MAX_HISTORY - 1], timeData[0]);
00609 
00610         // and replot
00611         replot();
00612         }
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 
00621 
00622 
00623 void QVPlot::updateLegendItems()
00624         {
00625         if (decorations)
00626                 foreach(QWidget *widgetItem, legend()->legendItems())
00627                         {
00628                         QwtLegendItem *legendItem;
00629                         if((legendItem = dynamic_cast<QwtLegendItem*>(widgetItem)) != NULL)
00630                                 QObject::connect(legendItem, SIGNAL(checked(bool)), this, SLOT(legendItemCheked(bool)));
00631                         }
00632         }
00633 
00634 void QVPlot::legendItemCheked(bool)
00635         {
00636         if (decorations)
00637                 foreach(QWidget *widgetItem, legend()->legendItems())
00638                         {
00639                         QwtLegendItem *legendItem;
00640                         if ((legendItem = dynamic_cast<QwtLegendItem*>(widgetItem)) != NULL)
00641                                 if (legendItem->isChecked())
00642                                         hideStat(legendItem->text().text());
00643                                 else
00644                                         showStat(legendItem->text().text());
00645                         }
00646         }
00647 
00648 void QVPlot::hideStat(const QString labelText)
00649         {
00650         for(int i = 0; i < linkCont.size(); i++)
00651                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00652                         for(int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00653                                 if (linkCont[i].properties[j].curves[k].name == labelText) {
00654                                         linkCont[i].properties[j].curves[k].plot->setStyle(QwtPlotCurve::NoCurve);
00655                                         return;
00656                                 }
00657         }
00658 
00659 void QVPlot::showStat(const QString labelText)
00660         {
00661         for(int i = 0; i < linkCont.size(); i++)
00662                 for(int j = 0; j < linkCont[i].properties.size(); j++)
00663                         for(int k = 0; k < linkCont[i].properties[j].curves.size(); k++)
00664                                 if (linkCont[i].properties[j].curves[k].name == labelText)
00665                                         {
00666                                         linkCont[i].properties[j].curves[k].plot->setStyle(QwtPlotCurve::Lines);
00667                                         return;
00668                                         }
00669         }



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