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> 39 #include <QInputDialog> 40 #include <QMessageBox> 41 #include <QFileDialog> 42 #include <QtGui/QClipboard> 43 #include <QApplication> 45 #include <QColorDialog> 48 #include <QtSvg/QSvgGenerator> 55 QGraphicsEllipseItem(0, 0, width, width, 0),
61 this->
init(dataX, dataY);
65 QGraphicsEllipseItem(0, 0, width, width, 0),
71 this->
init(data.x(), data.y());
78 this->setAcceptHoverEvents(
true);
79 this->setFlag(QGraphicsItem::ItemIsFocusable,
true);
141 if(this->parentItem() && this->parentItem() !=
_textBackground->parentItem())
147 if(this->scene() && shown)
152 this->setPen(QPen(this->pen().color(), 2));
154 QRectF rect = this->scene()->sceneRect();
155 QPointF p = this->pos();
156 QRectF br =
_text->boundingRect();
160 if(p.x() - br.width() < 0)
164 else if(p.x() > rect.width())
166 p.setX(rect.width() - br.width());
170 p.setX(p.x() - br.width());
173 if(p.y() - br.height() < 0)
179 p.setY(p.y() - br.height());
186 this->setPen(QPen(this->pen().color(), 1));
194 QGraphicsEllipseItem::hoverEnterEvent(event);
199 if(!this->hasFocus())
203 QGraphicsEllipseItem::hoverLeaveEvent(event);
209 QGraphicsEllipseItem::focusInEvent(event);
215 QGraphicsEllipseItem::focusOutEvent(event);
221 if(keyEvent->key() == Qt::Key_Right)
224 while(next && !next->isVisible())
228 if(next && next->isVisible())
234 else if(keyEvent->key() == Qt::Key_Left)
237 while(previous && !previous->isVisible())
241 if(previous && previous->isVisible())
244 previous->setFocus();
247 QGraphicsEllipseItem::keyReleaseEvent(keyEvent);
262 _itemsColor(0,0,0,150)
310 if(!plot || plot ==
_plot)
325 ULOGGER_DEBUG(
"curve=\"%s\" from plot=\"%s\"", this->objectName().toStdString().c_str(), plot?plot->objectName().toStdString().c_str():
"");
327 if(plot &&
_plot == plot)
349 for(
int i=0; i<
_items.size(); ++i)
354 x = item->
data().x();
355 y = item->
data().y();
379 float x = data->
data().x();
380 float y = data->
data().y();
389 QGraphicsLineItem * line =
new QGraphicsLineItem(
_rootItem);
391 line->setVisible(
false);
409 data->setVisible(
false);
410 QPen
pen = data->pen();
436 UWARN(
"New value (%f) added to curve \"%s\" is smaller " 437 "than the last added (%f). Clearing the curve.",
464 float v = value.toFloat(&ok);
471 ULOGGER_ERROR(
"Value not valid, must be a number, received %s", value.toStdString().c_str());
477 for(
int i=0; i<data.size(); ++i)
487 for(
int i=0; i<xs.size() && i<ys.size(); ++i)
498 for(
int i=0; i<ys.size(); ++i)
518 for(
int i=0; i<ys.size(); ++i)
538 for(
unsigned int i=0; i<ys.size(); ++i)
558 for(
unsigned int i=0; i<ys.size(); ++i)
576 if(index >= 0 && index <
_items.size())
581 delete _items.takeAt(index);
585 delete _items.takeAt(index+1);
597 float x = tmp->
data().x();
598 float y = tmp->
data().y();
603 for(
int i = 2; i<
_items.size(); i+=2)
628 for(
int i=0; i<
_items.size(); ++i)
643 item->scene()->removeItem(item);
662 for(
int i=1; i<
_items.size(); i+=2)
679 for(
int i=0; i<
_items.size(); i+=2)
688 void UPlotCurve::update(
float scaleX,
float scaleY,
float offsetX,
float offsetY,
float xDir,
float yDir,
int maxItemsKept)
692 xDir<0?xDir=-1:xDir=1;
693 yDir<0?yDir=-1:yDir=1;
697 for(
int i=
_items.size()-1; i>=0; --i)
704 if(maxItemsKept == 0 || j <= maxItemsKept)
707 if(!item->isVisible())
711 item->setVisible(
false);
721 QPointF newPos(((xDir*item->
data().x()+offsetX)*scaleX-item->rect().width()/2.0f),
722 ((yDir*item->
data().y()+offsetY)*scaleY-item->rect().width()/2.0f));
723 if(!item->isVisible())
725 item->setVisible(
true);
727 item->setPos(newPos);
735 _items.at(i)->setVisible(
false);
741 QGraphicsLineItem * lineItem = (QGraphicsLineItem *)
_items.at(i);
742 lineItem->setLine((xDir*from->
data().x()+offsetX)*scaleX,
743 (yDir*from->
data().y()+offsetY)*scaleY,
744 (xDir*to->
data().x()+offsetX)*scaleX,
745 (yDir*to->
data().y()+offsetY)*scaleY);
746 if(!lineItem->isVisible())
748 lineItem->setVisible(
true);
752 QLineF line = lineItem->line();
753 if((line.x1() <= line.x2() && line.x2() < 0-((line.x2() - line.x1()))) ||
754 (line.x1() > line.x2() && line.x2() > lineItem->scene()->sceneRect().width() + ((line.x1() - line.x2()))))
769 for(
int i=
_items.size()-1; i>=0 &&
_items.at(i)->isVisible(); i-=2)
773 int x = (int)item->x();
783 const QGraphicsLineItem * lineItem = (
const QGraphicsLineItem *)
_items.at(i-1);
784 QLine line = lineItem->line().toLine();
785 if(limits.contains(line.p1()) || limits.contains(line.p2()))
788 QLineF::IntersectType type;
789 type = lineItem->line().intersect(QLineF(limits.topLeft(), limits.bottomLeft()), &intersection);
790 if(type == QLineF::BoundedIntersection)
792 !limits.contains(line.p1())?line.setP1(intersection.toPoint()):line.setP2(intersection.toPoint());
796 type = lineItem->line().intersect(QLineF(limits.topLeft(), limits.topRight()), &intersection);
797 if(type == QLineF::BoundedIntersection)
799 !limits.contains(line.p1())?line.setP1(intersection.toPoint()):line.setP2(intersection.toPoint());
803 type = lineItem->line().intersect(QLineF(limits.bottomLeft(), limits.bottomRight()), &intersection);
804 if(type == QLineF::BoundedIntersection)
806 !limits.contains(line.p1())?line.setP1(intersection.toPoint()):line.setP2(intersection.toPoint());
810 type = lineItem->line().intersect(QLineF(limits.topRight(), limits.bottomRight()), &intersection);
811 if(type == QLineF::BoundedIntersection)
813 !limits.contains(line.p1())?line.setP1(intersection.toPoint()):line.setP2(intersection.toPoint());
819 painter->setPen(this->
pen());
820 painter->setBrush(this->
brush());
821 painter->drawLine(line);
846 if(index>=0 && index <
_items.size() && index % 2 == 0 )
860 for(
int i=0; i<
_items.size(); ++i)
862 _items.at(i)->setVisible(visible);
879 for(
int i = 0; i<data.size(); ++i)
887 if(x.size() == y.size())
890 int margin = int((
_items.size()+1)/2) - x.size();
905 QVector<float>::const_iterator i=x.begin();
906 QVector<float>::const_iterator j=y.begin();
907 for(; i!=x.end() && j!=y.end(); ++i, ++j, index+=2)
916 else if(y.size()>0 && x.size()==0)
928 if(x.size() == y.size())
931 int margin = int((
_items.size()+1)/2) - int(x.size());
946 std::vector<float>::const_iterator i=x.begin();
947 std::vector<float>::const_iterator j=y.begin();
948 for(; i!=x.end() && j!=y.end(); ++i, ++j, index+=2)
957 else if(y.size()>0 && x.size()==0)
969 this->
setData(y.toStdVector());
975 int margin = int((
_items.size()+1)/2) - int(y.size());
991 std::vector<float>::const_iterator j=y.begin();
992 for(; j!=y.end(); ++j, index+=2)
1008 x.resize((
_items.size()-1)/2+1);
1011 for(
int i=0; i<
_items.size(); i+=2)
1024 for(
int i=0; i<
_items.size(); i+=2)
1037 _orientation(orientation)
1067 item->
setData(QPointF(item->
data().x(), threshold));
1069 item->
setData(QPointF(item->
data().x(), threshold));
1074 item->
setData(QPointF(threshold, item->
data().y()));
1076 item->
setData(QPointF(threshold, item->
data().y()));
1081 ULOGGER_ERROR(
"A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)");
1100 ULOGGER_ERROR(
"A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)");
1116 item->
setData(QPointF(-(offsetX-item->rect().width()/scaleX)/xDir, item->
data().y()));
1118 item->
setData(QPointF( (
_plot->
sceneRect().width()/scaleX-(offsetX+item->rect().width()/scaleX))/xDir, item->
data().y()));
1123 item->
setData(QPointF(item->
data().x(), -(offsetY-item->rect().height()/scaleY)/yDir));
1125 item->
setData(QPointF(item->
data().x(), (
_plot->
sceneRect().height()/scaleY-(offsetY+item->rect().height()/scaleY))/yDir));
1132 ULOGGER_ERROR(
"A threshold must has only 3 items (1 PlotItem + 1 QGraphicsLineItem + 1 PlotItem)");
1155 this->setMinimumSize(15, 25);
1157 this->setMinimumSize(15, 25);
1187 borderMin = borderMax = this->fontMetrics().height()/2;
1194 int border = borderMin>borderMax?borderMin:borderMax;
1199 length = (this->height()-border*2);
1203 length = (this->width()-border*2);
1210 else if(length <= 175)
1214 else if(length <= 350)
1218 else if(length <= 700)
1222 else if(length <= 1000)
1226 else if(length <= 1300)
1239 float rangef = max -
min;
1242 for(
int i=0; i<6; ++i)
1244 val = (rangef/float(countStep)) * mul;
1245 if( val >= 1.0
f && val < 10.0
f)
1259 int minR = min*mul-0.9;
1260 int maxR = max*mul+0.9;
1261 min = float(minR)/mul;
1262 max = float(maxR)/mul;
1286 if(borderDelta%2 != 0)
1291 _border = border + borderDelta/2;
1297 for (
int i = 0; i <=
_count; i+=5)
1300 if(this->fontMetrics().width(n) > minWidth)
1302 minWidth = this->fontMetrics().width(n);
1305 this->setMinimumWidth(15+minWidth);
1311 QPainter painter(
this);
1314 painter.translate(0,
_border);
1315 for (
int i = 0; i <=
_count; ++i)
1319 painter.drawLine(this->width(), 0, this->width()-10, 0);
1321 painter.drawText(this->width()-(12+n.sizeHint().width()), n.sizeHint().height()/2-2, n.text());
1325 painter.drawLine(this->width(), 0, this->width()-5, 0);
1327 painter.translate(0,
_step);
1332 painter.translate(
_border, 0);
1333 for (
int i = 0; i <=
_count; ++i)
1337 painter.drawLine(0, 0, 0, 10);
1339 painter.drawText(-(n.sizeHint().width()/2)+1, 22, n.text());
1343 painter.drawLine(0, 0, 0, 5);
1345 painter.translate(
_step, 0);
1354 QPushButton(parent),
1357 QString nameSpaced = curve->
name();
1358 nameSpaced.replace(
'_',
' ');
1359 this->setText(nameSpaced);
1362 this->setIconSize(QSize(25,20));
1364 _aChangeText =
new QAction(tr(
"Change text..."),
this);
1365 _aResetText =
new QAction(tr(
"Reset text..."),
this);
1368 _aShowStdDev =
new QAction(tr(
"Show std deviation"),
this);
1370 _aMoveUp =
new QAction(tr(
"Move up"),
this);
1371 _aMoveDown =
new QAction(tr(
"Move down"),
this);
1373 _menu =
new QMenu(tr(
"Curve"),
this);
1379 _menu->addSeparator();
1382 _menu->addSeparator();
1392 QAction * action =
_menu->exec(event->globalPos());
1396 QString text = QInputDialog::getText(
this,
_aChangeText->text(), tr(
"Name :"), QLineEdit::Normal, this->text(), &ok);
1397 if(ok && !text.isEmpty())
1399 this->setText(text);
1414 QColor color = QColorDialog::getColor(pen.color(),
this);
1417 pen.setColor(color);
1432 for(
int i=0; i<x.size(); ++i)
1434 textX.append(QString::number(x[i]));
1435 textY.append(QString::number(y[i]));
1442 QClipboard * clipboard = QApplication::clipboard();
1443 clipboard->setText((textX+
"\n")+textY);
1456 nameSpaced.replace(
'_',
' ');
1457 this->setText(nameSpaced);
1476 QPixmap pixmap(50, 50);
1477 pixmap.fill(Qt::transparent);
1478 QPainter painter(&pixmap);
1482 painter.drawLine(0.0, 25.0, 50.0, 25.0);
1488 QVector<float> x, y;
1492 nameSpaced.replace(
'_',
' ');
1493 nameSpaced += QString(
" (%1=%2)").arg(QChar(0xc3, 0x03)).arg(stdDev);
1494 this->setText(nameSpaced);
1511 _menu =
new QMenu(tr(
"Legend"),
this);
1515 QVBoxLayout * vLayout =
new QVBoxLayout(
this);
1516 vLayout->setContentsMargins(0,0,0,0);
1517 this->setLayout(vLayout);
1518 vLayout->addStretch(0);
1519 vLayout->setSpacing(0);
1534 QList<UPlotLegendItem*> items = this->findChildren<UPlotLegendItem*>();
1535 for(
int i=0; i<items.size(); ++i)
1537 items.at(i)->setFlat(
_flat);
1538 items.at(i)->setChecked(!items.at(i)->isChecked());
1549 legendItem->setAutoDefault(
false);
1550 legendItem->setFlat(
_flat);
1551 legendItem->setCheckable(
true);
1552 legendItem->setChecked(
false);
1553 connect(legendItem, SIGNAL(toggled(
bool)),
this, SLOT(
redirectToggled(
bool)));
1559 QHBoxLayout * hLayout =
new QHBoxLayout();
1560 hLayout->addWidget(legendItem);
1561 hLayout->addStretch(0);
1562 hLayout->setMargin(0);
1565 ((QVBoxLayout*)this->layout())->insertLayout(this->layout()->count()-1, hLayout);
1571 QList<UPlotLegendItem *> items = this->findChildren<UPlotLegendItem*>();
1572 for(
int i=0; i<items.size(); ++i)
1574 if(items.at(i)->curve() == curve)
1585 if(this->
remove(curve))
1594 QLayoutItem * layoutItem = 0;
1595 for(
int i=0; i<this->layout()->count(); ++i)
1597 if(this->layout()->itemAt(i)->layout() &&
1598 this->layout()->itemAt(i)->layout()->indexOf(item) != -1)
1600 layoutItem = this->layout()->itemAt(i);
1605 if(index > 0 && layoutItem)
1607 this->layout()->removeItem(layoutItem);
1608 QHBoxLayout * hLayout =
new QHBoxLayout();
1609 hLayout->addWidget(layoutItem->layout()->itemAt(0)->widget());
1610 hLayout->addStretch(0);
1611 hLayout->setMargin(0);
1612 ((QVBoxLayout*)this->layout())->insertLayout(index-1, hLayout);
1621 QLayoutItem * layoutItem = 0;
1622 for(
int i=0; i<this->layout()->count(); ++i)
1624 if(this->layout()->itemAt(i)->layout() &&
1625 this->layout()->itemAt(i)->layout()->indexOf(item) != -1)
1627 layoutItem = this->layout()->itemAt(i);
1632 if(index < this->layout()->count()-2 && layoutItem)
1634 this->layout()->removeItem(layoutItem);
1635 QHBoxLayout * hLayout =
new QHBoxLayout();
1636 hLayout->addWidget(layoutItem->layout()->itemAt(0)->widget());
1637 hLayout->addStretch(0);
1638 hLayout->setMargin(0);
1639 ((QVBoxLayout*)this->layout())->insertLayout(index+1, hLayout);
1647 QAction * action =
_menu->exec(event->globalPos());
1654 QList<UPlotLegendItem *> items = this->findChildren<UPlotLegendItem*>();
1657 QMap<float,float> firstData;
1658 QVector<QVector<float> > axes;
1659 for(
int i=0; i<items.size(); ++i)
1661 QMap<float, float> data;
1662 items.at(i)->curve()->getData(data);
1670 QVector<float> y(firstData.size(), 0.0f);
1673 for(QMap<float,float>::iterator iter=firstData.begin(); iter!=firstData.end(); ++iter)
1675 if(data.contains(iter.key()))
1677 y[j] = data.value(iter.key());
1684 if(firstData.size())
1686 axes.push_front(firstData.values().toVector());
1687 axes.push_front(firstData.keys().toVector());
1689 for(
int i=0; i<axes.size(); ++i)
1691 for(
int j=0; j<axes[i].size(); ++j)
1693 text.append(QString::number(axes[i][j]));
1694 if(j+1<axes[i].size())
1704 QClipboard * clipboard = QApplication::clipboard();
1705 clipboard->setText(text);
1730 QLabel(text, parent),
1731 _orientation(orientation)
1741 QSize size = QLabel::sizeHint();
1750 QSize size = QLabel::minimumSizeHint();
1761 case Qt::Horizontal:
1762 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
1766 setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
1777 case Qt::Horizontal:
1781 p.translate(-height(), 0);
1782 QSize size = r.size();
1787 p.drawText(r, this->alignment() | (this->wordWrap()?Qt::TextWordWrap:0), this->text());
1804 _maxVisibleItems(-1),
1805 _autoScreenCaptureFormat(
"png"),
1820 for(
int i=0; i<4; ++i)
1852 _view =
new QGraphicsView(
this);
1853 _view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1854 _view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1855 _view->setScene(
new QGraphicsScene(0,0,0,0,
this));
1856 _view->setStyleSheet(
"QGraphicsView { border-style: none; }" );
1858 _sceneRoot->setTransform(QTransform::fromTranslate(0, 0),
true);
1869 _title->setAlignment(Qt::AlignCenter);
1870 _xLabel->setAlignment(Qt::AlignCenter);
1871 _yLabel->setAlignment(Qt::AlignCenter);
1873 _title->setWordWrap(
true);
1876 _title->setVisible(
false);
1883 vLayout->setContentsMargins(0,0,0,0);
1884 vLayout->addWidget(
_view);
1886 QGridLayout * grid =
new QGridLayout(
this);
1887 grid->setContentsMargins(0,0,0,0);
1888 grid->addWidget(
_title, 0, 2);
1889 grid->addWidget(
_yLabel, 1, 0);
1893 grid->setColumnStretch(2, 1);
1894 grid->setRowStretch(1, 1);
1896 grid->addWidget(
_xLabel, 3, 2);
1897 grid->addWidget(
_legend, 1, 3);
1908 _aShowGrid =
new QAction(tr(
"Show grid"),
this);
1918 _aLimit0 =
new QAction(tr(
"No maximum items shown"),
this);
1919 _aLimit10 =
new QAction(tr(
"10"),
this);
1920 _aLimit50 =
new QAction(tr(
"50"),
this);
1942 _aSaveFigure =
new QAction(tr(
"Save figure..."),
this);
1945 _aClearData =
new QAction(tr(
"Clear data"),
this);
1947 QActionGroup * grpLimit =
new QActionGroup(
this);
1960 _menu =
new QMenu(tr(
"Plot"),
this);
1967 _menu->addSeparator()->setStatusTip(tr(
"Maximum items shown"));
1975 _menu->addSeparator();
1976 QMenu * addLineMenu =
_menu->addMenu(tr(
"Add line"));
1979 _menu->addSeparator();
1982 QMenu * yLabelMenu =
_menu->addMenu(tr(
"Y label"));
1988 _menu->addSeparator();
2014 ULOGGER_DEBUG(
"Adding curve \"%s\" to plot \"%s\"...", curve->
name().toStdString().c_str(), this->
title().toStdString().c_str());
2017 if(!qobject_cast<UPlotCurveThreshold*>(curve))
2019 for(
int i=
_curves.size()-1; i>=0; --i)
2021 if(!qobject_cast<UPlotCurveThreshold*>(
_curves.at(i)))
2033 if(ownershipTransferred)
2035 curve->setParent(
this);
2045 ULOGGER_DEBUG(
"Curve \"%s\" added to plot \"%s\"", curve->
name().toStdString().c_str(), this->
title().toStdString().c_str());
2060 for(QList<UPlotCurve*>::iterator iter =
_curves.begin(); iter!=
_curves.end(); ++iter)
2064 names.append((*iter)->name());
2072 for(QList<UPlotCurve*>::iterator iter =
_curves.begin(); iter!=
_curves.end(); ++iter)
2074 if(*iter && (*iter)->name().compare(curveName) == 0)
2085 bool colorNotUsed =
false;
2086 for(
int i=0; i<12; ++i)
2088 QColor tmp((Qt::GlobalColor)((penStyle+i) % 12 + 7 ));
2089 bool colorAlreadyUsed =
false;
2090 for(QList<UPlotCurve*>::const_iterator iter =
_curves.constBegin(); iter!=
_curves.constEnd() && !colorAlreadyUsed; ++iter)
2092 colorAlreadyUsed = (*iter)->pen().color() == tmp;
2094 if(!colorAlreadyUsed)
2096 colorNotUsed =
true;
2116 for(QList<UPlotCurve *>::iterator i=
_curves.begin(); i!=
_curves.end(); ++i)
2118 if((*i)->isVisible() && ((
UPlotCurve *)(*i))->itemsSize() > maxItem)
2130 float axis[4] = {0};
2131 for(
int i=0; i<4; ++i)
2147 _view->scene()->setSceneRect(newRect);
2159 float w = newRect.width()-(borderHor*2);
2160 float h = newRect.height()-(borderVer*2);
2163 QPen dashPen(Qt::DashLine);
2165 QPen pen(dashPen.color());
2166 for(
float i=0.0
f; i*stepV <= h+stepV; i+=5.0f)
2174 painter->setPen(pen);
2175 painter->drawLine(0, stepV*i+borderVer+0.5
f, borderHor, stepV*i+borderVer+0.5
f);
2177 painter->setPen(dashPen);
2178 painter->drawLine(borderHor, stepV*i+borderVer+0.5
f, w+borderHor, stepV*i+borderVer+0.5
f);
2180 painter->setPen(pen);
2181 painter->drawLine(w+borderHor, stepV*i+borderVer+0.5
f, w+borderHor*2, stepV*i+borderVer+0.5
f);
2187 hGridLines.append(
new QGraphicsLineItem(0, stepV*i+borderVer, borderHor, stepV*i+borderVer,
_sceneRoot));
2189 hGridLines.append(
new QGraphicsLineItem(borderHor, stepV*i+borderVer, w+borderHor, stepV*i+borderVer,
_sceneRoot));
2191 hGridLines.append(
new QGraphicsLineItem(w+borderHor, stepV*i+borderVer, w+borderHor*2, stepV*i+borderVer,
_sceneRoot));
2195 for(
float i=0; i*stepH < w+stepH; i+=5.0f)
2203 painter->setPen(pen);
2204 painter->drawLine(stepH*i+borderHor+0.5
f, 0, stepH*i+borderHor+0.5
f, borderVer);
2206 painter->setPen(dashPen);
2207 painter->drawLine(stepH*i+borderHor+0.5
f, borderVer, stepH*i+borderHor+0.5
f, h+borderVer);
2209 painter->setPen(pen);
2210 painter->drawLine(stepH*i+borderHor+0.5
f, h+borderVer, stepH*i+borderHor+0.5
f, h+borderVer*2);
2216 vGridLines.append(
new QGraphicsLineItem(stepH*i+borderHor, 0, stepH*i+borderHor, borderVer,
_sceneRoot));
2218 vGridLines.append(
new QGraphicsLineItem(stepH*i+borderHor, borderVer, stepH*i+borderHor, h+borderVer,
_sceneRoot));
2220 vGridLines.append(
new QGraphicsLineItem(stepH*i+borderHor, h+borderVer, stepH*i+borderHor, h+borderVer*2,
_sceneRoot));
2230 den = axis[1] - axis[0];
2233 scaleX = (newRect.width()-(borderHor*2)) / den;
2235 den = axis[3] - axis[2];
2238 scaleY = (newRect.height()-(borderVer*2)) / den;
2240 for(QList<UPlotCurve *>::iterator i=
_curves.begin(); i!=
_curves.end(); ++i)
2242 if((*i)->isVisible())
2246 (*i)->update(scaleX,
2248 xDir<0?axis[1]+borderHor/scaleX:-(axis[0]-borderHor/scaleX),
2249 yDir<0?axis[3]+borderVer/scaleY:-(axis[2]-borderVer/scaleY),
2296 const QVector<float> & minMax = curve->
getMinMax();
2298 if(minMax.size() != 4)
2303 this->
updateAxis(minMax[0], minMax[1], minMax[2], minMax[3]);
2310 bool modified =
false;
2326 bool modified =
false;
2361 for(
int i=0; i<4; ++i)
2370 for(
int i=0; i<
_curves.size(); ++i)
2374 const QVector<float> & minMax =
_curves.at(i)->getMinMax();
2375 this->
updateAxis(minMax[0], minMax[1], minMax[2], minMax[3]);
2391 QPainter painter(
this);
2395 painter.setPen(QPen(Qt::NoPen));
2404 int left, top, right, bottom;
2425 painter.setPen(Qt::NoPen);
2428 painter.drawRect(0, top, left, bottom-top);
2436 QWidget::paintEvent(event);
2446 QWidget::resizeEvent(event);
2453 QWidget::mousePressEvent(event);
2460 if(!(QApplication::mouseButtons() & Qt::LeftButton))
2468 if(QApplication::mouseButtons() & Qt::LeftButton)
2476 if((QApplication::mouseButtons() & Qt::LeftButton) ||
2479 QToolTip::showText(event->globalPos(), QString(
"%1,%2").arg(x).arg(y));
2483 QToolTip::hideText();
2488 QToolTip::hideText();
2491 QWidget::mouseMoveEvent(event);
2498 int left,top,bottom,right;
2505 if(right - left > 5 || bottom - top > 5)
2511 UDEBUG(
"resize! new axis = [%f, %f, %f, %f]", axis[0], axis[1], axis[2], axis[3]);
2514 for(
int i=0; i<4; ++i)
2526 QWidget::mouseReleaseEvent(event);
2532 QWidget::mouseDoubleClickEvent(event);
2541 if(maxX == 0 || maxY == 0)
2550 else if(xPos > maxX)
2559 else if(yPos > maxY)
2580 QAction * action =
_menu->exec(event->globalPos());
2623 QString text = QInputDialog::getText(
this, action->text(), tr(
"New line name :"), QLineEdit::Normal,
"", &ok);
2624 while(ok && text.isEmpty())
2626 QMessageBox::warning(
this, action->text(), tr(
"The name is not valid or it is already used in this plot."));
2627 text = QInputDialog::getText(
this, action->text(), tr(
"New line name :"), QLineEdit::Normal,
"", &ok);
2640 double value = QInputDialog::getDouble(
this,
2642 tr(
"%1 value (min=%2, max=%3):").arg(axis).arg(min).arg(max),
2664 QString text =
_title->text();
2667 text = this->objectName();
2669 text = QInputDialog::getText(
this,
_aChangeTitle->text(), tr(
"Title :"), QLineEdit::Normal, text, &ok);
2678 QString text = QInputDialog::getText(
this,
_aChangeXLabel->text(), tr(
"X axis label :"), QLineEdit::Normal,
_xLabel->text(), &ok);
2687 QString text = QInputDialog::getText(
this,
_aChangeYLabel->text(), tr(
"Y axis label :"), QLineEdit::Normal,
_yLabel->text(), &ok);
2699 QColor color = QColorDialog::getColor(
_bgColor,
this);
2710 text = QFileDialog::getSaveFileName(
this, tr(
"Save figure to ..."), (QDir::homePath() +
"/") + this->
title() +
".png",
"*.png *.xpm *.jpg *.pdf *.svg");
2712 text = QFileDialog::getSaveFileName(
this, tr(
"Save figure to ..."), (QDir::homePath() +
"/") + this->
title() +
".png",
"*.png *.xpm *.jpg *.pdf");
2716 bool flatModified =
false;
2720 flatModified =
true;
2723 QPalette p(palette());
2725 QColor c = p.color(QPalette::Background);
2726 p.setColor(QPalette::Background, Qt::white);
2730 if(QFileInfo(text).suffix().compare(
"svg") == 0)
2732 QSvgGenerator generator;
2733 generator.setFileName(text);
2734 generator.setSize(this->size());
2736 painter.begin(&generator);
2737 this->render(&painter);
2743 if(QFileInfo(text).suffix().compare(
"pdf") == 0)
2746 printer.setOutputFormat(QPrinter::PdfFormat);
2747 printer.setOutputFileName(text);
2748 this->render(&printer);
2752 QPixmap figure = QPixmap::grabWidget(
this);
2759 p.setColor(QPalette::Background, c);
2793 ULOGGER_ERROR(
"The directory \"%s\" doesn't exist", workingDirectory.toStdString().c_str());
2805 if(!dir.exists(targetDir))
2807 dir.mkdir(targetDir);
2810 targetDir += this->
title().replace(
" ",
"_");
2811 if(!dir.exists(targetDir))
2813 dir.mkdir(targetDir);
2817 QPixmap figure = QPixmap::grabWidget(
this);
2818 figure.save(targetDir + name);
2824 items << QString(
"png") << QString(
"jpg");
2826 QString item = QInputDialog::getItem(
this, tr(
"Select format"), tr(
"Format:"), items, 0,
false, &ok);
2827 if(ok && !item.isEmpty())
2836 for(
int i=0; i<
_curves.size(); ++i)
2839 if(qobject_cast<UPlotCurveThreshold*>(
_curves.at(i)) == 0)
2851 QPen pen = curve->
pen();
2871 _title->setVisible(!text.isEmpty());
2875 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
2882 _xLabel->setVisible(!text.isEmpty());
2886 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
2894 _yLabel->setVisible(!text.isEmpty());
2899 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
2909 for(QList<UPlotCurve*>::iterator iter=
_curves.begin(); iter!=
_curves.end(); ++iter)
2919 item->setZValue(1.0
f);
2929 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
2946 QTimer::singleShot(10,
this, SLOT(
updateAxis()));
2953 this->setMouseTracking(tracking);
2959 _view->setVisible(on);
2971 if(maxVisibleItems <= 0)
2975 else if(maxVisibleItems == 10)
2979 else if(maxVisibleItems == 50)
2983 else if(maxVisibleItems == 100)
2987 else if(maxVisibleItems == 500)
2991 else if(maxVisibleItems == 1000)
3007 return _view->sceneRect();
3012 QList<UPlotCurve*> tmp =
_curves;
3013 for(QList<UPlotCurve*>::iterator iter=tmp.begin(); iter!=tmp.end(); ++iter)
3022 QList<UPlotCurve *>::iterator iter = qFind(
_curves.begin(),
_curves.end(), curve);
3024 ULOGGER_DEBUG(
"Plot=\"%s\" removing curve=\"%s\"", this->objectName().toStdString().c_str(), curve?curve->
name().toStdString().c_str():
"");
3032 if(!qobject_cast<UPlotCurveThreshold*>(c))
3035 for(
int i=
_curves.size()-1; i>=0; --i)
3037 if(!qobject_cast<UPlotCurveThreshold*>(
_curves.at(i)))
3045 if(c->parent() ==
this)
3056 QList<UPlotCurve *>::iterator iter = qFind(
_curves.begin(),
_curves.end(), curve);
3071 int currentIndex = -1;
3073 for(
int i=0; i<
_curves.size(); ++i)
3083 if(c && currentIndex != index)
3085 _curves.removeAt(currentIndex);
3086 QList<QGraphicsItem *> children =
_sceneRoot->childItems();
3088 if(currentIndex > index)
3090 children[currentIndex]->stackBefore(children[index]);
3094 if(currentIndex<children.size()-2)
3096 if(index < children.size()-1)
3098 children[index]->stackBefore(children[currentIndex]);
3102 children[currentIndex]->stackBefore(children[index]);
3105 if(currentIndex == children.size()-2 && currentIndex < index)
3107 children[index]->stackBefore(children[currentIndex]);
QString _autoScreenCaptureFormat
QPointF getItemData(int index)
UPlotCurveThreshold(const QString &name, float thesholdValue, Qt::Orientation orientation=Qt::Horizontal, QObject *parent=0)
T uVariance(const T *v, unsigned int size, T meanV)
QGraphicsTextItem * _text
virtual void contextMenuEvent(QContextMenuEvent *event)
void setData(QVector< UPlotItem * > &data)
void setOrientation(Qt::Orientation orientation)
const QVector< float > & getMinMax() const
void redirectToggled(bool)
QGraphicsItem * _sceneRoot
UPlotAxis * _verticalAxis
QList< UPlotCurve * > _curves
virtual ~UPlotCurveThreshold()
void showGrid(bool shown)
GLM_FUNC_DECL genType min(genType const &x, genType const &y)
void setXIncrement(float increment)
virtual void contextMenuEvent(QContextMenuEvent *event)
int removeItem(int index)
void moveDownRequest(UPlotLegendItem *)
void setFixedYAxis(float y1, float y2)
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)
UPlotAxis(Qt::Orientation orientation=Qt::Horizontal, float min=0, float max=1, QWidget *parent=0)
void setFixedXAxis(float x1, float x2)
QAction * _aAddVerticalLine
virtual void mouseReleaseEvent(QMouseEvent *event)
UPlotItem * _previousItem
virtual ~UOrientableLabel()
virtual void contextMenuEvent(QContextMenuEvent *event)
Basic mathematics functions.
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)
UPlotItem * previousItem() const
void setPen(const QPen &pen)
void init(qreal dataX, qreal dataY)
virtual void update(float scaleX, float scaleY, float offsetX, float offsetY, float xDir, float yDir, int maxItemsKept)
QString _workingDirectory
const QBrush & brush() const
virtual void mousePressEvent(QMouseEvent *event)
void legendItemMoved(const UPlotCurve *curve, int)
QPen getRandomPenColored()
UPlotAxis * _horizontalAxis
virtual void showDescription(bool shown)
bool remove(const UPlotCurve *curve)
QAction * _aCopyAllCurveToClipboard
void trackMouse(bool tracking)
const QPointF & data() const
void removeLegendItem(const UPlotCurve *curve)
bool mousePosToValue(const QPoint &pos, float &x, float &y)
virtual void paintEvent(QPaintEvent *event)
void setVisible(bool visible)
#define ULOGGER_DEBUG(...)
virtual bool isMinMaxValid() const
Qt::Orientation _orientation
void setOrientation(Qt::Orientation orientation)
UPlotCurve * addCurve(const QString &curveName, const QColor &color=QColor())
QAction * _aShowRefreshRate
void removeCurve(const UPlotCurve *curve)
UPlotItem(qreal dataX, qreal dataY, qreal width=2)
void setGraphicsView(bool on)
QAction * _aAddHorizontalLine
void addItem(UPlotCurve *curve)
QPixmap createSymbol(const QPen &pen, const QBrush &brush)
virtual void mouseMoveEvent(QMouseEvent *event)
void _addValue(UPlotItem *data)
virtual void update(float scaleX, float scaleY, float offsetX, float offsetY, float xDir, float yDir, int maxItemsKept)
void setThreshold(float threshold)
void legendItemRemoved(const UPlotCurve *)
virtual ~UPlotLegendItem()
QSize minimumSizeHint() const
void addValues(QVector< UPlotItem * > &data)
UPlotLegend(QWidget *parent=0)
virtual void keyReleaseEvent(QKeyEvent *keyEvent)
QList< QGraphicsItem * > _items
virtual void resizeEvent(QResizeEvent *event)
void moveDown(UPlotLegendItem *item)
QAction * _aYLabelVertical
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
QAction * _aAutoScreenCapture
UPlotCurveThreshold * addThreshold(const QString &name, float value, Qt::Orientation orientation=Qt::Horizontal)
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 *)
void setData(const QPointF &data)
Qt::Orientation orientation() const
void setMaxVisibleItems(int maxVisibleItems)
UPlotItem * nextItem() const
void setBackgroundColor(const QColor &color)
void draw(QPainter *painter, const QRect &limits)
virtual void focusInEvent(QFocusEvent *event)
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)
const UPlotCurve * curve() const
UPlotCurve(const QString &name, QObject *parent=0)
#define ULOGGER_ERROR(...)
void getData(QVector< float > &x, QVector< float > &y) const
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 setAxis(float &min, float &max)
void setNextItem(UPlotItem *nextItem)
QList< QGraphicsLineItem * > hGridLines
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 setPreviousItem(UPlotItem *previousItem)
void setXStart(float val)
void moveUp(UPlotLegendItem *item)