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 "linkcontroller.h" 0021 0022 #include <QDebug> 0023 #include <QRectF> 0024 #include <cmath> 0025 0026 #include "mindnode.h" 0027 namespace mindmap 0028 { 0029 0030 LinkController::LinkController(QObject* parent) : MindItem(MindItem::LinkType, parent) 0031 { 0032 connect(this, &LinkController::visibleChanged, this, 0033 [this]() 0034 { 0035 if(!m_end || !m_constraint) 0036 return; 0037 m_end->setVisible(isVisible()); 0038 }); 0039 connect(this, &LinkController::geometryChanged, this, &LinkController::computeNormalizedRect); 0040 connect(this, &LinkController::endChanged, this, &LinkController::computeNormalizedRect); 0041 connect(this, &LinkController::startChanged, this, &LinkController::computeNormalizedRect); 0042 } 0043 0044 void LinkController::setDirection(const Direction& direction) 0045 { 0046 if(m_dir == direction) 0047 return; 0048 m_dir= direction; 0049 emit directionChanged(); 0050 } 0051 0052 LinkController::Direction LinkController::direction() const 0053 { 0054 return m_dir; 0055 } 0056 0057 PositionedItem* LinkController::start() const 0058 { 0059 return m_start; 0060 } 0061 0062 void LinkController::computeNormalizedRect() 0063 { 0064 if(!m_start) 0065 return; 0066 0067 QRectF rect{m_start->centerPoint().x(), m_start->centerPoint().y(), width(), height()}; 0068 0069 auto o= m_orient; 0070 if(rect.height() < 0 && rect.width() < 0) 0071 m_orient= LeftTop; 0072 else if(rect.height() < 0) 0073 m_orient= RightTop; 0074 else if(rect.width() < 0) 0075 m_orient= LeftBottom; 0076 else 0077 m_orient= RightBottom; 0078 0079 if(o != m_orient) 0080 emit orientationChanged(); 0081 setNormalizedRect(rect.normalized()); 0082 } 0083 0084 void LinkController::setStart(PositionedItem* start) 0085 { 0086 if(start == m_start) 0087 return; 0088 0089 if(m_start) 0090 { 0091 m_start->removeLink(this); 0092 disconnect(m_start, 0, this, 0); 0093 } 0094 0095 m_start= start; 0096 0097 if(nullptr != m_start) 0098 { 0099 m_start->addLink(this); 0100 connect(m_start, &MindNode::positionChanged, this, &LinkController::startPointChanged); 0101 connect(m_start, &MindNode::positionChanged, this, &LinkController::geometryChanged); 0102 connect(m_start, &MindNode::positionChanged, this, &LinkController::startBoxChanged); 0103 connect(m_start, &MindNode::widthChanged, this, &LinkController::startBoxChanged); 0104 connect(m_start, &MindNode::heightChanged, this, &LinkController::startBoxChanged); 0105 connect(m_start, &MindNode::visibleChanged, this, &LinkController::setVisible); 0106 connect(m_start, &MindNode::textChanged, this, 0107 [this]() 0108 { 0109 emit startBoxChanged(); 0110 emit startPointChanged(); 0111 }); 0112 } 0113 emit startChanged(); 0114 } 0115 0116 void LinkController::setEnd(PositionedItem* end) 0117 { 0118 if(end == m_end) 0119 return; 0120 0121 if(m_end) 0122 { 0123 disconnect(m_end, 0, this, 0); 0124 } 0125 m_end= end; 0126 if(nullptr != m_end) 0127 { 0128 connect(m_end, &MindNode::positionChanged, this, &LinkController::endPointChanged); 0129 connect(m_end, &MindNode::positionChanged, this, &LinkController::geometryChanged); 0130 connect(m_end, &MindNode::positionChanged, this, &LinkController::endBoxChanged); 0131 connect(m_end, &MindNode::widthChanged, this, &LinkController::endBoxChanged); 0132 connect(m_end, &MindNode::heightChanged, this, &LinkController::endBoxChanged); 0133 connect(m_end, &MindNode::visibleChanged, this, &LinkController::setVisible); 0134 connect(m_end, &MindNode::textChanged, this, 0135 [this]() 0136 { 0137 emit endBoxChanged(); 0138 emit endPointChanged(); 0139 }); 0140 } 0141 0142 emit endChanged(); 0143 } 0144 0145 qreal LinkController::width() const 0146 { 0147 if(!end() || !start()) 0148 return 0.0; 0149 return end()->centerPoint().x() - start()->centerPoint().x(); 0150 } 0151 0152 qreal LinkController::height() const 0153 { 0154 if(!end() || !start()) 0155 return 0.0; 0156 return end()->centerPoint().y() - start()->centerPoint().y(); 0157 } 0158 0159 PositionedItem* LinkController::end() const 0160 { 0161 return m_end; 0162 } 0163 0164 QPointF LinkController::endPoint() const 0165 { 0166 if(nullptr == m_end) 0167 return {}; 0168 return m_end->centerPoint(); 0169 } 0170 0171 QPointF LinkController::startPoint() const 0172 { 0173 if(nullptr == m_start) 0174 return {}; 0175 return m_start->centerPoint(); 0176 } 0177 0178 QPointF LinkController::topLeftCorner() const 0179 { 0180 return m_normalizedRect.topLeft(); 0181 } 0182 0183 qreal LinkController::normalizedWidth() const 0184 { 0185 return m_normalizedRect.width(); 0186 } 0187 0188 qreal LinkController::normalizedHeight() const 0189 { 0190 return m_normalizedRect.height(); 0191 } 0192 0193 LinkController::Orientation LinkController::orientation() const 0194 { 0195 return m_orient; 0196 } 0197 0198 void LinkController::computePosition() 0199 { 0200 auto pos1= m_start->position(); 0201 pos1.setY(pos1.y() + 50); 0202 m_end->setNextPosition(pos1, this); 0203 } 0204 0205 void LinkController::setNormalizedRect(QRectF rect) 0206 { 0207 if(m_normalizedRect == rect) 0208 return; 0209 m_normalizedRect= rect; 0210 emit normalizedRectChanged(); 0211 } 0212 0213 float LinkController::getStiffness() const 0214 { 0215 return m_stiffness; 0216 } 0217 0218 void LinkController::setStiffness(float stiffness) 0219 { 0220 m_stiffness= stiffness; 0221 } 0222 0223 void LinkController::cleanUpLink() 0224 { 0225 m_start->removeLink(this); 0226 } 0227 0228 float LinkController::getLength() const 0229 { 0230 auto length= 100.; 0231 auto rect1= m_start->boundingRect(); 0232 auto diag1= std::sqrt(std::pow(rect1.width(), 2) + std::pow(rect1.height(), 2)) / 2; 0233 0234 auto rect2= m_end->boundingRect(); 0235 auto diag2= std::sqrt(std::pow(rect2.width(), 2) + std::pow(rect2.height(), 2)) / 2; 0236 0237 auto realDiag= std::max(diag1, diag2); 0238 0239 auto length1= static_cast<float>(length + 2 * realDiag); 0240 if(m_end == nullptr || m_start == nullptr) 0241 return length1; 0242 0243 auto nodeCount= static_cast<int>(m_start->subLinks().size()); 0244 0245 QSet<LinkController*> a; 0246 auto endNodeCount= (m_end->subNodeCount(a) + nodeCount) / 3; 0247 auto length2= static_cast<float>(length * (1 + endNodeCount)); 0248 0249 return std::max(length1, length2); 0250 } 0251 0252 const QRectF LinkController::endBox() const 0253 { 0254 return m_end ? m_end->boundingRect() : QRectF{}; 0255 } 0256 0257 const QRectF LinkController::startBox() const 0258 { 0259 return m_start ? m_start->boundingRect() : QRectF{}; 0260 } 0261 0262 bool LinkController::color() const 0263 { 0264 return m_color; 0265 } 0266 0267 void LinkController::setColor(const bool& newColor) 0268 { 0269 if(m_color == newColor) 0270 return; 0271 m_color= newColor; 0272 emit colorChanged(); 0273 } 0274 0275 const Qt::PenStyle& LinkController::lineStyle() const 0276 { 0277 return m_lineStyle; 0278 } 0279 0280 void LinkController::setLineStyle(const Qt::PenStyle& newLineStyle) 0281 { 0282 if(m_lineStyle == newLineStyle) 0283 return; 0284 m_lineStyle= newLineStyle; 0285 emit lineStyleChanged(); 0286 } 0287 0288 bool LinkController::constraint() const 0289 { 0290 return m_constraint; 0291 } 0292 0293 void LinkController::setConstraint(bool newConstraint) 0294 { 0295 if(m_constraint == newConstraint) 0296 return; 0297 m_constraint= newConstraint; 0298 emit constraintChanged(); 0299 } 0300 0301 QString LinkController::toString(bool) const 0302 { 0303 return id(); 0304 } 0305 } // namespace mindmap