nodes are scalable with ctrl + plus/minus

master
Denes Matetelki 14 years ago
parent 565c45ce6a
commit 0f21ae4faa

@ -38,30 +38,6 @@ Node *Edge::destNode() const
return m_destNode; return m_destNode;
} }
/** @note This is brute force. Isn't there a simple fv for this?
* The precision is not the best either
*/
QPointF firstNotContainedPoint(const QLineF &line,
const QRectF &rect,
bool reverse = false)
{
if (reverse)
{
for (qreal t = 1; t!=0; t-=0.01)
{
if (!rect.contains(line.pointAt(t))) return line.pointAt(t);
}
}
else
{
for (qreal t = 0; t!=1; t+=0.01)
{
if (!rect.contains(line.pointAt(t))) return line.pointAt(t);
}
}
return QPoint(0,0);
}
double Edge::getAngle() const double Edge::getAngle() const
{ {
return m_angle; return m_angle;
@ -74,16 +50,14 @@ void Edge::adjust()
prepareGeometryChange(); prepareGeometryChange();
QLineF line(mapFromItem(m_sourceNode, 0, 0) + QLineF line(m_sourceNode->sceneBoundingRect().center(),
m_sourceNode->boundingRect().center(), m_destNode->sceneBoundingRect().center());
mapFromItem(m_destNode, 0, 0) +
m_destNode->boundingRect().center()); if (line.length() > qreal(20.))
{
m_sourcePoint = m_sourceNode->intersect(line);
m_destPoint = m_destNode->intersect(line,true);
if (line.length() > qreal(20.)) {
m_sourcePoint = firstNotContainedPoint(line,
m_sourceNode->sceneBoundingRect());
m_destPoint = firstNotContainedPoint(line,
m_destNode->sceneBoundingRect(),true);
} else { } else {
m_sourcePoint = m_destPoint = line.p1(); m_sourcePoint = m_destPoint = line.p1();
} }

@ -5,6 +5,7 @@
#include <QMessageBox> #include <QMessageBox>
#include <QFileDialog> #include <QFileDialog>
#include <QtXml> #include <QtXml>
#include <QColorDialog>
#include "node.h" #include "node.h"
#include "edge.h" #include "edge.h"
@ -84,6 +85,8 @@ void GraphWidget::readContentFromXmlFile(const QString &fileName)
m_scene->addItem(node); m_scene->addItem(node);
node->setPos(e.attribute("x").toFloat(), node->setPos(e.attribute("x").toFloat(),
e.attribute("y").toFloat()); e.attribute("y").toFloat());
node->setScale(e.attribute("scale").toFloat());
m_nodeList.append(node); m_nodeList.append(node);
} }
} }
@ -120,10 +123,13 @@ void GraphWidget::writeContentToXmlFile(const QString &fileName)
foreach(Node *node, m_nodeList) foreach(Node *node, m_nodeList)
{ {
QDomElement cn = doc.createElement("nodes"); QDomElement cn = doc.createElement("nodes");
// cn.setAttribute( "id", QString::number(m_nodeList.indexOf(node)));
// no need to store ID: parsing order is preorder.
// cn.setAttribute( "id", QString::number(m_nodeList.indexOf(node)));
cn.setAttribute( "x", QString::number(node->pos().x())); cn.setAttribute( "x", QString::number(node->pos().x()));
cn.setAttribute( "y", QString::number(node->pos().y())); cn.setAttribute( "y", QString::number(node->pos().y()));
cn.setAttribute( "htmlContent", node->toHtml()); cn.setAttribute( "htmlContent", node->toHtml());
cn.setAttribute("scale", QString::number(((QGraphicsTextItem*)node)->scale()));
nodes_root.appendChild(cn); nodes_root.appendChild(cn);
} }
@ -176,8 +182,6 @@ void GraphWidget::writeContentToPngFile(const QString &fileName)
void GraphWidget::keyPressEvent(QKeyEvent *event) void GraphWidget::keyPressEvent(QKeyEvent *event)
{ {
qDebug() << __PRETTY_FUNCTION__;
// esc leaves node editing mode // esc leaves node editing mode
if (event->key() == Qt::Key_Escape && m_editingNode) if (event->key() == Qt::Key_Escape && m_editingNode)
{ {
@ -199,11 +203,13 @@ void GraphWidget::keyPressEvent(QKeyEvent *event)
event->key() == Qt::Key_Delete || // delete node event->key() == Qt::Key_Delete || // delete node
event->key() == Qt::Key_A || // add edge event->key() == Qt::Key_A || // add edge
event->key() == Qt::Key_D || // remove edge event->key() == Qt::Key_D || // remove edge
( event->modifiers() == Qt::ControlModifier && // moving node ( event->modifiers() & Qt::ControlModifier && // moving node
( event->key() == Qt::Key_Up || ( event->key() == Qt::Key_Up ||
event->key() == Qt::Key_Down || event->key() == Qt::Key_Down ||
event->key() == Qt::Key_Left || event->key() == Qt::Key_Left ||
event->key() == Qt::Key_Right)))) event->key() == Qt::Key_Right ||
event->key() == Qt::Key_Plus ||
event->key() == Qt::Key_Minus ))))
{ {
m_parent->statusBarMsg(tr("No active node.")); m_parent->statusBarMsg(tr("No active node."));
return; return;
@ -254,10 +260,24 @@ void GraphWidget::keyPressEvent(QKeyEvent *event)
// zoom in/out // zoom in/out
case Qt::Key_Plus: case Qt::Key_Plus:
if (event->modifiers() & Qt::ControlModifier)
{
m_activeNode->scale(qreal(1.2));
}
else
{
scaleView(qreal(1.2)); scaleView(qreal(1.2));
}
break; break;
case Qt::Key_Minus: case Qt::Key_Minus:
if (event->modifiers() & Qt::ControlModifier)
{
m_activeNode->scale(qreal(1 / 1.2));
}
else
{
scaleView(1 / qreal(1.2)); scaleView(1 / qreal(1.2));
}
break; break;
// Hint mode: select a node vimperator style // Hint mode: select a node vimperator style
@ -359,6 +379,14 @@ void GraphWidget::keyPressEvent(QKeyEvent *event)
m_edgeDeleting = true; m_edgeDeleting = true;
break; break;
case Qt::Key_C:
{
QColorDialog dialog(this);
if (dialog.exec())
QColor color = dialog.selectedColor();
break;
}
default: default:
QGraphicsView::keyPressEvent(event); QGraphicsView::keyPressEvent(event);
} }
@ -554,6 +582,7 @@ void GraphWidget::addFirstNode()
m_scene->addItem(node); m_scene->addItem(node);
node->setPos(-25, -25); node->setPos(-25, -25);
node->setBorder(false); node->setBorder(false);
m_nodeList.append(node); m_nodeList.append(node);
m_activeNode = m_nodeList.first(); m_activeNode = m_nodeList.first();

@ -35,12 +35,11 @@ protected:
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
void wheelEvent(QWheelEvent *event); void wheelEvent(QWheelEvent *event);
void scaleView(qreal scaleFactor);
void drawBackground(QPainter *painter, const QRectF &rect); void drawBackground(QPainter *painter, const QRectF &rect);
private: private:
void scaleView(qreal scaleFactor);
void showNodeNumbers(); void showNodeNumbers();
void showingAllNodeNumbers(const bool &show = true); void showingAllNodeNumbers(const bool &show = true);
void showingNodeNumbersBeginWithNumber(const int &number, void showingNodeNumbersBeginWithNumber(const int &number,

@ -16,7 +16,7 @@ Node::Node(GraphWidget *parent) :
m_graph(parent), m_graph(parent),
m_isActive(false), m_isActive(false),
m_number(-1), m_number(-1),
m_hasBorder(false), m_hasBorder(true),
m_numberIsSpecial(false) m_numberIsSpecial(false)
{ {
setFlag(ItemIsMovable); setFlag(ItemIsMovable);
@ -66,6 +66,11 @@ void Node::removeEdgeFromList(Edge *edge)
} }
} }
void Node::adjustEdges()
{
foreach (EdgeElement element, m_edgeList) element.edge->adjust();
}
void Node::setBorder(const bool &hasBorder) void Node::setBorder(const bool &hasBorder)
{ {
m_hasBorder = hasBorder; m_hasBorder = hasBorder;
@ -90,6 +95,21 @@ void Node::setEditable(const bool &editable)
setTextCursor(c); setTextCursor(c);
} }
void Node::scale(const qreal &factor)
{
qDebug() << factor * QGraphicsTextItem::scale();
if (factor * QGraphicsTextItem::scale() < 0.3 ||
factor * QGraphicsTextItem::scale() > 5 )
return;
// it would make stuff difficult, like limiting the pos. inside scene
// setTransformOriginPoint(boundingRect().center());
QGraphicsTextItem::setScale(factor * QGraphicsTextItem::scale());
adjustEdges();
}
void Node::showNumber(const int &number, void Node::showNumber(const int &number,
const bool& show, const bool& show,
const bool &numberIsSpecial) const bool &numberIsSpecial)
@ -197,6 +217,40 @@ bool Node::isConnected(const Node *node) const
return false; return false;
} }
QPointF Node::intersect(const QLineF &line, const bool &reverse) const
{
// QPainterPath shape;
// shape.addRoundedRect(sceneBoundingRect(), 20.0, 15.0);
// QPainterPath l;
// l.moveTo(sceneBoundingRect().center());
// l.lineTo(line.p2());
// return shape.intersected(l).pointAtPercent(0.5);
/// @but this just does not work, doing it with brute force
QPainterPath path;
path.addRoundedRect(sceneBoundingRect(), 28.0, 28.0);
if (reverse)
{
for (qreal t = 1; t!=0; t-=0.01)
{
if (!path.contains(line.pointAt(t))) return line.pointAt(t);
}
}
else
{
for (qreal t = 0; t!=1; t+=0.01)
{
if (!path.contains(line.pointAt(t))) return line.pointAt(t);
}
}
return QPointF(0,0);
}
QList<Edge *> Node::edgesFrom() const QList<Edge *> Node::edgesFrom() const
{ {
QList<Edge *> list; QList<Edge *> list;
@ -219,29 +273,25 @@ void Node::paint(QPainter *painter,
painter->setPen(Qt::transparent); painter->setPen(Qt::transparent);
painter->setBrush(m_numberIsSpecial ? Qt::green : Qt::yellow); painter->setBrush(m_numberIsSpecial ? Qt::green : Qt::yellow);
painter->drawRoundedRect(QRect(boundingRect().topLeft().toPoint(), painter->drawRoundedRect(boundingRect(), 20.0, 15.0);
boundingRect().bottomRight().toPoint()), 20.0, 15.0);
painter->setBrush(Qt::NoBrush);
} }
else if (m_isActive) // draw background for active node else
{ {
m_hasBorder ?
painter->setPen(m_isActive ? Qt::red : Qt::blue) :
painter->setPen(Qt::transparent); painter->setPen(Qt::transparent);
if (m_isActive)
painter->setBrush(Node::m_orange); painter->setBrush(Node::m_orange);
painter->drawRoundedRect(QRect(boundingRect().topLeft().toPoint(),
boundingRect().bottomRight().toPoint()), 20.0, 15.0); painter->drawRoundedRect(boundingRect(), 20.0, 15.0);
painter->setBrush(Qt::NoBrush);
} }
painter->setBrush(Qt::NoBrush);
// the text itself // the text itself
QGraphicsTextItem::paint(painter, option, w); QGraphicsTextItem::paint(painter, option, w);
if (m_hasBorder)
{
painter->setPen(m_isActive ? Qt::red : Qt::blue);
painter->drawRect(QRect(boundingRect().topLeft().toPoint(),
boundingRect().bottomRight().toPoint() -
QPoint(1,1)));
}
// print num to topleft corner in hint mode. // print num to topleft corner in hint mode.
if (m_number != -1) if (m_number != -1)
@ -268,7 +318,7 @@ QVariant Node::itemChange(GraphicsItemChange change, const QVariant &value)
// the fence is reduced with the size of the node // the fence is reduced with the size of the node
QRectF rect (scene()->sceneRect().topLeft(), QRectF rect (scene()->sceneRect().topLeft(),
scene()->sceneRect().bottomRight() - scene()->sceneRect().bottomRight() -
boundingRect().bottomRight()); boundingRect().bottomRight() * QGraphicsTextItem::scale() );
if (!rect.contains(newPos)) if (!rect.contains(newPos))
{ {
@ -316,6 +366,14 @@ void Node::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
QGraphicsItem::mouseMoveEvent(event); QGraphicsItem::mouseMoveEvent(event);
} }
/// @bug it seems sceneBoundingRect().contains doesn't care about path retval...
QPainterPath Node::shape () const
{
QPainterPath path;
path.addRoundedRect(boundingRect(), 20.0, 15.0);
return path;
}
double Node::doubleModulo(const double &devided, const double &devisor) double Node::doubleModulo(const double &devided, const double &devisor)
{ {
return devided - static_cast<double>(devisor * static_cast<int>(devided return devided - static_cast<double>(devisor * static_cast<int>(devided

@ -19,10 +19,12 @@ public:
void addEdge(Edge *edge, bool startsFromThisNode); void addEdge(Edge *edge, bool startsFromThisNode);
void deleteEdge(Node *otherEnd); void deleteEdge(Node *otherEnd);
void removeEdgeFromList(Edge *edge); void removeEdgeFromList(Edge *edge);
void adjustEdges();
void setBorder(const bool &hasBorder); void setBorder(const bool &hasBorder);
void setActive(const bool &active = true); void setActive(const bool &active = true);
void setEditable(const bool &editable = true); void setEditable(const bool &editable = true);
void scale(const qreal &factor);
void showNumber(const int &number, const bool& show = true, void showNumber(const int &number, const bool& show = true,
const bool &numberIsSpecial = false); const bool &numberIsSpecial = false);
@ -31,6 +33,7 @@ public:
// changing visibility from prot to pub // changing visibility from prot to pub
void keyPressEvent(QKeyEvent *event); void keyPressEvent(QKeyEvent *event);
bool isConnected(const Node *node) const; bool isConnected(const Node *node) const;
QPointF intersect(const QLineF &line, const bool &reverse = false) const;
QList<Edge *> edgesFrom() const; QList<Edge *> edgesFrom() const;
@ -43,6 +46,7 @@ protected:
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
QPainterPath shape () const;
private: private:

Loading…
Cancel
Save