Beispiel #1
0
void GraphDraw::mouseMoveEvent(QMouseEvent *event)
{
    QGraphicsView::mouseMoveEvent(event);

    //handle the first move event transition from a press event
    if (_selectionState == SELECTION_STATE_PRESS)
    {
        _selectionState = SELECTION_STATE_MOVE;

        //record positions to determine movement on release
        _preMovePositions.clear();
        for (auto obj : getObjectsSelected(~GRAPH_CONNECTION))
        {
            _preMovePositions[obj] = obj->pos();
        }
    }

    //cause full render when moving objects for clean animation
    if (_selectionState == SELECTION_STATE_MOVE) this->render();

    //auto scroll near boundaries
    if (_selectionState != SELECTION_STATE_NONE)
    {
        handleAutoScroll(this->horizontalScrollBar(), this->size().width(), this->mapToScene(event->pos()).x());
        handleAutoScroll(this->verticalScrollBar(), this->size().height(), this->mapToScene(event->pos()).y());
    }
}
Beispiel #2
0
void GraphEditor::handleBlockXcrement(const int adj)
{
    if (not this->isVisible()) return;
    auto draw = this->getCurrentGraphDraw();
    GraphObjectList changedObjects;
    for (auto obj : draw->getObjectsSelected(GRAPH_BLOCK))
    {
        auto block = dynamic_cast<GraphBlock *>(obj);
        assert(block != nullptr);
        for (const auto &propKey : block->getProperties())
        {
            auto paramDesc = block->getParamDesc(propKey);
            if (paramDesc->has("widgetType") and paramDesc->getValue<std::string>("widgetType") == "SpinBox")
            {
                const auto newValue = block->getPropertyValue(propKey).toInt() + adj;
                block->setPropertyValue(propKey, QString("%1").arg(newValue));
                changedObjects.push_back(block);
                break;
            }
        }
    }

    if (changedObjects.empty()) return;
    const auto desc = (changedObjects.size() == 1)? changedObjects.front()->getId() : tr("selected");
    if (adj > 0) handleStateChange(GraphState("list-add", tr("Increment %1").arg(desc)));
    if (adj < 0) handleStateChange(GraphState("list-remove", tr("Decrement %1").arg(desc)));
}
Beispiel #3
0
void GraphEditor::handleObjectProperties(void)
{
    if (not this->isVisible()) return;
    auto draw = this->getCurrentGraphDraw();
    const auto objs = draw->getObjectsSelected();
    if (not objs.isEmpty()) emit draw->modifyProperties(objs.at(0));
}
Beispiel #4
0
void GraphEditor::handleRotateRight(void)
{
    if (not this->isVisible()) return;
    auto draw = this->getCurrentGraphDraw();
    //TODO rotate group of objects around central point
    for (auto obj : draw->getObjectsSelected(~GRAPH_CONNECTION))
    {
        obj->rotateRight();
    }
    handleStateChange(GraphState("object-rotate-right", tr("Rotate %1 right").arg(draw->getSelectionDescription(~GRAPH_CONNECTION))));
}
Beispiel #5
0
void GraphEditor::handleAffinityZoneClicked(const QString &zone)
{
    if (not this->isVisible()) return;
    auto draw = this->getCurrentGraphDraw();

    for (auto obj : draw->getObjectsSelected(GRAPH_BLOCK))
    {
        auto block = dynamic_cast<GraphBlock *>(obj);
        assert(block != nullptr);
        block->setAffinityZone(zone);
    }
    handleStateChange(GraphState("document-export", tr("Set %1 affinity zone").arg(draw->getSelectionDescription(GRAPH_BLOCK))));
}
Beispiel #6
0
void GraphEditor::handleSetEnabled(const bool enb)
{
    if (not this->isVisible()) return;
    auto draw = this->getCurrentGraphDraw();

    auto objs = draw->getObjectsSelected();
    if (objs.isEmpty()) return;

    for (auto obj : objs)
    {
        obj->setEnabled(enb);
    }

    if (enb) handleStateChange(GraphState("document-import", tr("Enable %1").arg(draw->getSelectionDescription())));
    else handleStateChange(GraphState("document-export", tr("Disable %1").arg(draw->getSelectionDescription())));
}
Beispiel #7
0
void GraphEditor::handleDelete(void)
{
    if (not this->isVisible()) return;
    auto draw = this->getCurrentGraphDraw();
    auto desc = tr("Delete %1").arg(draw->getSelectionDescription());

    //delete all selected graph objects
    for (auto obj : draw->getObjectsSelected())
    {
        delete obj;
    }

    this->deleteFlagged();

    handleStateChange(GraphState("edit-delete", desc));
}
void GraphDraw::mouseMoveEvent(QMouseEvent *event)
{
    QGraphicsView::mouseMoveEvent(event);

    //implement mouse tracking for blocks
    const auto scenePos = this->mapToScene(event->pos());
    for (auto obj : this->getGraphObjects())
    {
        obj->updateMouseTracking(obj->mapFromParent(scenePos));
    }

    //handle drawing in the click, drag, connect mode
    const auto topObj = _lastClickSelectEp.getObj();
    if (_connectLineItem and topObj)
    {
        const auto attrs = topObj->getConnectableAttrs(_lastClickSelectEp.getKey());
        const auto newPos = topObj->mapFromParent(scenePos);
        _connectLineItem->setLine(QLineF(attrs.point, newPos));
    }

    //handle the first move event transition from a press event
    if (_selectionState == SELECTION_STATE_PRESS)
    {
        _selectionState = SELECTION_STATE_MOVE;

        //record positions to determine movement on release
        _preMovePositions.clear();
        for (auto obj : getObjectsSelected(~GRAPH_CONNECTION))
        {
            _preMovePositions[obj] = obj->pos();
        }
    }

    //cause full render when moving objects for clean animation
    if (_selectionState == SELECTION_STATE_MOVE) this->render();

    //auto scroll near boundaries
    if (_selectionState != SELECTION_STATE_NONE)
    {
        handleAutoScroll(this->horizontalScrollBar(), this->size().width(), this->mapToScene(event->pos()).x());
        handleAutoScroll(this->verticalScrollBar(), this->size().height(), this->mapToScene(event->pos()).y());
    }
}
Beispiel #9
0
void GraphEditor::handleCopy(void)
{
    if (not this->isVisible()) return;
    auto draw = this->getCurrentGraphDraw();

    Poco::JSON::Array jsonObjs;
    for (auto obj : draw->getObjectsSelected())
    {
        jsonObjs.add(obj->serialize());
    }

    //to byte array
    std::ostringstream oss;
    jsonObjs.stringify(oss);
    QByteArray byteArray(oss.str().data(), oss.str().size());

    //load the clipboard
    auto mimeData = new QMimeData();
    mimeData->setData("text/json/pothos_object_array", byteArray);
    QApplication::clipboard()->setMimeData(mimeData);
}
Beispiel #10
0
void GraphEditor::handleReeval(void)
{
    if (not this->isVisible()) return;
    auto draw = this->getCurrentGraphDraw();
    _evalEngine->submitReeval(draw->getObjectsSelected(GRAPH_BLOCK));
}
Beispiel #11
0
void GraphEditor::handleMoveGraphObjects(const int index)
{
    if (not this->isVisible()) return;
    if (index >= this->count()) return;
    auto draw = this->getCurrentGraphDraw();
    auto desc = tr("Move %1 to %2").arg(draw->getSelectionDescription(~GRAPH_CONNECTION), this->tabText(index));

    //move all selected objects
    for (auto obj : draw->getObjectsSelected())
    {
        obj->setSelected(false);
        this->getGraphDraw(index)->scene()->addItem(obj);
    }

    //reparent all connections based on endpoints:
    std::vector<GraphConnection *> boundaryConnections;
    for (auto obj : this->getGraphObjects(GRAPH_CONNECTION))
    {
        auto conn = dynamic_cast<GraphConnection *>(obj);
        assert(conn != nullptr);

        //Connection has the same endpoints, so make sure that the parent is corrected to the endpoint
        if (conn->getOutputEndpoint().getObj()->scene() == conn->getInputEndpoint().getObj()->scene())
        {
            if (conn->getOutputEndpoint().getObj()->scene() != conn->scene())
            {
                conn->getInputEndpoint().getObj()->scene()->addItem(conn);
            }
        }

        //otherwise stash it for more processing
        else
        {
            boundaryConnections.push_back(conn);
        }
    }

    //create breakers for output endpoints that have to cross
    for (auto conn : boundaryConnections)
    {
        const auto &epOut = conn->getOutputEndpoint();
        const auto &epIn = conn->getInputEndpoint();

        auto sigSlotPairs = conn->getSigSlotPairs();
        if (sigSlotPairs.empty()) sigSlotPairs.resize(1); //add empty
        for (const auto &sigSlotPair : sigSlotPairs)
        {
            auto breaker = findInputBreaker(this, epOut);
            if (breaker != nullptr) continue;

            breaker = new GraphBreaker(epOut.getObj()->draw());
            breaker->setInput(true);
            const auto name = QString("%1[%2]").arg(epOut.getObj()->getId(), epOut.getKey().id);
            breaker->setId(this->newId(name));
            breaker->setNodeName(breaker->getId()); //the first of its name
            breaker->setRotation(epIn.getObj()->rotation());
            breaker->setPos(epIn.getObj()->pos());

            auto outConn = this->makeConnection(epOut, GraphConnectionEndpoint(breaker, breaker->getConnectableKeys().at(0)));
            if (not sigSlotPair.first.isEmpty()) outConn->addSigSlotPair(std::make_pair(sigSlotPair.first, breaker->getConnectableKeys().at(0).id));
            if (outConn->scene() != breaker->scene()) breaker->scene()->addItem(outConn); //use desired parent
        }
    }

    //create breakers for input endpoints that have to cross
    for (auto conn : boundaryConnections)
    {
        const auto &epOut = conn->getOutputEndpoint();
        const auto &epIn = conn->getInputEndpoint();

        auto sigSlotPairs = conn->getSigSlotPairs();
        if (sigSlotPairs.empty()) sigSlotPairs.resize(1); //add empty
        for (const auto &sigSlotPair : sigSlotPairs)
        {
            //find the existing breaker or make a new one
            const auto name = findInputBreaker(this, epOut)->getNodeName();
            GraphBreaker *breaker = nullptr;
            for (auto obj : this->getGraphObjects(GRAPH_BREAKER))
            {
                if (obj->draw() != epIn.getObj()->draw()) continue;
                auto outBreaker = dynamic_cast<GraphBreaker *>(obj);
                assert(outBreaker != nullptr);
                if (outBreaker->isInput()) continue;
                if (outBreaker->getNodeName() != name) continue;
                breaker = outBreaker;
                break;
            }

            //make a new output breaker
            if (breaker == nullptr)
            {
                breaker = new GraphBreaker(epIn.getObj()->draw());
                breaker->setInput(false);
                breaker->setId(this->newId(name));
                breaker->setNodeName(name);
                breaker->setRotation(epOut.getObj()->rotation());
                breaker->setPos(epOut.getObj()->pos());
            }

            //connect to this breaker
            auto inConn = this->makeConnection(epIn, GraphConnectionEndpoint(breaker, breaker->getConnectableKeys().at(0)));
            if (not sigSlotPair.second.isEmpty()) inConn->addSigSlotPair(std::make_pair(breaker->getConnectableKeys().at(0).id, sigSlotPair.second));
            if (inConn->scene() != breaker->scene()) breaker->scene()->addItem(inConn); //use desired parent
        }

        delete conn;
    }

    handleStateChange(GraphState("transform-move", desc));
}