24 #include <QGraphicsScene> 25 #include <QGraphicsView> 26 #include <QGraphicsItem> 27 #include <QGraphicsRectItem> 28 #include <QHBoxLayout> 29 #include <QFormLayout> 30 #include <QtGui/QResizeEvent> 31 #include <QtGui/QMouseEvent> 32 #include <QtCore/QTime> 33 #include <QtCore/QTimer> 34 #include <QtCore/QFileInfo> 35 #include <QPushButton> 36 #include <QToolButton> 40 #include <QInputDialog> 41 #include <QMessageBox> 42 #include <QFileDialog> 43 #include <QtGui/QClipboard> 44 #include <QApplication> 46 #include <QColorDialog> 49 #include <QtSvg/QSvgGenerator> 57 QGraphicsEllipseItem(0, 0, width, width, 0),
63 this->
init(dataX, dataY);
67 QGraphicsEllipseItem(0, 0, width, width, 0),
73 this->
init(data.x(), data.y());
80 this->setAcceptHoverEvents(
true);
81 this->setFlag(QGraphicsItem::ItemIsFocusable,
true);
143 if(this->parentItem() && this->parentItem() !=
_textBackground->parentItem())
149 if(this->scene() && shown)
154 this->setPen(QPen(this->pen().color(), 2));
156 QRectF rect = this->scene()->sceneRect();
157 QPointF p = this->pos();
158 QRectF br =
_text->boundingRect();
162 if(p.x() - br.width() < 0)
166 else if(p.x() > rect.width())
168 p.setX(rect.width() - br.width());
172 p.setX(p.x() - br.width());
175 if(p.y() - br.height() < 0)
181 p.setY(p.y() - br.height());
188 this->setPen(QPen(this->pen().color(), 1));
196 QGraphicsEllipseItem::hoverEnterEvent(event);
201 if(!this->hasFocus())
205 QGraphicsEllipseItem::hoverLeaveEvent(event);
211 QGraphicsEllipseItem::focusInEvent(event);
217 QGraphicsEllipseItem::focusOutEvent(event);
223 if(keyEvent->key() == Qt::Key_Right)
226 while(next && !next->isVisible())
230 if(next && next->isVisible())
236 else if(keyEvent->key() == Qt::Key_Left)
239 while(previous && !previous->isVisible())
243 if(previous && previous->isVisible())
246 previous->setFocus();
249 QGraphicsEllipseItem::keyReleaseEvent(keyEvent);
264 _itemsColor(0,0,0,150)
312 if(!plot || plot ==
_plot)
327 ULOGGER_DEBUG(
"curve=\"%s\" from plot=\"%s\"", this->objectName().toStdString().c_str(), plot?plot->objectName().toStdString().c_str():
"");
329 if(plot &&
_plot == plot)
351 for(
int i=0; i<
_items.size(); ++i)
356 x = item->
data().x();
357 y = item->
data().y();
381 qreal
x = data->
data().x();
382 qreal y = data->
data().y();
391 QGraphicsLineItem * line =
new QGraphicsLineItem(
_rootItem);
393 line->setVisible(
false);
411 data->setVisible(
false);
412 QPen
pen = data->pen();
438 UWARN(
"New value (%f) added to curve \"%s\" is smaller " 439 "than the last added (%f). Clearing the curve.",
466 qreal v = value.toDouble(&ok);
473 ULOGGER_ERROR(
"Value not valid, must be a number, received %s", value.toStdString().c_str());
479 for(
int i=0; i<data.size(); ++i)
489 for(
int i=0; i<xs.size() && i<ys.size(); ++i)
500 for(
int i=0; i<ys.size(); ++i)
520 for(
int i=0; i<ys.size(); ++i)
540 for(
unsigned int i=0; i<ys.size(); ++i)
560 for(
unsigned int i=0; i<ys.size(); ++i)
578 if(index >= 0 && index <
_items.size())
583 delete _items.takeAt(index);
587 delete _items.takeAt(index+1);
599 qreal
x = tmp->
data().x();
600 qreal y = tmp->
data().y();
605 for(
int i = 2; i<
_items.size(); i+=2)
630 for(
int i=0; i<
_items.size(); ++i)
645 item->scene()->removeItem(item);
664 for(
int i=1; i<
_items.size(); i+=2)
681 for(
int i=0; i<
_items.size(); i+=2)
690 void UPlotCurve::update(qreal scaleX, qreal scaleY, qreal offsetX, qreal offsetY, qreal xDir, qreal yDir,
int maxItemsKept)
694 xDir<0?xDir=-1:xDir=1;
695 yDir<0?yDir=-1:yDir=1;
699 for(
int i=
_items.size()-1; i>=0; --i)
706 if(maxItemsKept == 0 || j <= maxItemsKept)
709 if(!item->isVisible())
713 item->setVisible(
false);
723 QPointF newPos(((xDir*item->
data().x()+offsetX)*scaleX-item->rect().width()/2.0f),
724 ((yDir*item->
data().y()+offsetY)*scaleY-item->rect().width()/2.0f));
725 if(!item->isVisible())
727 item->setVisible(
true);
729 item->setPos(newPos);
737 _items.at(i)->setVisible(
false);
743 QGraphicsLineItem * lineItem = (QGraphicsLineItem *)
_items.at(i);
744 lineItem->setLine((xDir*from->
data().x()+offsetX)*scaleX,
745 (yDir*from->
data().y()+offsetY)*scaleY,
746 (xDir*to->
data().x()+offsetX)*scaleX,
747 (yDir*to->
data().y()+offsetY)*scaleY);
748 if(!lineItem->isVisible())
750 lineItem->setVisible(
true);
754 QLineF line = lineItem->line();
755 if((line.x1() <= line.x2() && line.x2() < 0-((line.x2() - line.x1()))) ||
756 (line.x1() > line.x2() && line.x2() > lineItem->scene()->sceneRect().width() + ((line.x1() - line.x2()))))
771 for(
int i=
_items.size()-1; i>=0 &&
_items.at(i)->isVisible(); i-=2)
775 int x = (int)item->x();
785 const QGraphicsLineItem * lineItem = (
const QGraphicsLineItem *)
_items.at(i-1);
786 QLine line = lineItem->line().toLine();
787 if(limits.contains(line.p1()) || limits.contains(line.p2()))
790 QLineF::IntersectType type;
791 type = lineItem->line().intersect(QLineF(limits.topLeft(), limits.bottomLeft()), &intersection);
792 if(type == QLineF::BoundedIntersection)
794 !limits.contains(line.p1())?line.setP1(intersection.toPoint()):line.setP2(intersection.toPoint());
798 type = lineItem->line().intersect(QLineF(limits.topLeft(), limits.topRight()), &intersection);
799 if(type == QLineF::BoundedIntersection)
801 !limits.contains(line.p1())?line.setP1(intersection.toPoint()):line.setP2(intersection.toPoint());
805 type = lineItem->line().intersect(QLineF(limits.bottomLeft(), limits.bottomRight()), &intersection);
806 if(type == QLineF::BoundedIntersection)
808 !limits.contains(line.p1())?line.setP1(intersection.toPoint()):line.setP2(intersection.toPoint());
812 type = lineItem->line().intersect(QLineF(limits.topRight(), limits.bottomRight()), &intersection);
813 if(type == QLineF::BoundedIntersection)
815 !limits.contains(line.p1())?line.setP1(intersection.toPoint()):line.setP2(intersection.toPoint());
821 painter->setPen(this->
pen());
822 painter->setBrush(this->
brush());
823 painter->drawLine(line);
848 if(index>=0 && index <
_items.size() && index % 2 == 0 )
862 for(
int i=0; i<
_items.size(); ++i)
864 _items.at(i)->setVisible(visible);
881 for(
int i = 0; i<data.size(); ++i)
889 if(x.size() == y.size())
892 int margin = int((
_items.size()+1)/2) - x.size();
907 QVector<qreal>::const_iterator i=x.begin();
908 QVector<qreal>::const_iterator j=y.begin();
909 for(; i!=x.end() && j!=y.end(); ++i, ++j, index+=2)
918 else if(y.size()>0 && x.size()==0)
930 if(x.size() == y.size())
933 int margin = int((
_items.size()+1)/2) - int(x.size());
948 std::vector<qreal>::const_iterator i=x.begin();
949 std::vector<qreal>::const_iterator j=y.begin();
950 for(; i!=x.end() && j!=y.end(); ++i, ++j, index+=2)
959 else if(y.size()>0 && x.size()==0)
971 this->
setData(y.toStdVector());
977 int margin = int((
_items.size()+1)/2) - int(y.size());
993 std::vector<qreal>::const_iterator j=y.begin();
994 for(; j!=y.end(); ++j, index+=2)
1010 x.resize((
_items.size()-1)/2+1);
1013 for(
int i=0; i<
_items.size(); i+=2)
1026 for(
int i=0; i<
_items.size(); i+=2)
1039 _orientation(orientation)
1069 item->
setData(QPointF(item->
data().x(), threshold));
1071 item->
setData(QPointF(item->
data().x(), threshold));
1076 item->
setData(QPointF(threshold, item->
data().y()));
1078 item->
setData(QPointF(threshold, item->
data().y()));
1083 ULOGGER_ERROR(
"A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)");
1102 ULOGGER_ERROR(
"A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)");
1118 item->
setData(QPointF(-(offsetX-item->rect().width()/scaleX)/xDir, item->
data().y()));
1120 item->
setData(QPointF( (
_plot->
sceneRect().width()/scaleX-(offsetX+item->rect().width()/scaleX))/xDir, item->
data().y()));
1125 item->
setData(QPointF(item->
data().x(), -(offsetY-item->rect().height()/scaleY)/yDir));
1127 item->
setData(QPointF(item->
data().x(), (
_plot->
sceneRect().height()/scaleY-(offsetY+item->rect().height()/scaleY))/yDir));
1134 ULOGGER_ERROR(
"A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)");
1161 this->setMinimumSize(15, 25);
1163 this->setMinimumSize(15, 25);
1193 borderMin = borderMax = this->fontMetrics().height()/2;
1200 int border = borderMin>borderMax?borderMin:borderMax;
1205 length = (this->height()-border*2);
1209 length = (this->width()-border*2);
1216 else if(length <= 175)
1220 else if(length <= 350)
1224 else if(length <= 700)
1228 else if(length <= 1000)
1232 else if(length <= 1300)
1245 qreal rangef = max -
min;
1248 for(
int i=0; i<6; ++i)
1250 val = (rangef/qreal(countStep)) * mul;
1251 if( val >= 1.0
f && val < 10.0
f)
1265 int minR = min*mul-0.9;
1266 int maxR = max*mul+0.9;
1267 min = qreal(minR)/mul;
1268 max = qreal(maxR)/mul;
1292 if(borderDelta%2 != 0)
1297 _border = border + borderDelta/2;
1303 for (
int i = 0; i <=
_count; i+=5)
1306 if(this->fontMetrics().width(n) > minWidth)
1308 minWidth = this->fontMetrics().width(n);
1311 this->setMinimumWidth(15+minWidth);
1317 QPainter painter(
this);
1320 painter.translate(0,
_border);
1321 for (
int i = 0; i <=
_count; ++i)
1325 painter.drawLine(this->width(), 0, this->width()-10, 0);
1327 painter.drawText(this->width()-(12+n.sizeHint().width()), n.sizeHint().height()/2-2, n.text());
1331 painter.drawLine(this->width(), 0, this->width()-5, 0);
1333 painter.translate(0,
_step);
1338 painter.translate(
_border, 0);
1339 for (
int i = 0; i <=
_count; ++i)
1343 painter.drawLine(0, 0, 0, 10);
1345 painter.drawText(-(n.sizeHint().width()/2)+1, 22, n.text());
1349 painter.drawLine(0, 0, 0, 5);
1351 painter.translate(
_step, 0);
1360 QPushButton(parent),
1363 QString nameSpaced = curve->
name();
1364 nameSpaced.replace(
'_',
' ');
1365 this->setText(nameSpaced);
1368 this->setIconSize(QSize(25,20));
1370 _aChangeText =
new QAction(tr(
"Change text..."),
this);
1371 _aResetText =
new QAction(tr(
"Reset text..."),
this);
1374 _aShowStdDevMeanMax =
new QAction(tr(
"Show %1, %2, max").arg(QChar(0xbc, 0x03)).arg(QChar(0xc3, 0x03)),
this);
1376 _aMoveUp =
new QAction(tr(
"Move up"),
this);
1377 _aMoveDown =
new QAction(tr(
"Move down"),
this);
1379 _menu =
new QMenu(tr(
"Curve"),
this);
1385 _menu->addSeparator();
1388 _menu->addSeparator();
1398 QAction * action =
_menu->exec(event->globalPos());
1402 QString text = QInputDialog::getText(
this,
_aChangeText->text(), tr(
"Name :"), QLineEdit::Normal, this->text(), &ok);
1403 if(ok && !text.isEmpty())
1405 this->setText(text);
1420 QColor color = QColorDialog::getColor(pen.color(),
this);
1423 pen.setColor(color);
1441 for(
int i=0; i<x.size(); ++i)
1443 text.append(QString::number(x[i]));
1445 text.append(QString::number(y[i]));
1451 QClipboard * clipboard = QApplication::clipboard();
1452 clipboard->setText(text);
1485 nameSpaced.replace(
'_',
' ');
1486 this->setText(nameSpaced);
1492 QPixmap pixmap(50, 50);
1493 pixmap.fill(Qt::transparent);
1494 QPainter painter(&pixmap);
1498 painter.drawLine(0.0, 25.0, 50.0, 25.0);
1504 QVector<qreal>
x, y;
1506 qreal mean =
uMean(y.data(), y.size());
1508 qreal
max =
uMax(y.data(), y.size());
1510 nameSpaced.replace(
'_',
' ');
1511 nameSpaced += QString(
"\n(%1=%2, %3=%4, max=%5, n=%6)").arg(QChar(0xbc, 0x03)).arg(QString::number(mean,
'f', 3)).arg(QChar(0xc3, 0x03)).arg(QString::number(stdDev,
'f', 3)).arg(QString::number(max,
'f', 3)).arg(y.size());
1512 this->setText(nameSpaced);
1529 _aShowAllStdDevMeanMax =
new QAction(tr(
"Show all %1, %2, max").arg(QChar(0xbc, 0x03)).arg(QChar(0xc3, 0x03)),
this);
1532 _menu =
new QMenu(tr(
"Legend"),
this);
1541 this->setLayout(
new QVBoxLayout());
1542 this->layout()->setContentsMargins(0,0,0,0);
1545 QWidget * _scrollAreaWidgetContent =
new QWidget();
1546 _scrollArea->setWidget( _scrollAreaWidgetContent );
1567 QList<UPlotLegendItem*> items = this->findChildren<UPlotLegendItem*>();
1568 for(
int i=0; i<items.size(); ++i)
1570 items.at(i)->setFlat(
_flat);
1571 items.at(i)->setChecked(!items.at(i)->isChecked());
1582 legendItem->setAutoDefault(
false);
1583 legendItem->setFlat(
_flat);
1584 legendItem->setCheckable(
true);
1585 legendItem->setChecked(
false);
1586 connect(legendItem, SIGNAL(toggled(
bool)),
this, SLOT(
redirectToggled(
bool)));
1592 QHBoxLayout * hLayout =
new QHBoxLayout();
1593 hLayout->addWidget(legendItem);
1594 hLayout->addStretch(0);
1595 hLayout->setMargin(0);
1600 _scrollArea->setMinimumWidth(
std::min(480,
_scrollArea->widget()->sizeHint().width()+QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent)));
1606 QList<UPlotLegendItem *> items = this->findChildren<UPlotLegendItem*>();
1607 for(
int i=0; i<items.size(); ++i)
1609 if(items.at(i)->curve() == curve)
1612 _scrollArea->setMinimumWidth(
std::min(480,
_scrollArea->widget()->sizeHint().width()+QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent)));
1621 if(this->
remove(curve))
1630 QLayoutItem * layoutItem = 0;
1641 if(index > 0 && layoutItem)
1644 QHBoxLayout * hLayout =
new QHBoxLayout();
1645 hLayout->addWidget(layoutItem->layout()->itemAt(0)->widget());
1646 hLayout->addStretch(0);
1647 hLayout->setMargin(0);
1657 QLayoutItem * layoutItem = 0;
1668 if(index < _contentLayout->count()-2 && layoutItem)
1671 QHBoxLayout * hLayout =
new QHBoxLayout();
1672 hLayout->addWidget(layoutItem->layout()->itemAt(0)->widget());
1673 hLayout->addStretch(0);
1674 hLayout->setMargin(0);
1683 QList<UPlotLegendItem *> items = this->findChildren<UPlotLegendItem*>();
1687 QMap<qreal, qreal> xAxisMap;
1688 for(
int i=0; i<items.size(); ++i)
1690 QMap<qreal, qreal>
data;
1691 items.at(i)->curve()->getData(data);
1692 for(QMap<qreal, qreal>::iterator iter=data.begin(); iter!=data.end(); ++iter)
1694 xAxisMap.insert(iter.key(), iter.value());
1697 QList<qreal> xAxis = xAxisMap.uniqueKeys();
1699 QVector<QVector<qreal> > axes;
1700 for(
int i=0; i<items.size(); ++i)
1702 QMap<qreal, qreal>
data;
1703 items.at(i)->curve()->getData(data);
1705 QVector<qreal> y(xAxis.size(), std::numeric_limits<qreal>::quiet_NaN());
1708 for(QList<qreal>::iterator iter=xAxis.begin(); iter!=xAxis.end(); ++iter)
1710 if(data.contains(*iter))
1712 y[j] = data.value(*iter);
1720 axes.push_front(xAxis.toVector());
1724 for(
int i=0; i<items.size(); ++i)
1726 text.append(items.at(i)->curve()->name());
1733 for(
int i=0; i<axes[0].size(); ++i)
1735 for(
int j=0; j<axes.size(); ++j)
1743 text.append(QString::number(axes[j][i],
'f'));
1750 if(i+1<axes[0].size())
1763 QAction * action =
_menu->exec(event->globalPos());
1773 QClipboard * clipboard = QApplication::clipboard();
1774 clipboard->setText(data);
1779 QList<UPlotLegendItem *> items = this->findChildren<UPlotLegendItem*>();
1780 for(
int i=0; i<items.size(); ++i)
1806 QLabel(text, parent),
1807 _orientation(orientation)
1817 QSize size = QLabel::sizeHint();
1826 QSize size = QLabel::minimumSizeHint();
1837 case Qt::Horizontal:
1838 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
1842 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
1853 case Qt::Horizontal:
1857 p.translate(-height(), 0);
1858 QSize size = r.size();
1863 p.drawText(r, this->alignment() | (this->wordWrap()?Qt::TextWordWrap:0), this->text());
1883 _graphicsViewHolder(0),
1887 _maxVisibleItems(-1),
1892 _workingDirectory(QDir::homePath()),
1893 _lowestRefreshRate(99),
1894 _autoScreenCaptureFormat(
"png"),
1895 _bgColor(Qt::white),
1907 _aAddVerticalLine(0),
1908 _aAddHorizontalLine(0),
1912 _aChangeBackgroundColor(0),
1913 _aYLabelVertical(0),
1914 _aShowRefreshRate(0),
1917 _aAutoScreenCapture(0),
1933 for(
int i=0; i<4; ++i)
1961 _view =
new QGraphicsView(
this);
1962 _view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1963 _view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1964 _view->setScene(
new QGraphicsScene(0,0,0,0,
this));
1965 _view->setStyleSheet(
"QGraphicsView { border-style: none; }" );
1967 _sceneRoot->setTransform(QTransform::fromTranslate(0, 0),
true);
1978 _title->setAlignment(Qt::AlignCenter);
1979 _xLabel->setAlignment(Qt::AlignCenter);
1980 _yLabel->setAlignment(Qt::AlignCenter);
1982 _title->setWordWrap(
true);
1985 _title->setVisible(
false);
1992 vLayout->setContentsMargins(0,0,0,0);
1993 vLayout->addWidget(
_view);
1995 QGridLayout * grid =
new QGridLayout(
this);
1996 grid->setContentsMargins(0,0,0,0);
1997 grid->addWidget(
_title, 0, 2);
1998 grid->addWidget(
_yLabel, 1, 0);
2002 grid->setColumnStretch(2, 1);
2003 grid->setRowStretch(1, 1);
2005 grid->addWidget(
_xLabel, 3, 2);
2006 grid->addWidget(
_legend, 1, 3);
2017 _aShowGrid =
new QAction(tr(
"Show grid"),
this);
2027 _aLimit0 =
new QAction(tr(
"No maximum items shown"),
this);
2028 _aLimit10 =
new QAction(tr(
"10"),
this);
2029 _aLimit50 =
new QAction(tr(
"50"),
this);
2051 _aSaveFigure =
new QAction(tr(
"Save figure..."),
this);
2054 _aClearData =
new QAction(tr(
"Clear data"),
this);
2056 QActionGroup * grpLimit =
new QActionGroup(
this);
2069 _menu =
new QMenu(tr(
"Plot"),
this);
2076 _menu->addSeparator()->setStatusTip(tr(
"Maximum items shown"));
2084 _menu->addSeparator();
2085 QMenu * addLineMenu =
_menu->addMenu(tr(
"Add line"));
2088 _menu->addSeparator();
2091 QMenu * yLabelMenu =
_menu->addMenu(tr(
"Y label"));
2097 _menu->addSeparator();
2123 ULOGGER_DEBUG(
"Adding curve \"%s\" to plot \"%s\"...", curve->
name().toStdString().c_str(), this->
title().toStdString().c_str());
2126 if(!qobject_cast<UPlotCurveThreshold*>(curve))
2128 for(
int i=
_curves.size()-1; i>=0; --i)
2130 if(!qobject_cast<UPlotCurveThreshold*>(
_curves.at(i)))
2142 if(ownershipTransferred)
2144 curve->setParent(
this);
2154 ULOGGER_DEBUG(
"Curve \"%s\" added to plot \"%s\"", curve->
name().toStdString().c_str(), this->
title().toStdString().c_str());
2169 for(QList<UPlotCurve*>::iterator iter =
_curves.begin(); iter!=
_curves.end(); ++iter)
2173 names.append((*iter)->name());
2181 for(QList<UPlotCurve*>::iterator iter =
_curves.begin(); iter!=
_curves.end(); ++iter)
2183 if(*iter && (*iter)->name().compare(curveName) == 0)
2194 bool colorNotUsed =
false;
2195 for(
int i=0; i<12; ++i)
2197 QColor tmp((Qt::GlobalColor)((penStyle+i) % 12 + 7 ));
2198 bool colorAlreadyUsed =
false;
2199 for(QList<UPlotCurve*>::const_iterator iter =
_curves.constBegin(); iter!=
_curves.constEnd() && !colorAlreadyUsed; ++iter)
2201 colorAlreadyUsed = (*iter)->pen().color() == tmp;
2203 if(!colorAlreadyUsed)
2205 colorNotUsed =
true;
2225 for(QList<UPlotCurve *>::iterator i=
_curves.begin(); i!=
_curves.end(); ++i)
2227 if((*i)->isVisible() && ((
UPlotCurve *)(*i))->itemsSize() > maxItem)
2239 qreal
axis[4] = {0};
2240 for(
int i=0; i<4; ++i)
2256 _view->scene()->setSceneRect(newRect);
2268 qreal w = newRect.width()-(borderHor*2);
2269 qreal h = newRect.height()-(borderVer*2);
2272 QPen dashPen(Qt::DashLine);
2274 QPen pen(dashPen.color());
2275 for(qreal i=0.0
f; i*stepV <= h+stepV; i+=5.0f)
2283 painter->setPen(pen);
2284 painter->drawLine(0, stepV*i+borderVer+0.5
f, borderHor, stepV*i+borderVer+0.5
f);
2286 painter->setPen(dashPen);
2287 painter->drawLine(borderHor, stepV*i+borderVer+0.5
f, w+borderHor, stepV*i+borderVer+0.5
f);
2289 painter->setPen(pen);
2290 painter->drawLine(w+borderHor, stepV*i+borderVer+0.5
f, w+borderHor*2, stepV*i+borderVer+0.5
f);
2296 hGridLines.append(
new QGraphicsLineItem(0, stepV*i+borderVer, borderHor, stepV*i+borderVer,
_sceneRoot));
2298 hGridLines.append(
new QGraphicsLineItem(borderHor, stepV*i+borderVer, w+borderHor, stepV*i+borderVer,
_sceneRoot));
2300 hGridLines.append(
new QGraphicsLineItem(w+borderHor, stepV*i+borderVer, w+borderHor*2, stepV*i+borderVer,
_sceneRoot));
2304 for(qreal i=0; i*stepH < w+stepH; i+=5.0f)
2312 painter->setPen(pen);
2313 painter->drawLine(stepH*i+borderHor+0.5
f, 0, stepH*i+borderHor+0.5
f, borderVer);
2315 painter->setPen(dashPen);
2316 painter->drawLine(stepH*i+borderHor+0.5
f, borderVer, stepH*i+borderHor+0.5
f, h+borderVer);
2318 painter->setPen(pen);
2319 painter->drawLine(stepH*i+borderHor+0.5
f, h+borderVer, stepH*i+borderHor+0.5
f, h+borderVer*2);
2325 vGridLines.append(
new QGraphicsLineItem(stepH*i+borderHor, 0, stepH*i+borderHor, borderVer,
_sceneRoot));
2327 vGridLines.append(
new QGraphicsLineItem(stepH*i+borderHor, borderVer, stepH*i+borderHor, h+borderVer,
_sceneRoot));
2329 vGridLines.append(
new QGraphicsLineItem(stepH*i+borderHor, h+borderVer, stepH*i+borderHor, h+borderVer*2,
_sceneRoot));
2339 den = axis[1] - axis[0];
2342 scaleX = (newRect.width()-(borderHor*2)) / den;
2344 den = axis[3] - axis[2];
2347 scaleY = (newRect.height()-(borderVer*2)) / den;
2349 for(QList<UPlotCurve *>::iterator i=
_curves.begin(); i!=
_curves.end(); ++i)
2351 if((*i)->isVisible())
2355 (*i)->update(scaleX,
2357 xDir<0?axis[1]+borderHor/scaleX:-(axis[0]-borderHor/scaleX),
2358 yDir<0?axis[3]+borderVer/scaleY:-(axis[2]-borderVer/scaleY),
2405 const QVector<qreal> & minMax = curve->
getMinMax();
2407 if(minMax.size() != 4)
2412 this->
updateAxis(minMax[0], minMax[1], minMax[2], minMax[3]);
2419 bool modified =
false;
2435 bool modified =
false;
2470 for(
int i=0; i<4; ++i)
2479 for(
int i=0; i<
_curves.size(); ++i)
2483 const QVector<qreal> & minMax =
_curves.at(i)->getMinMax();
2484 this->
updateAxis(minMax[0], minMax[1], minMax[2], minMax[3]);
2500 QPainter painter(
this);
2504 painter.setPen(QPen(Qt::NoPen));
2513 int left, top, right, bottom;
2534 painter.setPen(Qt::NoPen);
2537 painter.drawRect(0, top, left, bottom-top);
2545 QWidget::paintEvent(event);
2555 QWidget::resizeEvent(event);
2562 QWidget::mousePressEvent(event);
2569 if(!(QApplication::mouseButtons() & Qt::LeftButton))
2577 if(QApplication::mouseButtons() & Qt::LeftButton)
2585 if((QApplication::mouseButtons() & Qt::LeftButton) ||
2588 QToolTip::showText(event->globalPos(), QString(
"%1,%2").arg(x).arg(y));
2592 QToolTip::hideText();
2597 QToolTip::hideText();
2600 QWidget::mouseMoveEvent(event);
2607 int left,top,bottom,right;
2614 if(right - left > 5 || bottom - top > 5)
2620 UDEBUG(
"resize! new axis = [%f, %f, %f, %f]", axis[0], axis[1], axis[2], axis[3]);
2623 for(
int i=0; i<4; ++i)
2635 QWidget::mouseReleaseEvent(event);
2641 QWidget::mouseDoubleClickEvent(event);
2650 if(maxX == 0 || maxY == 0)
2659 else if(xPos > maxX)
2668 else if(yPos > maxY)
2689 QAction * action =
_menu->exec(event->globalPos());
2732 QString text = QInputDialog::getText(
this, action->text(), tr(
"New line name :"), QLineEdit::Normal,
"", &ok);
2733 while(ok && text.isEmpty())
2735 QMessageBox::warning(
this, action->text(), tr(
"The name is not valid or it is already used in this plot."));
2736 text = QInputDialog::getText(
this, action->text(), tr(
"New line name :"), QLineEdit::Normal,
"", &ok);
2749 double value = QInputDialog::getDouble(
this,
2751 tr(
"%1 value (min=%2, max=%3):").arg(axis).arg(min).arg(max),
2773 QString text =
_title->text();
2776 text = this->objectName();
2778 text = QInputDialog::getText(
this,
_aChangeTitle->text(), tr(
"Title :"), QLineEdit::Normal, text, &ok);
2787 QString text = QInputDialog::getText(
this,
_aChangeXLabel->text(), tr(
"X axis label :"), QLineEdit::Normal,
_xLabel->text(), &ok);
2796 QString text = QInputDialog::getText(
this,
_aChangeYLabel->text(), tr(
"Y axis label :"), QLineEdit::Normal,
_yLabel->text(), &ok);
2808 QColor color = QColorDialog::getColor(
_bgColor,
this);
2819 text = QFileDialog::getSaveFileName(
this, tr(
"Save figure to ..."), (QDir::homePath() +
"/") + this->
title() +
".png",
"*.png *.xpm *.jpg *.pdf *.svg");
2821 text = QFileDialog::getSaveFileName(
this, tr(
"Save figure to ..."), (QDir::homePath() +
"/") + this->
title() +
".png",
"*.png *.xpm *.jpg *.pdf");
2825 bool flatModified =
false;
2829 flatModified =
true;
2832 QPalette p(palette());
2834 QColor c = p.color(QPalette::Background);
2835 p.setColor(QPalette::Background, Qt::white);
2839 if(QFileInfo(text).suffix().compare(
"svg") == 0)
2841 QSvgGenerator generator;
2842 generator.setFileName(text);
2843 generator.setSize(this->size());
2845 painter.begin(&generator);
2846 this->render(&painter);
2852 if(QFileInfo(text).suffix().compare(
"pdf") == 0)
2855 printer.setOutputFormat(QPrinter::PdfFormat);
2856 printer.setOutputFileName(text);
2857 this->render(&printer);
2861 QPixmap figure = QPixmap::grabWidget(
this);
2868 p.setColor(QPalette::Background, c);
2902 ULOGGER_ERROR(
"The directory \"%s\" doesn't exist", workingDirectory.toStdString().c_str());
2914 if(!dir.exists(targetDir))
2916 dir.mkdir(targetDir);
2919 targetDir += this->
title().replace(
" ",
"_");
2920 if(!dir.exists(targetDir))
2922 dir.mkdir(targetDir);
2926 QPixmap figure = QPixmap::grabWidget(
this);
2927 figure.save(targetDir + name);
2933 items << QString(
"png") << QString(
"jpg");
2935 QString item = QInputDialog::getItem(
this, tr(
"Select format"), tr(
"Format:"), items, 0,
false, &ok);
2936 if(ok && !item.isEmpty())
2945 for(
int i=0; i<
_curves.size(); ++i)
2948 if(qobject_cast<UPlotCurveThreshold*>(
_curves.at(i)) == 0)
2958 if(!xAxis && !yAxis)
2964 for(
int i=0; i<
_curves.size(); ++i)
2966 if(qobject_cast<UPlotCurveThreshold*>(
_curves.at(i)) == 0)
2968 const QVector<qreal> & minMax =
_curves.at(i)->getMinMax();
2969 if(minMax.size() == 4)
2971 if(minMax[0] < minX)
2975 if(minMax[2] < minY)
2984 for(
int i=0; i<
_curves.size(); ++i)
2986 if(qobject_cast<UPlotCurveThreshold*>(
_curves.at(i)) == 0)
2991 for(
int j=0; j<x.size(); ++j)
3013 QPen pen = curve->
pen();
3033 _title->setVisible(!text.isEmpty());
3037 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
3044 _xLabel->setVisible(!text.isEmpty());
3048 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
3056 _yLabel->setVisible(!text.isEmpty());
3061 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
3071 for(QList<UPlotCurve*>::iterator iter=
_curves.begin(); iter!=
_curves.end(); ++iter)
3081 item->setZValue(1.0
f);
3091 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
3108 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
3115 this->setMouseTracking(tracking);
3121 _view->setVisible(on);
3133 if(maxVisibleItems <= 0)
3137 else if(maxVisibleItems == 10)
3141 else if(maxVisibleItems == 50)
3145 else if(maxVisibleItems == 100)
3149 else if(maxVisibleItems == 500)
3153 else if(maxVisibleItems == 1000)
3169 return _view->sceneRect();
3174 QList<UPlotCurve*> tmp =
_curves;
3175 for(QList<UPlotCurve*>::iterator iter=tmp.begin(); iter!=tmp.end(); ++iter)
3184 QList<UPlotCurve *>::iterator iter = qFind(
_curves.begin(),
_curves.end(), curve);
3186 ULOGGER_DEBUG(
"Plot=\"%s\" removing curve=\"%s\"", this->objectName().toStdString().c_str(), curve?curve->
name().toStdString().c_str():
"");
3194 if(!qobject_cast<UPlotCurveThreshold*>(c))
3197 for(
int i=
_curves.size()-1; i>=0; --i)
3199 if(!qobject_cast<UPlotCurveThreshold*>(
_curves.at(i)))
3207 if(c->parent() ==
this)
3218 QList<UPlotCurve *>::iterator iter = qFind(
_curves.begin(),
_curves.end(), curve);
3233 int currentIndex = -1;
3235 for(
int i=0; i<
_curves.size(); ++i)
3245 if(c && currentIndex != index)
3247 _curves.removeAt(currentIndex);
3248 QList<QGraphicsItem *> children =
_sceneRoot->childItems();
3250 if(currentIndex > index)
3252 children[currentIndex]->stackBefore(children[index]);
3256 if(currentIndex<children.size()-2)
3258 if(index < children.size()-1)
3260 children[index]->stackBefore(children[currentIndex]);
3264 children[currentIndex]->stackBefore(children[index]);
3267 if(currentIndex == children.size()-2 && currentIndex < index)
3269 children[index]->stackBefore(children[currentIndex]);
QString _autoScreenCaptureFormat
void setXStart(qreal val)
QPointF getItemData(int index)
QString getAllCurveDataAsText() const
T uVariance(const T *v, unsigned int size, T meanV)
QGraphicsTextItem * _text
virtual void contextMenuEvent(QContextMenuEvent *event)
void setOrientation(Qt::Orientation orientation)
void redirectToggled(bool)
UPlotCurveThreshold * addThreshold(const QString &name, qreal value, Qt::Orientation orientation=Qt::Horizontal)
QGraphicsItem * _sceneRoot
UPlotAxis * _verticalAxis
virtual void update(qreal scaleX, qreal scaleY, qreal offsetX, qreal offsetY, qreal xDir, qreal yDir, int maxItemsKept)
QList< UPlotCurve * > _curves
T uMean(const T *v, unsigned int size)
virtual ~UPlotCurveThreshold()
void showGrid(bool shown)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
void setFixedXAxis(qreal x1, qreal x2)
virtual void contextMenuEvent(QContextMenuEvent *event)
UPlotCurveThreshold(const QString &name, qreal thesholdValue, Qt::Orientation orientation=Qt::Horizontal, QObject *parent=0)
const QBrush & brush() const
int removeItem(int index)
void moveDownRequest(UPlotLegendItem *)
virtual void hoverEnterEvent(QGraphicsSceneHoverEvent *event)
GLM_FUNC_DECL vecType< T, P > sqrt(vecType< T, P > const &x)
void setBrush(const QBrush &brush)
QGraphicsRectItem * _textBackground
GLM_FUNC_DECL detail::tvec3< T, P > axis(detail::tquat< T, P > const &x)
void updateStdDevMeanMax()
QAction * _aAddVerticalLine
virtual void mouseReleaseEvent(QMouseEvent *event)
UPlotItem * _previousItem
const UPlotCurve * curve() const
QAction * _aShowStdDevMeanMax
virtual ~UOrientableLabel()
virtual void contextMenuEvent(QContextMenuEvent *event)
virtual bool isMinMaxValid() const
Basic mathematics functions.
void setThreshold(qreal threshold)
void showRefreshRate(bool shown)
QAction * _aMouseTracking
UOrientableLabel * _yLabel
void addValue(UPlotItem *data)
QWidget * _graphicsViewHolder
void moveCurve(const UPlotCurve *, int index)
Qt::Orientation _orientation
static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv)
QTime _refreshIntervalTime
QAction * _aChangeBackgroundColor
virtual void mouseDoubleClickEvent(QMouseEvent *event)
void setPen(const QPen &pen)
void setData(QVector< UPlotItem *> &data)
Qt::Orientation orientation() const
void init(qreal dataX, qreal dataY)
void showStdDevMeanMax(bool shown)
QString _workingDirectory
virtual void mousePressEvent(QMouseEvent *event)
QAction * _aCopyAllCurvesToClipboard
void legendItemMoved(const UPlotCurve *curve, int)
void getData(QVector< qreal > &x, QVector< qreal > &y) const
QPen getRandomPenColored()
UPlotAxis * _horizontalAxis
QString getAllCurveDataAsText() const
virtual void showDescription(bool shown)
bool remove(const UPlotCurve *curve)
void trackMouse(bool tracking)
void removeLegendItem(const UPlotCurve *curve)
virtual void paintEvent(QPaintEvent *event)
void setVisible(bool visible)
#define ULOGGER_DEBUG(...)
Qt::Orientation _orientation
void setOrientation(Qt::Orientation orientation)
UPlotCurve * addCurve(const QString &curveName, const QColor &color=QColor())
const QVector< qreal > & getMinMax() const
QScrollArea * _scrollArea
QAction * _aShowRefreshRate
void removeCurve(const UPlotCurve *curve)
UPlotItem(qreal dataX, qreal dataY, qreal width=2)
void setGraphicsView(bool on)
void setFixedYAxis(qreal y1, qreal y2)
QAction * _aAddHorizontalLine
void addItem(UPlotCurve *curve)
QPixmap createSymbol(const QPen &pen, const QBrush &brush)
virtual void mouseMoveEvent(QMouseEvent *event)
void _addValue(UPlotItem *data)
bool mousePosToValue(const QPoint &pos, qreal &x, qreal &y)
void legendItemRemoved(const UPlotCurve *)
virtual ~UPlotLegendItem()
QAction * _aShowAllStdDevMeanMax
UPlotLegend(QWidget *parent=0)
QSize minimumSizeHint() const
virtual void keyReleaseEvent(QKeyEvent *keyEvent)
QList< QGraphicsItem * > _items
virtual void resizeEvent(QResizeEvent *event)
void moveDown(UPlotLegendItem *item)
void setAxis(qreal &min, qreal &max)
QAction * _aYLabelVertical
T uMax(const T *v, unsigned int size, unsigned int &index)
QGraphicsRectItem * _rootItem
bool contains(const QString &curveName)
void setItemsColor(const QColor &color)
UOrientableLabel(const QString &text, Qt::Orientation orientation=Qt::Horizontal, QWidget *parent=0)
void keepAllData(bool kept)
void setXLabel(const QString &text)
QList< QGraphicsLineItem * > vGridLines
QAction * _aCopyToClipboard
virtual void update(qreal scaleX, qreal scaleY, qreal offsetX, qreal offsetY, qreal xDir, qreal yDir, int maxItemsKept)
QAction * _aAutoScreenCapture
GLM_FUNC_DECL genType max(genType const &x, genType const &y)
void selectScreenCaptureFormat()
void setTitle(const QString &text)
virtual void paintEvent(QPaintEvent *event)
virtual void focusOutEvent(QFocusEvent *event)
#define ULOGGER_WARN(...)
ULogger class and convenient macros.
void legendItemRemoved(const UPlotCurve *curve)
void moveUpRequest(UPlotLegendItem *)
UPlotItem * nextItem() const
UPlotItem * previousItem() const
void setData(const QPointF &data)
void setMaxVisibleItems(int maxVisibleItems)
const QPointF & data() const
void setBackgroundColor(const QColor &color)
void draw(QPainter *painter, const QRect &limits)
virtual void focusInEvent(QFocusEvent *event)
bool uIsNan(const T &value)
void addItem(QGraphicsItem *item)
QAction * _aUseFlatButtons
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
void replot(QPainter *painter)
virtual void paintEvent(QPaintEvent *event)
void showLegend(bool shown)
void dataChanged(const UPlotCurve *)
GLM_FUNC_DECL genType::value_type length(genType const &x)
UPlotCurve(const QString &name, QObject *parent=0)
#define ULOGGER_ERROR(...)
void setYLabel(const QString &text, Qt::Orientation orientation=Qt::Vertical)
void showCurve(const UPlotCurve *curve, bool shown)
void setReversed(bool reversed)
UPlotLegendItem(UPlotCurve *curve, QWidget *parent=0)
void setNextItem(UPlotItem *nextItem)
QList< QGraphicsLineItem * > hGridLines
void addValues(QVector< UPlotItem *> &data)
UPlotAxis(Qt::Orientation orientation=Qt::Horizontal, qreal min=0, qreal max=1, QWidget *parent=0)
Qt::Orientation _orientation
void setWorkingDirectory(const QString &workingDirectory)
GLM_FUNC_DECL detail::tmat4x4< T, P > orientation(detail::tvec3< T, P > const &Normal, detail::tvec3< T, P > const &Up)
void legendItemToggled(const UPlotCurve *curve, bool toggled)
void setXIncrement(qreal increment)
void setPreviousItem(UPlotItem *previousItem)
void moveUp(UPlotLegendItem *item)
void frameData(bool xAxis=true, bool yAxis=false)