File indexing completed on 2024-05-12 05:40:25
0001 /*************************************************************************** 0002 * Copyright (C) 2019 by Renaud Guezennec * 0003 * http://www.rolisteam.org/contact * 0004 * * 0005 * This software is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 #include "mindmap/data/link.h" 0021 0022 #include "mindnode.h" 0023 0024 #include <QDebug> 0025 #include <QLineF> 0026 #include <QRectF> 0027 #include <QUuid> 0028 #include <cmath> 0029 0030 namespace mindmap 0031 { 0032 float Link::m_minimunLenght= 150.f; 0033 Link::Link(QObject* parent) : QObject(parent), m_uuid(QUuid::createUuid().toString(QUuid::WithoutBraces)) 0034 { 0035 setText(tr("is linked")); 0036 } 0037 0038 void Link::setDirection(const mindmap::ArrowDirection& direction) 0039 { 0040 if(direction == m_dir) 0041 return; 0042 m_dir= direction; 0043 emit directionChanged(); 0044 } 0045 0046 mindmap::ArrowDirection Link::direction() const 0047 { 0048 return m_dir; 0049 } 0050 0051 MindNode* Link::start() const 0052 { 0053 return m_start; 0054 } 0055 0056 QString Link::p1Id() const 0057 { 0058 return m_start ? m_start->id() : QString(); 0059 } 0060 0061 QString Link::p2Id() const 0062 { 0063 return m_end ? m_end->id() : QString(); 0064 } 0065 0066 void Link::setStart(MindNode* start) 0067 { 0068 if(start == m_start) 0069 return; 0070 if(m_start) 0071 disconnect(m_start, 0, this, 0); 0072 m_start= start; 0073 emit startPointChanged(); 0074 0075 connect(m_start, &MindNode::positionChanged, this, [this]() { 0076 emit startPositionChanged(); 0077 emit endPositionChanged(); 0078 }); 0079 } 0080 0081 MindNode* Link::endNode() const 0082 { 0083 return m_end; 0084 } 0085 0086 QPointF Link::endPoint() const 0087 { 0088 if(nullptr == m_end) 0089 return {}; 0090 return m_end->centerPoint(); 0091 } 0092 0093 QPointF Link::startPoint() const 0094 { 0095 if(nullptr == m_start) 0096 return {}; 0097 return m_start->centerPoint(); 0098 } 0099 0100 void Link::setEnd(MindNode* end) 0101 { 0102 if(end == m_end) 0103 return; 0104 if(m_end) 0105 disconnect(m_end, 0, this, 0); 0106 m_end= end; 0107 emit endPointChanged(); 0108 0109 connect(m_end, &MindNode::positionChanged, this, [this]() { 0110 emit startPositionChanged(); 0111 emit endPositionChanged(); 0112 }); 0113 } 0114 0115 QPointF Link::computePoint(bool p1) const 0116 { 0117 QLineF line(startPoint(), endPoint()); 0118 0119 auto node= p1 ? m_start : m_end; 0120 0121 if(!node) 0122 return {}; 0123 0124 auto top= QLineF(node->boundingRect().topLeft(), node->boundingRect().topRight()); 0125 auto bottom= QLineF(node->boundingRect().bottomLeft(), node->boundingRect().bottomRight()); 0126 auto left= QLineF(node->boundingRect().topLeft(), node->boundingRect().bottomLeft()); 0127 auto right= QLineF(node->boundingRect().topRight(), node->boundingRect().bottomRight()); 0128 0129 QPointF res; 0130 auto intersect= line.intersects(top, &res); 0131 if(intersect != QLineF::BoundedIntersection) 0132 intersect= line.intersects(bottom, &res); 0133 0134 if(intersect != QLineF::BoundedIntersection) 0135 intersect= line.intersects(left, &res); 0136 0137 if(intersect != QLineF::BoundedIntersection) 0138 line.intersects(right, &res); 0139 0140 return res; 0141 } 0142 0143 QPointF Link::p1() const 0144 { 0145 return computePoint(true); 0146 } 0147 0148 QPointF Link::p2() const 0149 { 0150 return computePoint(false); 0151 } 0152 0153 QString Link::id() const 0154 { 0155 return m_uuid; 0156 } 0157 0158 void Link::computePosition() 0159 { 0160 auto pos1= m_start->position(); 0161 pos1.setY(pos1.y() + 50); 0162 m_end->setNextPosition(pos1, this); 0163 } 0164 0165 void Link::setText(const QString& text) 0166 { 0167 if(m_text == text) 0168 return; 0169 m_text= text; 0170 emit textChanged(); 0171 } 0172 0173 void Link::setId(const QString& text) 0174 { 0175 if(m_uuid == text) 0176 return; 0177 m_uuid= text; 0178 emit idChanged(); 0179 } 0180 0181 float Link::getStiffness() const 0182 { 0183 return m_stiffness; 0184 } 0185 0186 void Link::setStiffness(float stiffness) 0187 { 0188 m_stiffness= stiffness; 0189 } 0190 0191 void Link::cleanUpLink() 0192 { 0193 m_start->removeLink(this); 0194 } 0195 0196 float Link::getLength() const 0197 { 0198 QLineF line(p1(), p2()); 0199 auto r1= m_start->boundingRect(); 0200 auto r2= m_end->boundingRect(); 0201 0202 auto diagonal= std::sqrt(r1.width() / 2 * r1.width() / 2 + r1.height() / 2 * r1.height() / 2) 0203 + std::sqrt(r2.width() / 2 * r2.width() / 2 + r2.height() / 2 * r2.height() / 2) + m_minimunLenght; 0204 auto length= std::max(static_cast<float>(diagonal), std::max(static_cast<float>(line.length()), m_minimunLenght)); 0205 0206 if(m_end == nullptr || m_start == nullptr) 0207 return length; 0208 0209 auto nodeCount= static_cast<int>(m_start->subLinks().size()); 0210 0211 auto endNodeCount= (m_end->subNodeCount() + nodeCount) / 3; 0212 auto length2= static_cast<float>(length * (1 + endNodeCount)); 0213 0214 return std::max(length, length2); 0215 } 0216 0217 void Link::setVisible(bool vi) 0218 { 0219 if(m_visible == vi) 0220 return; 0221 m_visible= vi; 0222 emit visibleChanged(); 0223 0224 if(nullptr != m_end) 0225 m_end->setVisible(vi); 0226 } 0227 0228 bool Link::isVisible() const 0229 { 0230 return m_visible; 0231 } 0232 0233 QString Link::text() const 0234 { 0235 return m_text; 0236 } 0237 0238 void Link::setMinimumLenght(float v) 0239 { 0240 m_minimunLenght= v; 0241 } 0242 0243 QString Link::toString(bool withLabel) 0244 { 0245 return withLabel ? QStringLiteral("%1 [label=\"Link text:%2\"]").arg(m_uuid, m_text) : m_uuid; 0246 } 0247 } // namespace mindmap