📄 connectionedit.cpp
字号:
+--------+ | | +--------+ | o--+---+--x | | o | | | +-----|--+ | | +------+--x | +--------+ When dragging one end point, move the other end point to the same y position, if that does not cause it to exit it's rectangle.*/ if (m_edit->state() == ConnectionEdit::Dragging) { if (m_edit->m_drag_end_point.type == EndPoint::Source) { QPoint p(t.x(), s.y()); m_knee_list.append(p); if (tr.contains(p)) t = m_target_pos = p; } else { QPoint p(s.x(), t.y()); m_knee_list.append(p); if (sr.contains(p)) s = m_source_pos = p; } } else { m_knee_list.append(QPoint(s.x(), t.y())); } } else {/* +--------+ | o----+-------+ | | +---|----+ +--------+ | | | | x | +--------+*/ m_knee_list.append(QPoint(t.x(), s.y())); } } else if (r.width() < sr.width() + tr.width()) { if (s.x() >= tr.left() && s.x() <= tr.right() || t.x() >= sr.right() || t.x() <= sr.left()) {/* +--------+ | | | o o+--+ +----|---+ | +-|------|-+ | x x | | | +----------+ When dragging one end point, move the other end point to the same x position, if that does not cause it to exit it's rectangle.*/ if (m_edit->state() == ConnectionEdit::Dragging) { if (m_edit->m_drag_end_point.type == EndPoint::Source) { QPoint p(s.x(), t.y()); m_knee_list.append(p); if (tr.contains(p)) t = m_target_pos = p; } else { QPoint p(t.x(), s.y()); m_knee_list.append(p); if (sr.contains(p)) s = m_source_pos = p; } } else { m_knee_list.append(QPoint(t.x(), s.y())); } } else {/* +--------+ | | | o | +--|-----+ | +--------+ +---+-x | | | +--------+*/ m_knee_list.append(QPoint(s.x(), t.y())); } } else {/* +--------+ | | | o o-+--------+ +--|-----+ | | +-----|--+ | | x | +--------+-x | +--------+ The line enters the target rectangle through the closest edge.*/ if (sr.topLeft() == r.topLeft()) { if (pointAboveLine(tr.topLeft(), tr.bottomRight(), t)) m_knee_list.append(QPoint(t.x(), s.y())); else m_knee_list.append(QPoint(s.x(), t.y())); } else if (sr.topRight() == r.topRight()) { if (pointAboveLine(tr.bottomLeft(), tr.topRight(), t)) m_knee_list.append(QPoint(t.x(), s.y())); else m_knee_list.append(QPoint(s.x(), t.y())); } else if (sr.bottomRight() == r.bottomRight()) { if (pointAboveLine(tr.topLeft(), tr.bottomRight(), t)) m_knee_list.append(QPoint(s.x(), t.y())); else m_knee_list.append(QPoint(t.x(), s.y())); } else { if (pointAboveLine(tr.bottomLeft(), tr.topRight(), t)) m_knee_list.append(QPoint(s.x(), t.y())); else m_knee_list.append(QPoint(t.x(), s.y())); } } } m_knee_list.append(t); if (m_knee_list.size() == 2) m_knee_list.clear(); trimLine(); LineDir new_source_label_dir = labelDir(EndPoint::Source); LineDir new_target_label_dir = labelDir(EndPoint::Target); if (new_source_label_dir != old_source_label_dir) updatePixmap(EndPoint::Source); if (new_target_label_dir != old_target_label_dir) updatePixmap(EndPoint::Target);}void Connection::trimLine(){ if (m_source == 0 || m_source_pos == QPoint(-1, -1) || m_target_pos == QPoint(-1, -1)) return; int cnt = m_knee_list.size(); if (cnt < 2) return; QRect sr = m_source_rect; QRect tr = m_target_rect; if (sr.contains(m_knee_list.at(1))) m_knee_list.removeFirst(); cnt = m_knee_list.size(); if (cnt < 2) return; if (!tr.contains(sr) && tr.contains(m_knee_list.at(cnt - 2))) m_knee_list.removeLast(); cnt = m_knee_list.size(); if (cnt < 2) return; if (sr.contains(m_knee_list.at(0)) && !sr.contains(m_knee_list.at(1))) m_knee_list[0] = lineEntryPos(m_knee_list.at(1), m_knee_list.at(0), sr); if (tr.contains(m_knee_list.at(cnt - 1)) && !tr.contains(m_knee_list.at(cnt - 2))) { m_knee_list[cnt - 1] = lineEntryPos(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1), tr); m_arrow_head = arrowHead(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1)); }}void Connection::setSource(QObject *source, const QPoint &pos){ if (source == m_source && m_source_pos == pos) return; update(false); m_source = source; if (QWidget *widget = qobject_cast<QWidget*>(source)) { m_source_pos = pos; m_source_rect = m_edit->widgetRect(widget); updateKneeList(); } update(false);}void Connection::setTarget(QObject *target, const QPoint &pos){ if (target == m_target && m_target_pos == pos) return; update(false); m_target = target; if (QWidget *widget = qobject_cast<QWidget*>(target)) { m_target_pos = pos; m_target_rect = m_edit->widgetRect(widget); updateKneeList(); } update(false);}static QRect lineRect(const QPoint &a, const QPoint &b){ QPoint c(qMin(a.x(), b.x()), qMin(a.y(), b.y())); QPoint d(qMax(a.x(), b.x()), qMax(a.y(), b.y())); QRect result(c, d); return expand(result, LINE_PROXIMITY_RADIUS);}QRect Connection::groundRect() const{ if (!ground()) return QRect(); if (m_knee_list.isEmpty()) return QRect(); QPoint p = m_knee_list.last(); return QRect(p.x() - GROUND_W/2, p.y(), GROUND_W, GROUND_H);}QRegion Connection::region() const{ QRegion result; for (int i = 0; i < m_knee_list.size() - 1; ++i) result = result.unite(lineRect(m_knee_list.at(i), m_knee_list.at(i + 1))); if (!m_arrow_head.isEmpty()) { QRect r = m_arrow_head.boundingRect().toRect(); r = expand(r, 1); result = result.unite(r); } else if (ground()) { result = result.unite(groundRect()); } result = result.unite(labelRect(EndPoint::Source)); result = result.unite(labelRect(EndPoint::Target)); return result;}void Connection::update(bool update_widgets) const{ m_edit->update(region()); if (update_widgets) { if (m_source != 0) m_edit->update(m_source_rect); if (m_target != 0) m_edit->update(m_target_rect); } m_edit->update(endPointRect(EndPoint::Source)); m_edit->update(endPointRect(EndPoint::Target));}void Connection::paint(QPainter *p) const{ for (int i = 0; i < m_knee_list.size() - 1; ++i) p->drawLine(m_knee_list.at(i), m_knee_list.at(i + 1)); if (!m_arrow_head.isEmpty()) { p->save(); p->setBrush(p->pen().color()); p->drawPolygon(m_arrow_head); p->restore(); } else if (ground()) { paintGround(p, groundRect()); }}bool Connection::contains(const QPoint &pos) const{ return region().contains(pos);}QRect Connection::endPointRect(EndPoint::Type type) const{ if (type == EndPoint::Source) { if (m_source_pos != QPoint(-1, -1)) return qdesigner_internal::endPointRect(m_source_pos); } else { if (m_target_pos != QPoint(-1, -1)) return qdesigner_internal::endPointRect(m_target_pos); } return QRect();}CETypes::LineDir Connection::labelDir(EndPoint::Type type) const{ int cnt = m_knee_list.size(); if (cnt < 2) return RightDir; LineDir dir; if (type == EndPoint::Source) dir = classifyLine(m_knee_list.at(0), m_knee_list.at(1)); else dir = classifyLine(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1)); if (dir == LeftDir) dir = RightDir; if (dir == UpDir) dir = DownDir; return dir;}QRect Connection::labelRect(EndPoint::Type type) const{ int cnt = m_knee_list.size(); if (cnt < 2) return QRect(); QString text = label(type); if (text.isEmpty()) return QRect(); QSize size = labelPixmap(type).size(); QPoint p1, p2; if (type == EndPoint::Source) { p1 = m_knee_list.at(0); p2 = m_knee_list.at(1); } else { p1 = m_knee_list.at(cnt - 1); p2 = m_knee_list.at(cnt - 2); } LineDir dir = classifyLine(p1, p2); QRect result; switch (dir) { case UpDir: result = QRect(p1 + QPoint(-size.width()/2, 0), size); break; case DownDir: result = QRect(p1 + QPoint(-size.width()/2, -size.height()), size); break; case LeftDir: result = QRect(p1 + QPoint(0, -size.height()/2), size); break; case RightDir: result = QRect(p1 + QPoint(-size.width(), -size.height()/2), size); break; } return result;}void Connection::setLabel(EndPoint::Type type, const QString &text){ if (text == label(type)) return; if (type == EndPoint::Source) m_source_label = text; else m_target_label = text; updatePixmap(type);}void Connection::updatePixmap(EndPoint::Type type){ QPixmap *pm = type == EndPoint::Source ? &m_source_label_pm : &m_target_label_pm; *pm = QPixmap(); QString text = label(type); if (text.isEmpty()) return; QFontMetrics fm = m_edit->fontMetrics(); QSize size = fm.size(Qt::TextSingleLine, text) + QSize(HLABEL_MARGIN*2, VLABEL_MARGIN*2); *pm = QPixmap(size); pm->fill(m_edit->palette().color(QPalette::Normal, QPalette::Base)); QPainter p(pm); p.setPen(m_edit->palette().color(QPalette::Normal, QPalette::Text)); p.drawText(-fm.leftBearing(text.at(0)) + HLABEL_MARGIN, fm.ascent() + VLABEL_MARGIN, text); p.end(); LineDir dir = labelDir(type); if (dir == DownDir) *pm = pm->transformed(QMatrix(0.0, -1.0, 1.0, 0.0, 0.0, 0.0));}void Connection::checkWidgets(){ bool changed = false; if (QWidget *sourceWidget = qobject_cast<QWidget*>(m_source)) { QRect r = m_edit->widgetRect(sourceWidget); if (r != m_source_rect) { if (m_source_pos != QPoint(-1, -1) && !r.contains(m_source_pos)) { QPoint offset = m_source_pos - m_source_rect.topLeft(); QPoint old_pos = m_source_pos; m_source_pos = pointInsideRect(r, r.topLeft() + offset); } m_edit->update(m_source_rect); m_source_rect = r; changed = true; } } if (QWidget *targetWidget = qobject_cast<QWidget*>(m_target)) { QRect r = m_edit->widgetRect(targetWidget); if (r != m_target_rect) { if (m_target_pos != QPoint(-1, -1) && !r.contains(m_target_pos)) { QPoint offset = m_target_pos - m_target_rect.topLeft(); QPoint old_pos = m_target_pos; m_target_pos = pointInsideRect(r, r.topLeft() + offset); } m_edit->update(m_target_rect); m_target_rect = r; changed = true; } } if (changed) { update(); updateKneeList(); update(); }}/********************************************************************************* ConnectionEdit*/ConnectionEdit::ConnectionEdit(QWidget *parent, QDesignerFormWindowInterface *form) : QWidget(parent){ m_bg_widget = 0; m_widget_under_mouse = 0; m_tmp_con = 0; m_start_connection_on_drag = true; m_enable_update_background = false; m_undo_stack = form->commandHistory(); m_active_color = Qt::red; m_inactive_color = Qt::blue; setAttribute(Qt::WA_MouseTracking, true); setFocusPolicy(Qt::ClickFocus); connect(form, SIGNAL(widgetRemoved(QWidget*)), this, SLOT(widgetRemoved(QWidget*)));}void ConnectionEdit::clear(){ m_con_list.clear(); m_sel_con_set.clear(); m_bg_widget = 0; m_widget_under_mouse = 0; m_tmp_con = 0;}void ConnectionEdit::setBackground(QWidget *background){ if (background == m_bg_widget) { // nothing to do return; } m_bg_widget = background; updateBackground();}void ConnectionEdit::enableUpdateBackground(bool enable){ m_enable_update_background = enable; if (enable) updateBackground();}void ConnectionEdit::updateBackground(){ if (m_bg_widget == 0) return; if (!m_enable_update_background) return; foreach(Connection *c, m_con_list) c->updateVisibility(); updateLines(); update();}QWidget *ConnectionEdit::widgetAt(const QPoint &pos) const{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -