void RoutingStatsScene::reloadContent(bool force) { if(m_nodeIdProxyWidgets.empty()) { return; } m_lastX = 0; m_lastY = 0; m_bottomY = 0; qreal currentTime = StatsMode::getInstance()->getCurrentTime(); qreal currentMaxHeight = 0; for(NodeIdProxyWidgetMap_t::const_iterator i = m_nodeIdProxyWidgets.begin(); i != m_nodeIdProxyWidgets.end(); ++i) { QGraphicsProxyWidget * pw = i->second; if((force) || (!m_lastTime) || (m_lastTime != currentTime)) { updateContent(i->first, pw); } bool nodeIsActive = StatsMode::getInstance()->isNodeActive(i->first); pw->setVisible(nodeIsActive); if(nodeIsActive) { qreal newX = m_lastX + pw->size().width(); currentMaxHeight = qMax(currentMaxHeight, pw->size().height()); if(newX >= sceneRect().right()) { m_lastX = 0; m_lastY += currentMaxHeight + INTERSTATS_SPACE; currentMaxHeight = 0; } pw->setPos(m_lastX, m_lastY); m_lastX = pw->pos().x() + pw->size().width() + INTERSTATS_SPACE; m_lastY = pw->pos().y(); m_bottomY = m_lastY + currentMaxHeight; adjustRect(); } } m_lastTime = currentTime; }
//! [0] PadNavigator::PadNavigator(const QSize &size, QWidget *parent) : QGraphicsView(parent) { //! [0] //! [1] // Splash item SplashItem *splash = new SplashItem; splash->setZValue(1); //! [1] //! [2] // Pad item FlippablePad *pad = new FlippablePad(size); QGraphicsRotation *flipRotation = new QGraphicsRotation(pad); QGraphicsRotation *xRotation = new QGraphicsRotation(pad); QGraphicsRotation *yRotation = new QGraphicsRotation(pad); flipRotation->setAxis(Qt::YAxis); xRotation->setAxis(Qt::YAxis); yRotation->setAxis(Qt::XAxis); pad->setTransformations(QList<QGraphicsTransform *>() << flipRotation << xRotation << yRotation); //! [2] //! [3] // Back (proxy widget) item QGraphicsProxyWidget *backItem = new QGraphicsProxyWidget(pad); QWidget *widget = new QWidget; form.setupUi(widget); form.hostName->setFocus(); backItem->setWidget(widget); backItem->setVisible(false); backItem->setFocus(); backItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); const QRectF r = backItem->rect(); backItem->setTransform(QTransform() .rotate(180, Qt::YAxis) .translate(-r.width()/2, -r.height()/2)); //! [3] //! [4] // Selection item RoundRectItem *selectionItem = new RoundRectItem(QRectF(-60, -60, 120, 120), Qt::gray, pad); selectionItem->setZValue(0.5); //! [4] //! [5] // Splash animations QPropertyAnimation *smoothSplashMove = new QPropertyAnimation(splash, "y"); QPropertyAnimation *smoothSplashOpacity = new QPropertyAnimation(splash, "opacity"); smoothSplashMove->setEasingCurve(QEasingCurve::InQuad); smoothSplashMove->setDuration(250); smoothSplashOpacity->setDuration(250); //! [5] //! [6] // Selection animation QPropertyAnimation *smoothXSelection = new QPropertyAnimation(selectionItem, "x"); QPropertyAnimation *smoothYSelection = new QPropertyAnimation(selectionItem, "y"); QPropertyAnimation *smoothXRotation = new QPropertyAnimation(xRotation, "angle"); QPropertyAnimation *smoothYRotation = new QPropertyAnimation(yRotation, "angle"); smoothXSelection->setDuration(125); smoothYSelection->setDuration(125); smoothXRotation->setDuration(125); smoothYRotation->setDuration(125); smoothXSelection->setEasingCurve(QEasingCurve::InOutQuad); smoothYSelection->setEasingCurve(QEasingCurve::InOutQuad); smoothXRotation->setEasingCurve(QEasingCurve::InOutQuad); smoothYRotation->setEasingCurve(QEasingCurve::InOutQuad); //! [6] //! [7] // Flip animation setup QPropertyAnimation *smoothFlipRotation = new QPropertyAnimation(flipRotation, "angle"); QPropertyAnimation *smoothFlipScale = new QPropertyAnimation(pad, "scale"); QPropertyAnimation *smoothFlipXRotation = new QPropertyAnimation(xRotation, "angle"); QPropertyAnimation *smoothFlipYRotation = new QPropertyAnimation(yRotation, "angle"); QParallelAnimationGroup *flipAnimation = new QParallelAnimationGroup(this); smoothFlipScale->setDuration(500); smoothFlipRotation->setDuration(500); smoothFlipXRotation->setDuration(500); smoothFlipYRotation->setDuration(500); smoothFlipScale->setEasingCurve(QEasingCurve::InOutQuad); smoothFlipRotation->setEasingCurve(QEasingCurve::InOutQuad); smoothFlipXRotation->setEasingCurve(QEasingCurve::InOutQuad); smoothFlipYRotation->setEasingCurve(QEasingCurve::InOutQuad); smoothFlipScale->setKeyValueAt(0, qvariant_cast<qreal>(1.0)); smoothFlipScale->setKeyValueAt(0.5, qvariant_cast<qreal>(0.7)); smoothFlipScale->setKeyValueAt(1, qvariant_cast<qreal>(1.0)); flipAnimation->addAnimation(smoothFlipRotation); flipAnimation->addAnimation(smoothFlipScale); flipAnimation->addAnimation(smoothFlipXRotation); flipAnimation->addAnimation(smoothFlipYRotation); //! [7] //! [8] // Flip animation delayed property assignment QSequentialAnimationGroup *setVariablesSequence = new QSequentialAnimationGroup; QPropertyAnimation *setFillAnimation = new QPropertyAnimation(pad, "fill"); QPropertyAnimation *setBackItemVisibleAnimation = new QPropertyAnimation(backItem, "visible"); QPropertyAnimation *setSelectionItemVisibleAnimation = new QPropertyAnimation(selectionItem, "visible"); setFillAnimation->setDuration(0); setBackItemVisibleAnimation->setDuration(0); setSelectionItemVisibleAnimation->setDuration(0); setVariablesSequence->addPause(250); setVariablesSequence->addAnimation(setBackItemVisibleAnimation); setVariablesSequence->addAnimation(setSelectionItemVisibleAnimation); setVariablesSequence->addAnimation(setFillAnimation); flipAnimation->addAnimation(setVariablesSequence); //! [8] //! [9] // Build the state machine QStateMachine *stateMachine = new QStateMachine(this); QState *splashState = new QState(stateMachine); QState *frontState = new QState(stateMachine); QHistoryState *historyState = new QHistoryState(frontState); QState *backState = new QState(stateMachine); //! [9] //! [10] frontState->assignProperty(pad, "fill", false); frontState->assignProperty(splash, "opacity", 0.0); frontState->assignProperty(backItem, "visible", false); frontState->assignProperty(flipRotation, "angle", qvariant_cast<qreal>(0.0)); frontState->assignProperty(selectionItem, "visible", true); backState->assignProperty(pad, "fill", true); backState->assignProperty(backItem, "visible", true); backState->assignProperty(xRotation, "angle", qvariant_cast<qreal>(0.0)); backState->assignProperty(yRotation, "angle", qvariant_cast<qreal>(0.0)); backState->assignProperty(flipRotation, "angle", qvariant_cast<qreal>(180.0)); backState->assignProperty(selectionItem, "visible", false); stateMachine->addDefaultAnimation(smoothXRotation); stateMachine->addDefaultAnimation(smoothYRotation); stateMachine->addDefaultAnimation(smoothXSelection); stateMachine->addDefaultAnimation(smoothYSelection); stateMachine->setInitialState(splashState); //! [10] //! [11] // Transitions QEventTransition *anyKeyTransition = new QEventTransition(this, QEvent::KeyPress, splashState); anyKeyTransition->setTargetState(frontState); anyKeyTransition->addAnimation(smoothSplashMove); anyKeyTransition->addAnimation(smoothSplashOpacity); //! [11] //! [12] QKeyEventTransition *enterTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Enter, backState); QKeyEventTransition *returnTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Return, backState); QKeyEventTransition *backEnterTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Enter, frontState); QKeyEventTransition *backReturnTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Return, frontState); enterTransition->setTargetState(historyState); returnTransition->setTargetState(historyState); backEnterTransition->setTargetState(backState); backReturnTransition->setTargetState(backState); enterTransition->addAnimation(flipAnimation); returnTransition->addAnimation(flipAnimation); backEnterTransition->addAnimation(flipAnimation); backReturnTransition->addAnimation(flipAnimation); //! [12] //! [13] // Create substates for each icon; store in temporary grid. int columns = size.width(); int rows = size.height(); QVector< QVector< QState * > > stateGrid; stateGrid.resize(rows); for (int y = 0; y < rows; ++y) { stateGrid[y].resize(columns); for (int x = 0; x < columns; ++x) stateGrid[y][x] = new QState(frontState); } frontState->setInitialState(stateGrid[0][0]); selectionItem->setPos(pad->iconAt(0, 0)->pos()); //! [13] //! [14] // Enable key navigation using state transitions for (int y = 0; y < rows; ++y) { for (int x = 0; x < columns; ++x) { QState *state = stateGrid[y][x]; QKeyEventTransition *rightTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Right, state); QKeyEventTransition *leftTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Left, state); QKeyEventTransition *downTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Down, state); QKeyEventTransition *upTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Up, state); rightTransition->setTargetState(stateGrid[y][(x + 1) % columns]); leftTransition->setTargetState(stateGrid[y][((x - 1) + columns) % columns]); downTransition->setTargetState(stateGrid[(y + 1) % rows][x]); upTransition->setTargetState(stateGrid[((y - 1) + rows) % rows][x]); //! [14] //! [15] RoundRectItem *icon = pad->iconAt(x, y); state->assignProperty(xRotation, "angle", -icon->x() / 6.0); state->assignProperty(yRotation, "angle", icon->y() / 6.0); state->assignProperty(selectionItem, "x", icon->x()); state->assignProperty(selectionItem, "y", icon->y()); frontState->assignProperty(icon, "visible", true); backState->assignProperty(icon, "visible", false); QPropertyAnimation *setIconVisibleAnimation = new QPropertyAnimation(icon, "visible"); setIconVisibleAnimation->setDuration(0); setVariablesSequence->addAnimation(setIconVisibleAnimation); } } //! [15] //! [16] // Scene QGraphicsScene *scene = new QGraphicsScene(this); scene->setBackgroundBrush(QPixmap(":/images/blue_angle_swirl.jpg")); scene->setItemIndexMethod(QGraphicsScene::NoIndex); scene->addItem(pad); scene->setSceneRect(scene->itemsBoundingRect()); setScene(scene); //! [16] //! [17] // Adjust splash item to scene contents const QRectF sbr = splash->boundingRect(); splash->setPos(-sbr.width() / 2, scene->sceneRect().top() - 2); frontState->assignProperty(splash, "y", splash->y() - 100.0); scene->addItem(splash); //! [17] //! [18] // View setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setMinimumSize(50, 50); setViewportUpdateMode(FullViewportUpdate); setCacheMode(CacheBackground); setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); #ifndef QT_NO_OPENGL setViewport(new QOpenGLWidget); #endif stateMachine->start(); //! [18] }
/* Most important function of an interactor component When an event arrive on your interactor : this function is call You have to process it and return true. If the event do nothing in your interactor : this function return false; */ bool eventFilter(QObject *, QEvent *e) { /* If you have clicked on a node/edge, information widget is visible. And if you use the wheel of the mouse we hide the information widget */ if (_informationWidgetItem->isVisible() && e->type() == QEvent::Wheel) { _informationWidgetItem->setVisible(false); return false; } /* Check if the event is a mouse event */ QMouseEvent *qMouseEv = dynamic_cast<QMouseEvent *>(e); if (qMouseEv != nullptr) { GlMainView *glMainView = static_cast<GlMainView *>(view()); /* Check if event is a left mouse button press */ if (e->type() == QEvent::MouseButtonPress && qMouseEv->button() == Qt::LeftButton) { /* If you have clicked on a node/edge, information widget is visible. And if you reclick : hide it */ if (_informationWidgetItem->isVisible()) { _informationWidgetItem->setVisible(false); } else { /* Select entities under the mouse cursor The result of selection is stored in SelectedEntity And pickNodesEdges return true if you click on node or edge */ SelectedEntity selectedEntity; if (glMainView->getGlMainWidget()->pickNodesEdges(qMouseEv->x(), qMouseEv->y(), selectedEntity)) { /* Change text of the information label with - If you click on a node : "Click on node id : nodeId" - If you click on an edge : "Click on edge id : edgeId" */ QString text("Click on "); if (selectedEntity.getEntityType() == SelectedEntity::NODE_SELECTED) text += "node "; else text += "edge "; text += " id : " + QString::number(selectedEntity.getComplexEntityId()); /* - Update QLabel with new text - Auto resize QLabel - Set position of the label at mouse position - Display it */ _informationLabel->setText(text); _informationLabel->adjustSize(); _informationWidgetItem->setPos(qMouseEv->pos()); _informationWidgetItem->setVisible(true); /* Here we just add a small smooth animation on the label pop */ QPropertyAnimation *animation = new QPropertyAnimation(_informationWidgetItem, "opacity"); animation->setDuration(100); animation->setStartValue(0.); animation->setEndValue(0.99); animation->start(); /* We have treated the event so we return true */ return true; } } } } /* We don't have treated the event se we return false */ return false; }
/* Basic constructor In this constructor we create a label to display information And a QGraphicsProxyWidget to show information in Tulip QGraphics system */ InteractorPluginComponent() { _informationLabel = new QLabel(); _informationWidgetItem = new QGraphicsProxyWidget(); _informationWidgetItem->setWidget(_informationLabel); _informationWidgetItem->setVisible(false); }
void FlowMonStatsScene::align() { m_lastX = 0; m_lastY = 0; m_bottomY = 0; qreal currentMaxHeight = 0; for(FlowIdProxyWidgetMap_t::const_iterator i = m_flowIdProxyWidgets.begin(); i != m_flowIdProxyWidgets.end(); ++i) { QGraphicsProxyWidget * pw = i->second; bool flowIsActive = StatsMode::getInstance()->isNodeActive(i->first); pw->setVisible(flowIsActive); if(flowIsActive) { TextBubble * tb = (TextBubble *) pw->widget(); QFont f(tb->font()); f.setPointSizeF(StatsMode::getInstance()->getCurrentFontSize()); tb->setFont(f); QFontMetrics fm(f); pw->setMaximumHeight(fm.height() * tb->text().count("\n")); pw->adjustSize(); qreal newX = m_lastX + pw->size().width(); currentMaxHeight = qMax(currentMaxHeight, pw->size().height()); if(newX >= sceneRect().right()) { m_lastX = 0; m_lastY += currentMaxHeight + INTERSTATS_SPACE; currentMaxHeight = 0; } pw->setPos(m_lastX, m_lastY); m_lastX = pw->pos().x() + pw->size().width() + INTERSTATS_SPACE; m_lastY = pw->pos().y(); m_bottomY = m_lastY + currentMaxHeight; adjustRect(); } } if(m_flowProbeWidget) { QGraphicsProxyWidget * pw = m_flowProbeWidget; TextBubble * tb = (TextBubble *) pw->widget(); QFont f(tb->font()); f.setPointSizeF(StatsMode::getInstance()->getCurrentFontSize()); tb->setFont(f); QFontMetrics fm(f); pw->setMaximumHeight(fm.height() * tb->text().count("\n")); pw->adjustSize(); qreal newX = m_lastX + pw->size().width(); currentMaxHeight = qMax(currentMaxHeight, pw->size().height()); if(newX >= sceneRect().right()) { m_lastX = 0; m_lastY += currentMaxHeight + INTERSTATS_SPACE; currentMaxHeight = 0; } pw->setPos(m_lastX, m_lastY); m_lastX = pw->pos().x() + pw->size().width() + INTERSTATS_SPACE; m_lastY = pw->pos().y(); m_bottomY = m_lastY + currentMaxHeight; adjustRect(); } }