##// END OF EJS Templates
Adds "number of operations" and "number of variables" properties for the tests
Adds "number of operations" and "number of variables" properties for the tests

File last commit:

r1159:4c27015bd9c6
r1170:3da18e6983d5
Show More
VisualizationSelectionZoneItem.cpp
440 lines | 15.2 KiB | text/x-c | CppLexer
/ gui / src / Visualization / VisualizationSelectionZoneItem.cpp
#include "Visualization/VisualizationSelectionZoneItem.h"
#include "Visualization/VisualizationGraphWidget.h"
#include "Visualization/VisualizationSelectionZoneManager.h"
#include "Visualization/VisualizationWidget.h"
const QString &DEFAULT_COLOR = QStringLiteral("#E79D41");
struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
QCustomPlot *m_Plot;
double m_T1 = 0;
double m_T2 = 0;
QColor m_Color;
bool m_IsEditionEnabled = true;
double m_MovedOrinalT1 = 0;
double m_MovedOrinalT2 = 0;
QCPItemStraightLine *m_LeftLine;
QCPItemStraightLine *m_RightLine;
QCPItemText *m_NameLabelItem = nullptr;
enum class EditionMode { NoEdition, ResizeLeft, ResizeRight, Move };
EditionMode m_CurrentEditionMode;
QVector<VisualizationSelectionZoneItem *> m_AssociatedEditedZones;
VisualizationSelectionZoneItemPrivate(QCustomPlot *plot)
: m_Plot(plot), m_Color(Qt::blue), m_CurrentEditionMode(EditionMode::NoEdition)
{
}
void updatePosition(VisualizationSelectionZoneItem *item)
{
item->topLeft->setCoords(m_T1, 0);
item->bottomRight->setCoords(m_T2, 1);
}
EditionMode getEditionMode(const QPoint &pos, const VisualizationSelectionZoneItem *zoneItem)
{
auto distanceLeft = m_LeftLine->selectTest(pos, false);
auto distanceRight = m_RightLine->selectTest(pos, false);
auto distance = zoneItem->selectTest(pos, false);
if (distanceRight <= distance) {
return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
}
else if (distanceLeft <= distance) {
return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft;
}
return VisualizationSelectionZoneItemPrivate::EditionMode::Move;
}
double pixelSizeToAxisXSize(double pixels)
{
auto axis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
return axis->pixelToCoord(pixels) - axis->pixelToCoord(0);
}
bool alignZones(VisualizationSelectionZoneItem *referenceZone,
const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool alignOnLeft,
bool allowResize, bool vertically)
{
auto result = false;
auto referenceTime
= alignOnLeft ? referenceZone->range().m_TStart : referenceZone->range().m_TEnd;
auto referenceBottomAxis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
auto referenceVerticalPosition = referenceBottomAxis->coordToPixel(referenceTime);
for (auto otherZone : zonesToAlign) {
auto otherZoneRange = otherZone->range();
auto newZoneStart = otherZoneRange.m_TStart;
auto newZoneEnd = otherZoneRange.m_TEnd;
auto alignedTime = referenceTime;
if (vertically) {
auto otherZoneAxis = otherZone->parentPlot()->axisRect()->axis(QCPAxis::atBottom);
alignedTime = otherZoneAxis->pixelToCoord(referenceVerticalPosition);
}
if (alignOnLeft) {
newZoneStart = alignedTime;
if (!allowResize) {
newZoneEnd = alignedTime + (otherZoneRange.m_TEnd - otherZoneRange.m_TStart);
}
}
else { // align on right
newZoneEnd = alignedTime;
if (!allowResize) {
newZoneStart = alignedTime - (otherZoneRange.m_TEnd - otherZoneRange.m_TStart);
}
}
if (newZoneStart < newZoneEnd) {
result = true;
otherZone->setRange(newZoneStart, newZoneEnd);
otherZone->parentPlot()->replot();
}
}
return result;
}
};
VisualizationSelectionZoneItem::VisualizationSelectionZoneItem(QCustomPlot *plot)
: QCPItemRect(plot),
impl{spimpl::make_unique_impl<VisualizationSelectionZoneItemPrivate>(plot)}
{
topLeft->setTypeX(QCPItemPosition::ptPlotCoords);
topLeft->setTypeY(QCPItemPosition::ptAxisRectRatio);
bottomRight->setTypeX(QCPItemPosition::ptPlotCoords);
bottomRight->setTypeY(QCPItemPosition::ptAxisRectRatio);
setSelectable(false);
impl->m_RightLine = new QCPItemStraightLine(plot);
impl->m_RightLine->point1->setParentAnchor(topRight);
impl->m_RightLine->point2->setParentAnchor(bottomRight);
impl->m_RightLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
impl->m_RightLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
impl->m_RightLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
impl->m_RightLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
impl->m_RightLine->setSelectable(false);
impl->m_LeftLine = new QCPItemStraightLine(plot);
impl->m_LeftLine->point1->setParentAnchor(topLeft);
impl->m_LeftLine->point2->setParentAnchor(bottomLeft);
impl->m_LeftLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
impl->m_LeftLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
impl->m_LeftLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
impl->m_LeftLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
impl->m_LeftLine->setSelectable(false);
connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_RightLine,
&QCPItemStraightLine::setSelected);
connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_LeftLine,
&QCPItemStraightLine::setSelected);
setColor(QColor(DEFAULT_COLOR));
}
VisualizationSelectionZoneItem::~VisualizationSelectionZoneItem()
{
}
VisualizationGraphWidget *VisualizationSelectionZoneItem::parentGraphWidget() const noexcept
{
auto parent = impl->m_Plot->parentWidget();
while (parent != nullptr && !qobject_cast<VisualizationGraphWidget *>(parent)) {
parent = parent->parentWidget();
}
return qobject_cast<VisualizationGraphWidget *>(parent);
}
void VisualizationSelectionZoneItem::setName(const QString &name)
{
if (name.isEmpty() && impl->m_NameLabelItem) {
impl->m_Plot->removeItem(impl->m_NameLabelItem);
impl->m_NameLabelItem = nullptr;
}
else if (!impl->m_NameLabelItem) {
impl->m_NameLabelItem = new QCPItemText(impl->m_Plot);
impl->m_NameLabelItem->setText(name);
impl->m_NameLabelItem->setPositionAlignment(Qt::AlignHCenter | Qt::AlignTop);
impl->m_NameLabelItem->setColor(impl->m_Color);
impl->m_NameLabelItem->position->setParentAnchor(top);
}
}
QString VisualizationSelectionZoneItem::name() const
{
if (!impl->m_NameLabelItem) {
return QString();
}
return impl->m_NameLabelItem->text();
}
SqpRange VisualizationSelectionZoneItem::range() const
{
SqpRange range;
range.m_TStart = impl->m_T1 <= impl->m_T2 ? impl->m_T1 : impl->m_T2;
range.m_TEnd = impl->m_T1 > impl->m_T2 ? impl->m_T1 : impl->m_T2;
return range;
}
void VisualizationSelectionZoneItem::setRange(double tstart, double tend)
{
impl->m_T1 = tstart;
impl->m_T2 = tend;
impl->updatePosition(this);
}
void VisualizationSelectionZoneItem::setStart(double tstart)
{
impl->m_T1 = tstart;
impl->updatePosition(this);
}
void VisualizationSelectionZoneItem::setEnd(double tend)
{
impl->m_T2 = tend;
impl->updatePosition(this);
}
void VisualizationSelectionZoneItem::setColor(const QColor &color)
{
impl->m_Color = color;
auto brushColor = color;
brushColor.setAlpha(80);
setBrush(QBrush(brushColor));
setPen(QPen(Qt::NoPen));
auto selectedBrushColor = brushColor;
selectedBrushColor.setAlpha(150);
setSelectedBrush(QBrush(selectedBrushColor));
setSelectedPen(QPen(Qt::NoPen));
auto linePen = QPen(color);
linePen.setStyle(Qt::SolidLine);
linePen.setWidth(4);
auto selectedLinePen = linePen;
selectedLinePen.setColor(color.darker(120));
selectedLinePen.setWidth(4);
impl->m_LeftLine->setPen(linePen);
impl->m_RightLine->setPen(linePen);
impl->m_LeftLine->setSelectedPen(selectedLinePen);
impl->m_RightLine->setSelectedPen(selectedLinePen);
}
void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
{
impl->m_IsEditionEnabled = value;
setSelectable(value);
if (!value) {
setSelected(false);
impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
}
}
bool VisualizationSelectionZoneItem::isEditionEnabled() const
{
return impl->m_IsEditionEnabled;
}
void VisualizationSelectionZoneItem::moveToTop()
{
moveToLayer(layer(), false);
}
Qt::CursorShape
VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const
{
auto mode = impl->m_CurrentEditionMode
== VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition
? impl->getEditionMode(position, this)
: impl->m_CurrentEditionMode;
switch (mode) {
case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
return Qt::SizeAllCursor;
case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight: // fallthrough
return Qt::SizeHorCursor;
default:
return Qt::ArrowCursor;
}
}
void VisualizationSelectionZoneItem::setHovered(bool value)
{
if (value) {
auto linePen = impl->m_LeftLine->pen();
linePen.setStyle(Qt::DotLine);
linePen.setWidth(3);
auto selectedLinePen = impl->m_LeftLine->selectedPen();
;
selectedLinePen.setStyle(Qt::DotLine);
selectedLinePen.setWidth(3);
impl->m_LeftLine->setPen(linePen);
impl->m_RightLine->setPen(linePen);
impl->m_LeftLine->setSelectedPen(selectedLinePen);
impl->m_RightLine->setSelectedPen(selectedLinePen);
}
else {
setColor(impl->m_Color);
}
}
void VisualizationSelectionZoneItem::setAssociatedEditedZones(
const QVector<VisualizationSelectionZoneItem *> &associatedZones)
{
impl->m_AssociatedEditedZones = associatedZones;
impl->m_AssociatedEditedZones.removeAll(this);
}
bool VisualizationSelectionZoneItem::alignZonesVerticallyOnLeft(
const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
{
return impl->alignZones(this, zonesToAlign, true, allowResize, true);
}
bool VisualizationSelectionZoneItem::alignZonesVerticallyOnRight(
const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
{
return impl->alignZones(this, zonesToAlign, false, allowResize, true);
}
bool VisualizationSelectionZoneItem::alignZonesTemporallyOnLeft(
const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
{
return impl->alignZones(this, zonesToAlign, true, allowResize, false);
}
bool VisualizationSelectionZoneItem::alignZonesTemporallyOnRight(
const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
{
return impl->alignZones(this, zonesToAlign, false, allowResize, false);
}
void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details)
{
Q_UNUSED(details);
if (isEditionEnabled() && event->button() == Qt::LeftButton) {
impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this);
impl->m_MovedOrinalT1 = impl->m_T1;
impl->m_MovedOrinalT2 = impl->m_T2;
for (auto associatedZone : impl->m_AssociatedEditedZones) {
associatedZone->impl->m_MovedOrinalT1 = associatedZone->impl->m_T1;
associatedZone->impl->m_MovedOrinalT2 = associatedZone->impl->m_T2;
}
}
else {
impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
event->ignore();
}
}
void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
{
if (isEditionEnabled()) {
if (!selected()) {
// Force the item to be selected during the edition
parentGraphWidget()->parentVisualizationWidget()->selectionZoneManager().setSelected(
this, true);
}
auto axis = impl->m_Plot->axisRect()->axis(QCPAxis::atBottom);
auto pixelDiff = event->pos().x() - startPos.x();
auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
switch (impl->m_CurrentEditionMode) {
case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
for (auto associatedZone : impl->m_AssociatedEditedZones) {
associatedZone->move(pixelDiff);
}
break;
case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
setStart(impl->m_MovedOrinalT1 + diff);
for (auto associatedZone : impl->m_AssociatedEditedZones) {
impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
? associatedZone->resizeLeft(pixelDiff)
: associatedZone->resizeRight(pixelDiff);
}
break;
case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight:
setEnd(impl->m_MovedOrinalT2 + diff);
for (auto associatedZone : impl->m_AssociatedEditedZones) {
impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
? associatedZone->resizeRight(pixelDiff)
: associatedZone->resizeLeft(pixelDiff);
}
break;
default:
break;
}
for (auto associatedZone : impl->m_AssociatedEditedZones) {
associatedZone->parentPlot()->replot();
}
}
else {
event->ignore();
}
}
void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
{
Q_UNUSED(startPos);
if (isEditionEnabled()) {
impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
}
else {
event->ignore();
}
impl->m_AssociatedEditedZones.clear();
}
void VisualizationSelectionZoneItem::resizeLeft(double pixelDiff)
{
auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
if (impl->m_MovedOrinalT1 <= impl->m_MovedOrinalT2) {
setStart(impl->m_MovedOrinalT1 + diff);
}
else {
setEnd(impl->m_MovedOrinalT2 + diff);
}
}
void VisualizationSelectionZoneItem::resizeRight(double pixelDiff)
{
auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
if (impl->m_MovedOrinalT1 > impl->m_MovedOrinalT2) {
setStart(impl->m_MovedOrinalT1 + diff);
}
else {
setEnd(impl->m_MovedOrinalT2 + diff);
}
}
void VisualizationSelectionZoneItem::move(double pixelDiff)
{
auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
}