Example #1
1
void RPolyline::appendShape(const RShape& shape, bool prepend) {
//    const RDirected* directed = dynamic_cast<const RDirected*>(&shape);
//    if (directed==NULL) {
//        qWarning() << "RPolyline::appendShape: shape is not a line, arc or polyline: " << shape;
//        return;
//    }

    const RPolyline* pl = dynamic_cast<const RPolyline*>(&shape);
    if (pl!=NULL) {
        if (prepend) {
            for (int i=pl->countSegments()-1; i>=0; --i) {
                QSharedPointer<RShape> s = pl->getSegmentAt(i);
                if (s.isNull()) {
                    continue;
                }
                prependShape(*s);
            }
        }
        else {
            for (int i=0; i<pl->countSegments(); ++i) {
                QSharedPointer<RShape> s = pl->getSegmentAt(i);
                if (s.isNull()) {
                    continue;
                }
                appendShape(*s);
            }
        }
        return;
    }

    const RDirected* directed = NULL;
    double bulge = 0.0;

    const RLine* line = dynamic_cast<const RLine*>(&shape);
    if (line!=NULL) {
        directed = line;
    }
    else {
        const RArc* arc = dynamic_cast<const RArc*>(&shape);
        if (arc!=NULL) {
            bulge = arc->getBulge();
            directed = arc;
        }
    }

    if (directed==NULL) {
        qWarning() << "RPolyline::appendShape: shape is not a line, arc or polyline: " << shape;
        return;
    }

    RVector connectionPoint;
    RVector nextPoint;
    double gap;
    if (prepend) {
        connectionPoint = directed->getEndPoint();
        nextPoint = directed->getStartPoint();
        if (vertices.size()==0) {
            appendVertex(connectionPoint);
        }
        gap = vertices.first().getDistanceTo(connectionPoint);
    }
    else {
        connectionPoint = directed->getStartPoint();
        nextPoint = directed->getEndPoint();
        if (vertices.size()==0) {
            appendVertex(connectionPoint);
        }
        gap = vertices.last().getDistanceTo(connectionPoint);
    }

    if (!RMath::fuzzyCompare(gap, 0.0, 1.0e-4)) {
        qWarning() << "RPolyline::appendShape: arc or line not connected to polyline, gap: " << gap;
    }

    if (prepend) {
        prependVertex(nextPoint);
        setBulgeAt(0, bulge);
    }
    else {
        appendVertex(nextPoint);
        setBulgeAt(bulges.size()-2, bulge);
    }
}
Example #2
0
void CanvasController::setup()
{
    // Padding is between each one of the two areas and the window
    double padding = 10;
    // Proportions for screen areas
    double canvasWidthRelative = 0.8;
    double toolsWidthRelative = 1 - canvasWidthRelative;

    double canvasWidth = window.getWidth()*canvasWidthRelative - 2*padding + padding/2;
    double canvasHeight = window.getHeight() - 2*padding;
    double toolsWidth = window.getWidth()*toolsWidthRelative - 2*padding + padding/2;
    double toolsHeight = window.getHeight() - 2*padding;

    // Create area objects
    backgroundArea = new Rectangle(Point(0, 0, 0), window.getWidth(), window.getHeight());
    canvasArea = new Rectangle(Point(padding, padding, 0), canvasWidth, canvasHeight);
    toolsArea = new Rectangle(Point(canvasWidth + 2*padding, padding, 0), toolsWidth, toolsHeight);

    // Responders
    canvasArea->setRespondsToMouseButtonDown(false);

    // Color them
    backgroundArea->setColor(Color::grayColor().withHue(0.75));
    canvasArea->setColor(Color::whiteColor());
    toolsArea->setColor(Color::whiteColor().withAlpha(0.5));

    // Add to hierarchy
    appendShape(backgroundArea);
    appendShape(canvasArea);
    appendShape(toolsArea);
}
void CustomGraphicsScene::appendVerticalLine()
{
	QPointF scenePosition = sceneRect().center();

	//
	// Если выделена фигура, то новую добавляем чуть правее
	// Избегаем момента, когда выделена горизонтальная линия, чтобы не добавлять линию в самый конец
	//
	Shape* selectedShape = 0;
	const QList<QGraphicsItem*> selectedShapes = selectedItems();
	if (!selectedShapes.isEmpty()
		&& selectedShapes.size() == 1
		&& !dynamic_cast<HorizontalLineShape*>(selectedShapes.last())
		&& (selectedShape = dynamic_cast<Shape*>(selectedShapes.last()))) {
		scenePosition = selectedShape->scenePos();
		scenePosition.setX(scenePosition.x() + selectedShape->boundingRect().width() + SHAPE_MOVE_DELTA);
	}
	//
	// В противном случае добавляем линию по середине видимой части сцены, если подключены представления
	//
	else if (!views().isEmpty()) {
		if (QGraphicsView* view = views().last()) {
			const QRect viewportRect(0, 0, view->viewport()->width(), view->viewport()->height());
			const QRectF visibleSceneRect = view->mapToScene(viewportRect).boundingRect();
			scenePosition = visibleSceneRect.center();
		}
	}

	//
	// Добавляем линию
	//
	appendShape(new VerticalLineShape(scenePosition));
}
void CustomGraphicsScene::appendNote(const QString& _text)
{
	QPointF scenePosition = sceneRect().center();

	//
	// Если выделена карточка, то заметку добавляем справа-сверху на углу карточки
	//
	CardShape* selectedCard = 0;
	if (!selectedItems().isEmpty()
		&& selectedItems().size() == 1
		&& (selectedCard = dynamic_cast<CardShape*>(selectedItems().last()))) {
		scenePosition = selectedCard->scenePos();
		scenePosition.setX(scenePosition.x() + selectedCard->boundingRect().width() - SHAPE_MICROMOVE_DELTA);
		scenePosition.setY(scenePosition.y() - SHAPE_MICROMOVE_DELTA);
	}
	//
	// В противном случае добавляем заметку по середине видимой части сцены, если подключены представления
	//
	else if (!views().isEmpty()) {
		if (QGraphicsView* view = views().last()) {
			const QRect viewportRect(0, 0, view->viewport()->width(), view->viewport()->height());
			const QRectF visibleSceneRect = view->mapToScene(viewportRect).boundingRect();
			scenePosition = visibleSceneRect.center();
		}
	}

	//
	// Добавляем заметку
	//
	appendShape(new NoteShape(_text, scenePosition));
}
Example #5
0
void RPolyline::appendShape(const RShape& shape) {
    const RDirected* directed = dynamic_cast<const RDirected*>(&shape);
    if (directed==NULL) {
        qWarning("RPolyline::appendShape: shape is not a line, arc or polyline");
        return;
    }

    const RPolyline* pl = dynamic_cast<const RPolyline*>(&shape);
    if (pl!=NULL) {
        for (int i=0; i<pl->countSegments(); ++i) {
            QSharedPointer<RShape> s = pl->getSegmentAt(i);
            if (s.isNull()) {
                continue;
            }
            appendShape(*s.data());
        }
    }

    double bulge = 0.0;
    const RArc* arc = dynamic_cast<const RArc*>(&shape);
    if (arc!=NULL) {
        bulge = arc->getBulge();
    }

    if (vertices.size()==0) {
        appendVertex(directed->getStartPoint());
    }

    appendVertex(directed->getEndPoint());
    setBulgeAt(bulges.size()-2, bulge);
}
void CustomGraphicsScene::removeShape(Shape* _shape)
{
	if (m_shapes.contains(_shape)) {
		//
		// Удаляем детей
		//
		for (QGraphicsItem* childItem : _shape->childItems()) {
			if (Shape* childShape = dynamic_cast<Shape*>(childItem)) {
				removeShape(childShape);
			}
		}

		//
		// Определяем внешние элементы
		//
		Shape* previousCard = nullptr;
		Shape* nextCard = nullptr;
		if (CardShape* cardShape = dynamic_cast<CardShape*>(_shape)) {
			if (Flow* startFlow = cardFlow(cardShape, CARD_ON_FLOW_END)) {
				previousCard = startFlow->startShape();
			}
			if (Flow* endFlow = cardFlow(cardShape, CARD_ON_FLOW_START)) {
				nextCard = endFlow->endShape();
			}
		}

		//
		// Удаляем сам элемент
		//
		QList<Shape *> items; items.append(_shape);
		QList<Shape *> all = m_shapes;
		bool found;
		do {
			found = false;
			for (int i = 0; i < all.count(); ++i) {
				if (Flow* item=dynamic_cast<Flow *>(all[i])) {
					if ((items.contains(item->endShape()) || items.contains(item->startShape())) && !items.contains(item)) {
						items << item, found = true;
					}
				}
			}
		} while (found);

		for(int i = items.count()-1; i>=0; --i) {
			removeItem(items[i]);
			disconnect(_shape, SIGNAL(stateIsAboutToBeChangedByUser()), this, SIGNAL(stateChangedByUser()));
			m_shapes.removeAll(items[i]);
			delete items[i];
		}

		//
		// Если надо добавляем связь между разорванными элементами
		//
		if (previousCard != nullptr && nextCard != nullptr) {
			appendShape(new ArrowFlow(previousCard, nextCard));
		}
	}
}
Example #7
0
void RPolyline::prependShape(const RShape& shape) {
    appendShape(shape, true);
//    const RDirected* directed = dynamic_cast<const RDirected*>(&shape);
//    if (directed==NULL) {
//        qWarning() << "RPolyline::prependShape: shape is not a line, arc or polyline: " << shape;
//        return;
//    }

//    const RPolyline* pl = dynamic_cast<const RPolyline*>(&shape);
//    if (pl!=NULL) {
//        for (int i=pl->countSegments()-1; i>=0; --i) {
//            QSharedPointer<RShape> s = pl->getSegmentAt(i);
//            if (s.isNull()) {
//                continue;
//            }
//            prependShape(*s.data());
//        }
//    }

//    double bulge = 0.0;
//    const RArc* arc = dynamic_cast<const RArc*>(&shape);
//    if (arc!=NULL) {
//        bulge = arc->getBulge();
//    }

//    const RLine* line = dynamic_cast<const RLine*>(&shape);
//    if (line!=NULL) {
//        directed = line;
//    }

//    if (vertices.size()==0) {
//        prependVertex(directed->getEndPoint());
//    }

//    if (!vertices.last().equalsFuzzy(directed->getEndPoint())) {
//        qWarning("RPolyline::prependShape: arc not connected to polyline");
//    }

//    prependVertex(directed->getStartPoint());
//    setBulgeAt(0, bulge);
}
void CustomGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* _event)
{
	//
	// Обработку производим только после перемещения мыши
	//
	if (m_afterMoving) {
		//
		// 1. Перемещение карточки на связь
		//
		QList<Shape*> selected = selectedShapes();
		CardShape* selectedCard = nullptr;
		ArrowFlow* selectedFlow = nullptr;
		if (selected.size() == 2) {
			if (dynamic_cast<CardShape*>(selected.first())) {
				selectedCard = dynamic_cast<CardShape*>(selected.first());
				selectedFlow = dynamic_cast<ArrowFlow*>(selected.last());
			} else {
				selectedCard = dynamic_cast<CardShape*>(selected.last());
				selectedFlow = dynamic_cast<ArrowFlow*>(selected.first());
			}
			//
			// Если это действительно перемещение карточки на связь
			//
			if (selectedCard != nullptr
				&& selectedFlow != nullptr
				&& selectedFlow->startShape() != selectedCard
				&& selectedFlow->endShape() != selectedCard) {
				//
				// Изымаем карточку из сцены
				//
				takeShape(selectedCard);

				//
				// Определяем элементы к которым теперь будет присоединена карточка
				//
				CardShape* previousCard = dynamic_cast<CardShape*>(selectedFlow->startShape());
				CardShape* nextCard = dynamic_cast<CardShape*>(selectedFlow->endShape());
				//
				// Заменяем старую связь на новые
				//
				removeShape(selectedFlow);
				appendShape(new ArrowFlow(previousCard, selectedCard));
				if (hasCards(selectedCard)) {
					appendShape(new ArrowFlow(lastCard(selectedCard), nextCard));
				} else {
					appendShape(new ArrowFlow(selectedCard, nextCard));
				}

				//
				// Меняем порядок следования фигур
				//
				insertShape(selectedCard, previousCard);

				//
				// Если предыдущая карточка вложена в группирующий элемент
				//
				QGraphicsItem* previousParentItem = previousCard->parentItem();
				QGraphicsItem* nextParentItem = nextCard->parentItem();
				bool handled = false;
				if (previousParentItem != nullptr) {
					const QRectF selectedCardRect = selectedCard->mapToScene(selectedCard->boundingRect()).boundingRect();
					const QRectF parentCardRect = previousParentItem->mapToScene(previousParentItem->boundingRect()).boundingRect();
					//
					// ... и если текущая карточка тоже помещена внутрь группирующего элемента
					//
					if (parentCardRect.contains(selectedCardRect)) {
						//
						// ... поместим её внутрь
						//
						const QPointF lastPos = selectedCard->scenePos();
						selectedCard->setParentItem(previousParentItem);
						selectedCard->setPos(previousParentItem->mapFromScene(lastPos));
						handled = true;
					}
				}
				//
				// Если следующая карточка вложена в группирующий элемент
				//
				if (!handled
					&& nextParentItem != nullptr) {
					const QRectF selectedCardRect = selectedCard->mapToScene(selectedCard->boundingRect()).boundingRect();
					const QRectF parentCardRect = nextParentItem->mapToScene(nextParentItem->boundingRect()).boundingRect();
					//
					// ... и если текущая карточка тоже помещена внутрь группирующего элемента
					//
					if (parentCardRect.contains(selectedCardRect)) {
						//
						// ... поместим её внутрь
						//
						const QPointF lastPos = selectedCard->scenePos();
						selectedCard->setParentItem(nextParentItem);
						selectedCard->setPos(nextParentItem->mapFromScene(lastPos));
						handled = true;
					}
				}
				//
				// Если не удалось вложить, то убираем родителя у элемента
				//
				if (!handled
					&& selectedCard->parentItem() != nullptr) {
					const QPointF lastPos = selectedCard->scenePos();
					selectedCard->setParentItem(nullptr);
					selectedCard->setPos(lastPos);
				}
			}
		}

		//
		// 2. Обработка вложения и вытаскивания элементов из групп сцен и папок
		//
		selected = selectedShapes();
		if (selected.size() == 1) {
			selectedCard = dynamic_cast<CardShape*>(selected.first());
			if (selectedCard != nullptr) {
				//
				// Определим, есть ли группирующий элемент, помеченный на вложение
				//
				CardShape* parentCard = nullptr;
				for (Shape* shape : shapes()) {
					if (CardShape* card = dynamic_cast<CardShape*>(shape)) {
						if (card->isOnInstertionState()) {
							parentCard = card;
							break;
						}
					}
				}

				//
				// Если это перемещение карточки внутри своего родителя, просто снимем режим выделения
				//
				if (parentCard != nullptr
					&& selectedCard->parentItem() == parentCard) {
					parentCard->setOnInstertionState(false);
				}
				//
				// В противном случае
				//
				else {
					//
					// Вложение
					//
					if (parentCard != nullptr) {
						//
						// Изымаем карточку из сцены
						//
						takeShape(selectedCard);

						//
						// Если у группирующего элемента есть дети, то связываем с последней карточкой
						//
						if (hasCards(parentCard)) {
							//
							// Определяем элементы к которым теперь будет присоединена карточка
							//
							CardShape* previousCard = dynamic_cast<CardShape*>(lastCard(parentCard));
							Flow* previousCardFlow = cardFlow(previousCard, CARD_ON_FLOW_START);
							if (previousCardFlow != nullptr) {
								CardShape* nextCard = dynamic_cast<CardShape*>(previousCardFlow->endShape());
								//
								// Заменяем старую связь на новые
								//
								removeShape(previousCardFlow);
								if (hasCards(selectedCard)) {
									appendShape(new ArrowFlow(lastCard(selectedCard), nextCard));
								} else {
									appendShape(new ArrowFlow(selectedCard, nextCard));
								}
							}
							appendShape(new ArrowFlow(previousCard, selectedCard));

							//
							// Меняем порядок следования фигур
							//
							insertShape(selectedCard, previousCard);
						}
						//
						// Если детей нет, то связываем непосредственно с группирующим элементом
						//
						else {
							//
							// Определяем элементы к которым теперь будет присоединена карточка
							//
							CardShape* previousCard = parentCard;
							Flow* previousCardFlow = cardFlow(previousCard, CARD_ON_FLOW_START);
							if (previousCardFlow != nullptr) {
								CardShape* nextCard = dynamic_cast<CardShape*>(previousCardFlow->endShape());
								//
								// Заменяем старую связь на новые
								//
								removeShape(previousCardFlow);
								if (hasCards(selectedCard)) {
									appendShape(new ArrowFlow(lastCard(selectedCard), nextCard));
								} else {
									appendShape(new ArrowFlow(selectedCard, nextCard));
								}
							}
							appendShape(new ArrowFlow(previousCard, selectedCard));

							//
							// Меняем порядок следования фигур
							//
							insertShape(selectedCard, previousCard);
						}

						//
						// Назначаем нового родителя
						//
						const QPointF lastPos = selectedCard->scenePos();
						selectedCard->setParentItem(parentCard);
						selectedCard->setPos(parentCard->mapFromScene(lastPos));
						parentCard->setOnInstertionState(false);
					}
					//
					// Вытаскивание - соединяем с последней карточкой в сценарии
					//
					else if (selectedCard->parentItem() != nullptr) {
						//
						// Изымаем карточку из сцены
						//
						takeShape(selectedCard);

						//
						// Определяем элемент к которому теперь будет присоединена карточка
						//
						CardShape* previousCard =  dynamic_cast<CardShape*>(lastCard());
						//
						// Добавляем связь
						//
						appendShape(new ArrowFlow(previousCard, selectedCard));

						//
						// Меняем порядок следования фигур
						//
						insertShape(selectedCard, previousCard);

						//
						// Убираем родителя
						//
						const QPointF lastPos = selectedCard->scenePos();
						selectedCard->setParentItem(nullptr);
						selectedCard->setPos(lastPos);
					}
				}
			}
		}
	}

	update();

	QGraphicsScene::mouseReleaseEvent(_event);

	m_afterMoving = false;
}
void CustomGraphicsScene::appendCard(int _cardType, const QString& _title, const QString& _description)
{
	QPointF scenePosition = sceneRect().center();

	//
	// Если выделена карточка
	//
	CardShape* selectedCard = nullptr;
	CardShape* previousCard = nullptr;
	CardShape* nextCard = nullptr;
	CardShape* parentCard = nullptr;
	if (!selectedItems().isEmpty()
		&& selectedItems().size() == 1
		&& (selectedCard = dynamic_cast<CardShape*>(selectedItems().last()))) {
		//
		// Если карточка вложена в группирующую, то расширяем родителя и вкладываем карту в него
		//
		if (selectedCard->parentItem() != nullptr) {
			//
			// Запомним родителя
			//
			parentCard = dynamic_cast<CardShape*>(selectedCard->parentItem());
		}

		//
		// Если выделен группирующий элемент, то соединять будем с последним из его детей
		//
		if (hasCards(selectedCard)) {
			selectedCard = dynamic_cast<CardShape*>(lastCard(selectedCard));
		}

		//
		// Предыдущей будет выделенная
		//
		previousCard = selectedCard;

		//
		// Настроим позицию для добавления новой карточки
		//
		scenePosition = previousCard->scenePos();
		scenePosition.setX(scenePosition.x() + previousCard->boundingRect().width() + SHAPE_MOVE_DELTA);
		scenePosition.setY(scenePosition.y() + previousCard->boundingRect().height() + SHAPE_MOVE_DELTA);

		//
		// Определим карточку, которая будет следовать за новой
		//
		Flow* flow = cardFlow(previousCard, CARD_ON_FLOW_START);
		if (flow != nullptr) {
			nextCard = dynamic_cast<CardShape*>(flow->endShape());
			removeShape(flow);
		}
	}
	//
	// В противном случае добавляем карточку после самой последней карточки, если карточки уже есть
	//
	else if (hasCards()) {
		//
		// Определим последнюю карточку
		//
		Shape* lastCardShape = lastCard();
		previousCard = dynamic_cast<CardShape*>(lastCardShape);

		//
		// Настроим позицию для добавления новой карточки
		//
		scenePosition = previousCard->scenePos();
		scenePosition.setX(scenePosition.x() + previousCard->boundingRect().width() + SHAPE_MOVE_DELTA);
		scenePosition.setY(scenePosition.y() + previousCard->boundingRect().height() + SHAPE_MOVE_DELTA);
	}
	//
	// В противном случае добавляем карточку по середине видимой части сцены, если подключены представления
	//
	else if (!views().isEmpty()) {
		if (QGraphicsView* view = views().last()) {
			const QRect viewportRect(0, 0, view->viewport()->width(), view->viewport()->height());
			const QRectF visibleSceneRect = view->mapToScene(viewportRect).boundingRect();
			scenePosition = visibleSceneRect.center();
		}
	}

	//
	// Добавляем карточку
	//
	CardShape* newCard = new CardShape((CardShape::CardType)_cardType, _title, _description, scenePosition, parentCard);
	insertShape(newCard, previousCard);
	//
	// ... корректируем позицию вкладываемой карточки
	//
	if (parentCard != nullptr) {
		const QPointF newPos = parentCard->mapFromScene(newCard->scenePos());
		const QPointF newBottomRightPos = newPos + QPointF(newCard->boundingRect().width(), newCard->boundingRect().height());
		//
		newCard->setParentItem(parentCard);
		newCard->setPos(newPos);
		//
		// ... и масштабируем родителя, если нужно
		//
		if (!parentCard->contains(newBottomRightPos)) {
			QSizeF newSize = parentCard->size();
			if (newSize.width() <= newBottomRightPos.x()) {
				newSize.setWidth(newBottomRightPos.x() + SHAPE_MICROMOVE_DELTA);
			}
			if (newSize.height() <= newBottomRightPos.y()) {
				newSize.setHeight(newBottomRightPos.y() + SHAPE_MICROMOVE_DELTA);
			}
			parentCard->setSize(newSize);
		}
	}

	//
	// Соединяем с предыдущей
	//
	if (previousCard != nullptr) {
		appendShape(new ArrowFlow(previousCard, newCard, parentCard));
	}

	//
	// Соединяем со следующей
	//
	if (nextCard != nullptr) {
		appendShape(new ArrowFlow(newCard, nextCard, parentCard));
	}
}