#include "CNodeItem.h" #include "CRectItem.h" #include "CTextItem.h" #include "CLineItem.h" #include #include #include CNodeItem::CNodeItem(const CNodeData data, CNodeItem *parent) : QObject(parent), m_data(data) { m_rectItem = new CRectItem(); m_rectItem->setToolTip(data.remark); m_textItem = new CTextItem(data.name, m_rectItem); m_lineItem = new CLineItem(m_rectItem); updateItemsGeometry(); connectSignalsAndSlots(); // m_textItem->setDefaultTextColor(Qt::white); m_rectItem->setNormalFillColor(QColor("#ddddff")); m_lineItem->setNormalLineColor(QColor("#ddddff")); m_lineItem->setLineWidth(2); m_lineItem->setBrush(Qt::NoBrush); } CNodeData CNodeItem::data() const { return m_data; } void CNodeItem::setData(CNodeData data) { m_data = data; m_textItem->setPlainText(data.name); m_rectItem->setToolTip(data.remark); } void CNodeItem::addSubNode(CNodeItem *n) { if (n == nullptr) { return; } if (n->data().pNumber == data().number) { n->setParent(this); } else { for (QObject *obj : children()) { CNodeItem *item = dynamic_cast(obj); item->addSubNode(n); } } } void CNodeItem::removeNode(int number) { for (QObject *obj : children()) { CNodeItem *item = dynamic_cast(obj); if (item->data().number == number) { item->setParent(nullptr); delete item; } else { item->removeNode(number); } } } CNodeItem *CNodeItem::subNode(int number) { if (data().number == number) { return this; } for (QObject *obj : children()) { CNodeItem *t = dynamic_cast(obj); CNodeItem *sub = t->subNode(number); if (sub != nullptr) { return sub; } } return nullptr; } CRectItem *CNodeItem::rectItem() const { return m_rectItem; } CTextItem *CNodeItem::textItem() const { return m_textItem; } CLineItem *CNodeItem::lineItem() const { return m_lineItem; } QPointF CNodeItem::pos() const { return m_pos; } void CNodeItem::setPos(const QPointF pos) { m_pos = pos; updateItemsGeometry(); } qreal CNodeItem::xMargin() const { return m_xMargin; } void CNodeItem::setXMargin(qreal x) { m_xMargin = x; updateItemsGeometry(); } qreal CNodeItem::yMargin() const { return m_yMargin; } void CNodeItem::setYMargin(qreal y) { m_yMargin = y; updateItemsGeometry(); } qreal CNodeItem::minWidth() const { return m_minWidth; } void CNodeItem::setMinWidth(qreal w) { m_minWidth = w; updateItemsGeometry(); } qreal CNodeItem::maxWidth() const { return m_maxWidth; } void CNodeItem::setMaxWidth(qreal w) { m_maxWidth = w; } qreal CNodeItem::minHeight() const { return m_minHeight; } void CNodeItem::setMinHeight(qreal h) { m_minHeight = h; updateItemsGeometry(); } void CNodeItem::connectSignalsAndSlots() { connect(m_rectItem->editAction(), &QAction::triggered, this, &CNodeItem::slotEditNode); connect(m_rectItem->selectAction(), &QAction::triggered, this, &CNodeItem::slotSelect); connect(m_rectItem->subNodeAction(), &QAction::triggered, this, &CNodeItem::slotSubNode); connect(m_rectItem->removeAction(), &QAction::triggered, this, &CNodeItem::slotRemove); connect(m_textItem, &CTextItem::sigWillBeginEditing, this, &CNodeItem::slotWillBeginEditing); connect(m_textItem, &CTextItem::sigTextChanged, this, &CNodeItem::slotTextChanged); } void CNodeItem::updateItemsGeometry() { QRectF tr = m_textItem->boundingRect(); qreal w = std::max(tr.width() + m_xMargin * 2, m_minWidth); qreal h = std::max(tr.height() + m_yMargin * 2, m_minHeight); m_rectItem->setRect(QRectF(m_pos, QSizeF(w, h))); m_textItem->setPos(m_pos + QPointF(m_xMargin, (h - tr.height()) / 2)); } int CNodeItem::height() const { int h = 1; for (QObject *obj : children()) { CNodeItem *item = dynamic_cast(obj); h = std::max(h, item->height() + 1); } return h; } int CNodeItem::depth() const { int d = 1; const CNodeItem *node = this; while (node->parent() != nullptr) { d++; node = dynamic_cast(node->parent()); } return d; } int CNodeItem::leafs() const { int d = 1; if (children().count() > 0) { int d = 0; for (QObject *obj : children()) { CNodeItem *item = dynamic_cast(obj); d += item->leafs(); } } return d; } int CNodeItem::sizeOfLevel(int lev) const { if (lev < 1) { return 0; } if (lev == 1) { return 1; } int size = 0; for (QObject *obj : children()) { CNodeItem *item = dynamic_cast(obj); size += item->sizeOfLevel(lev - 1); } return size; } qreal CNodeItem::textWidth() const { return m_textItem->boundingRect().width(); } qreal CNodeItem::textHeight() const { return m_textItem->boundingRect().height(); } qreal CNodeItem::borderWidth() const { return m_minWidth; QFont font = m_textItem->font(); QFontMetrics fm(font); int w = fm.width(m_textItem->toPlainText()); return std::max(w + m_xMargin * 2, m_minWidth); } qreal CNodeItem::borderHeight() const { return std::max(textHeight() + m_yMargin * 2, m_minHeight); } qreal CNodeItem::hNodeSpace() const { return m_hNodeSpace; } void CNodeItem::setHNodeSpace(qreal h) { m_hNodeSpace = h; } qreal CNodeItem::vNodeSpace() const { return m_vNodeSpace; } void CNodeItem::setVNodeSpace(qreal v) { m_vNodeSpace = v; } qreal CNodeItem::childrenHeight() const { qreal h = vNodeSpace() * (children().count() - 1); // 子节点竖直方向上总间隔 for (QObject *obj : children()) { CNodeItem *item = dynamic_cast(obj); h += item->treeHeight(); // 加上各子节点高度 } return std::max(h, h - h); } qreal CNodeItem::treeHeight() const { return std::max(borderHeight(), childrenHeight()); } qreal CNodeItem::maxBorderWidthOfLevel(int lev) const { if (lev < 1) { return 0; } if (lev == 1) { return borderWidth(); } qreal w = 0; for (QObject *obj : children()) { CNodeItem *item = dynamic_cast(obj); w = std::max(w, item->maxBorderWidthOfLevel(lev - 1)); } return w; } void CNodeItem::beginEditing() { m_textItem->beginEditing(); } void CNodeItem::endEditing() { CNodeItem *item = editingNode(); if (item != nullptr) { item->textItem()->endEditing(); } } CNodeItem *CNodeItem::editingNode() { CNodeItem *node = nullptr; if (m_textItem->isEditing()) { return this; } for (QObject *obj : children()) { CNodeItem *item = dynamic_cast(obj); node = item->editingNode(); if (node != nullptr) { return node; } } return node; } void CNodeItem::setHighlighted(bool h) { m_rectItem->setHighlighted(h); m_lineItem->setHighlighted(h); m_lineItem->setBrush(Qt::NoBrush); m_textItem->setDefaultTextColor(h ? QColor("#cccccc") : Qt::black); } void CNodeItem::slotEditNode() { emit sigEditNode(data()); } void CNodeItem::slotSelect() { m_rectItem->setHighlighted(!m_rectItem->highlighted()); } void CNodeItem::slotSubNode() { emit sigAddSubItem(data().number); } void CNodeItem::slotRemove() { emit sigRemoveItem(data().number); } void CNodeItem::slotTextChanged() { m_data.name = m_textItem->toPlainText(); emit sigTextChanged(); } void CNodeItem::slotWillBeginEditing() { emit sigWillBeginEditing(); }