00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <QtGui/QPainter>
00025 #include <QtGui/QPaintEvent>
00026 #include <QtGui/QFontMetrics>
00027 #include <QtGui/QPixmap>
00028 #include <QtGui/QMatrix>
00029 #include <QtGui/QApplication>
00030 #include <QtGui/qevent.h>
00031
00032 #include <QtCore/qdebug.h>
00033
00034 #include <QtDesigner/abstractformwindow.h>
00035
00036 #include "connectionedit_p.h"
00037
00038 #define BG_ALPHA 32
00039 #define LINE_PROXIMITY_RADIUS 3
00040 #define LOOP_MARGIN 20
00041 #define VLABEL_MARGIN 1
00042 #define HLABEL_MARGIN 3
00043 #define GROUND_W 20
00044 #define GROUND_H 25
00045
00046 namespace qdesigner_internal {
00047
00048
00049
00050
00051
00052 static QRect fixRect(const QRect &r)
00053 {
00054 return QRect(r.x(), r.y(), r.width() - 1, r.height() - 1);
00055 }
00056
00057 static QRect expand(const QRect &r, int i)
00058 {
00059 return QRect(r.x() - i, r.y() - i, r.width() + 2*i, r.height() + 2*i);
00060 }
00061
00062 static QRect endPointRect(const QPoint &pos)
00063 {
00064 QRect r(pos + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS),
00065 QSize(2*LINE_PROXIMITY_RADIUS, 2*LINE_PROXIMITY_RADIUS));
00066 return r;
00067 }
00068
00069 static void paintGround(QPainter *p, QRect r)
00070 {
00071 QPoint mid = r.center();
00072 p->drawLine(mid.x(), r.top(), mid.x(), mid.y());
00073 p->drawLine(r.left(), mid.y(), r.right(), mid.y());
00074 int y = r.top() + 4*r.height()/6;
00075 int x = GROUND_W/6;
00076 p->drawLine(r.left() + x, y, r.right() - x, y);
00077 y = r.top() + 5*r.height()/6;
00078 x = 2*GROUND_W/6;
00079 p->drawLine(r.left() + x, y, r.right() - x, y);
00080 p->drawLine(mid.x(), r.bottom(), mid.x() + 1, r.bottom());
00081 }
00082
00083 static void paintEndPoint(QPainter *p, const QPoint &pos)
00084 {
00085 QRect r(pos + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS),
00086 QSize(2*LINE_PROXIMITY_RADIUS, 2*LINE_PROXIMITY_RADIUS));
00087 p->fillRect(fixRect(r), p->pen().color());
00088 }
00089
00090 static CETypes::LineDir classifyLine(const QPoint &p1, const QPoint &p2)
00091 {
00092 if (p1.x() == p2.x())
00093 return p1.y() < p2.y() ? CETypes::DownDir : CETypes::UpDir;
00094 Q_ASSERT(p1.y() == p2.y());
00095 return p1.x() < p2.x() ? CETypes::RightDir : CETypes::LeftDir;
00096 }
00097
00098 static QPoint pointInsideRect(const QRect &r, QPoint p)
00099 {
00100 if (p.x() < r.left())
00101 p.setX(r.left());
00102 else if (p.x() > r.right())
00103 p.setX(r.right());
00104
00105 if (p.y() < r.top())
00106 p.setY(r.top());
00107 else if (p.y() > r.bottom())
00108 p.setY(r.bottom());
00109
00110 return p;
00111 }
00112
00113
00114
00115
00116
00117 AddConnectionCommand::AddConnectionCommand(ConnectionEdit *edit, Connection *con)
00118 : CECommand(edit), m_con(con)
00119 {
00120 setText(QApplication::translate("Command", "Add connection"));
00121 }
00122
00123 void AddConnectionCommand::redo()
00124 {
00125 edit()->selectNone();
00126 emit edit()->aboutToAddConnection(edit()->m_con_list.size());
00127 edit()->m_con_list.append(m_con);
00128 m_con->inserted();
00129 edit()->setSelected(m_con, true);
00130 emit edit()->connectionAdded(m_con);
00131 }
00132
00133 void AddConnectionCommand::undo()
00134 {
00135 int idx = edit()->indexOfConnection(m_con);
00136 emit edit()->aboutToRemoveConnection(m_con);
00137 edit()->setSelected(m_con, false);
00138 m_con->update();
00139 m_con->removed();
00140 edit()->m_con_list.removeAll(m_con);
00141 emit edit()->connectionRemoved(idx);
00142 }
00143
00144 class AdjustConnectionCommand : public CECommand
00145 {
00146 public:
00147 AdjustConnectionCommand(ConnectionEdit *edit, Connection *con,
00148 const QPoint &old_source_pos,
00149 const QPoint &old_target_pos,
00150 const QPoint &new_source_pos,
00151 const QPoint &new_target_pos);
00152 virtual void redo();
00153 virtual void undo();
00154 private:
00155 Connection *m_con;
00156 QPoint m_old_source_pos, m_old_target_pos,
00157 m_new_source_pos, m_new_target_pos;
00158 };
00159
00160 AdjustConnectionCommand::AdjustConnectionCommand(ConnectionEdit *edit, Connection *con,
00161 const QPoint &old_source_pos,
00162 const QPoint &old_target_pos,
00163 const QPoint &new_source_pos,
00164 const QPoint &new_target_pos)
00165 : CECommand(edit)
00166 {
00167 setText(QApplication::translate("Command", "Adjust connection"));
00168 m_con = con;
00169 m_old_source_pos = old_source_pos;
00170 m_old_target_pos = old_target_pos;
00171 m_new_source_pos = new_source_pos;
00172 m_new_target_pos = new_target_pos;
00173 }
00174
00175 void AdjustConnectionCommand::undo()
00176 {
00177 m_con->setEndPoint(EndPoint::Source, m_con->widget(EndPoint::Source), m_old_source_pos);
00178 m_con->setEndPoint(EndPoint::Target, m_con->widget(EndPoint::Target), m_old_target_pos);
00179 }
00180
00181 void AdjustConnectionCommand::redo()
00182 {
00183 m_con->setEndPoint(EndPoint::Source, m_con->widget(EndPoint::Source), m_new_source_pos);
00184 m_con->setEndPoint(EndPoint::Target, m_con->widget(EndPoint::Target), m_new_target_pos);
00185 }
00186
00187 DeleteConnectionsCommand::DeleteConnectionsCommand(ConnectionEdit *edit,
00188 const ConnectionList &con_list)
00189 : CECommand(edit), m_con_list(con_list)
00190 {
00191 setText(QApplication::translate("Command", "Delete connections"));
00192 }
00193
00194 void DeleteConnectionsCommand::redo()
00195 {
00196 foreach (Connection *con, m_con_list) {
00197 int idx = edit()->indexOfConnection(con);
00198 emit edit()->aboutToRemoveConnection(con);
00199 Q_ASSERT(edit()->m_con_list.contains(con));
00200 edit()->setSelected(con, false);
00201 con->update();
00202 con->removed();
00203 edit()->m_con_list.removeAll(con);
00204 emit edit()->connectionRemoved(idx);
00205 }
00206 }
00207
00208 void DeleteConnectionsCommand::undo()
00209 {
00210 foreach (Connection *con, m_con_list) {
00211 Q_ASSERT(!edit()->m_con_list.contains(con));
00212 emit edit()->aboutToAddConnection(edit()->m_con_list.size());
00213 edit()->m_con_list.append(con);
00214 edit()->setSelected(con, true);
00215 con->update();
00216 con->inserted();
00217 emit edit()->connectionAdded(con);
00218 }
00219 }
00220
00221 class SetEndPointCommand : public CECommand
00222 {
00223 public:
00224 SetEndPointCommand(ConnectionEdit *edit, Connection *con, EndPoint::Type type, QObject *object);
00225 virtual void redo();
00226 virtual void undo();
00227 private:
00228 Connection *m_con;
00229 EndPoint::Type m_type;
00230 QObject *m_old_widget, *m_new_widget;
00231 QPoint m_old_pos, m_new_pos;
00232 };
00233
00234 SetEndPointCommand::SetEndPointCommand(ConnectionEdit *edit, Connection *con,
00235 EndPoint::Type type, QObject *object)
00236 : CECommand(edit)
00237 {
00238 m_con = con;
00239 m_type = type;
00240 m_old_widget = con->object(type);
00241 m_old_pos = con->endPointPos(type);
00242 m_new_widget = object;
00243
00244 if (QWidget *widget = qobject_cast<QWidget*>(object)) {
00245 m_new_pos = edit->widgetRect(widget).center();
00246 }
00247
00248 if (m_type == EndPoint::Source)
00249 setText(QApplication::translate("Command", "Change source"));
00250 else
00251 setText(QApplication::translate("Command", "Change target"));
00252 }
00253
00254 void SetEndPointCommand::redo()
00255 {
00256 m_con->setEndPoint(m_type, m_new_widget, m_new_pos);
00257 emit edit()->connectionChanged(m_con);
00258 }
00259
00260 void SetEndPointCommand::undo()
00261 {
00262 m_con->setEndPoint(m_type, m_old_widget, m_old_pos);
00263 emit edit()->connectionChanged(m_con);
00264 }
00265
00266
00267
00268
00269
00270 Connection::Connection(ConnectionEdit *edit)
00271 {
00272 m_edit = edit;
00273 m_source = 0;
00274 m_target = 0;
00275 m_visible = true;
00276
00277 m_source_pos = QPoint(-1, -1);
00278 m_target_pos = QPoint(-1, -1);
00279 }
00280
00281 Connection::Connection(ConnectionEdit *edit, QObject *source, QObject *target)
00282 {
00283 m_edit = edit;
00284 m_source = source;
00285 m_target = target;
00286 m_visible = true;
00287
00288 m_source_pos = QPoint(-1, -1);
00289 m_target_pos = QPoint(-1, -1);
00290 }
00291
00292 void Connection::setVisible(bool b)
00293 {
00294 m_visible = b;
00295 }
00296
00297 void Connection::updateVisibility()
00298 {
00299 QWidget *source = widget(EndPoint::Source);
00300 QWidget *target = widget(EndPoint::Target);
00301
00302 if (source == 0 || target == 0) {
00303 setVisible(false);
00304 return;
00305 }
00306
00307 QWidget *w = source;
00308 while (w && w->parentWidget()) {
00309 if (!w->isVisibleTo(w->parentWidget())) {
00310 setVisible(false);
00311 return;
00312 }
00313 w = w->parentWidget();
00314 }
00315
00316 w = target;
00317 while (w && w->parentWidget()) {
00318 if (!w->isVisibleTo(w->parentWidget())) {
00319 setVisible(false);
00320 return;
00321 }
00322 w = w->parentWidget();
00323 }
00324
00325 setVisible(true);
00326 }
00327
00328 bool Connection::isVisible() const
00329 {
00330 return m_visible;
00331 }
00332
00333 bool Connection::ground() const
00334 {
00335 return m_target != 0 && m_target == m_edit->m_bg_widget;
00336 }
00337
00338 QPoint Connection::endPointPos(EndPoint::Type type) const
00339 {
00340 if (type == EndPoint::Source)
00341 return m_source_pos;
00342 else
00343 return m_target_pos;
00344 }
00345
00346 static QPoint lineEntryPos(const QPoint &p1, const QPoint &p2, const QRect &rect)
00347 {
00348 QPoint result;
00349
00350 CETypes::LineDir dir = classifyLine(p1, p2);
00351 switch (dir) {
00352 case CETypes::UpDir:
00353 result = QPoint(p1.x(), rect.bottom());
00354 break;
00355 case CETypes::DownDir:
00356 result = QPoint(p1.x(), rect.top());
00357 break;
00358 case CETypes::LeftDir:
00359 result = QPoint(rect.right(), p1.y());
00360 break;
00361 case CETypes::RightDir:
00362 result = QPoint(rect.left(), p1.y());
00363 break;
00364 }
00365
00366 return result;
00367 }
00368
00369 static QPolygonF arrowHead(const QPoint &p1, const QPoint &p2)
00370 {
00371 QPolygonF result;
00372
00373 CETypes::LineDir dir = classifyLine(p1, p2);
00374 switch (dir) {
00375 case CETypes::UpDir:
00376 result.append(p2 + QPoint(0, 1));
00377 result.append(p2 + QPoint(LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS*2 + 1));
00378 result.append(p2 + QPoint(-LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS*2 + 1));
00379 break;
00380 case CETypes::DownDir:
00381 result.append(p2);
00382 result.append(p2 + QPoint(LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS*2));
00383 result.append(p2 + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS*2));
00384 break;
00385 case CETypes::LeftDir:
00386 result.append(p2 + QPoint(1, 0));
00387 result.append(p2 + QPoint(2*LINE_PROXIMITY_RADIUS + 1, -LINE_PROXIMITY_RADIUS));
00388 result.append(p2 + QPoint(2*LINE_PROXIMITY_RADIUS + 1, LINE_PROXIMITY_RADIUS));
00389 break;
00390 case CETypes::RightDir:
00391 result.append(p2);
00392 result.append(p2 + QPoint(-2*LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS));
00393 result.append(p2 + QPoint(-2*LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS));
00394 break;
00395 }
00396
00397 return result;
00398 }
00399
00400 static CETypes::LineDir closestEdge(const QPoint &p, const QRect &r)
00401 {
00402 CETypes::LineDir result = CETypes::UpDir;
00403 int min = p.y() - r.top();
00404
00405 int d = p.x() - r.left();
00406 if (d < min) {
00407 min = d;
00408 result = CETypes::LeftDir;
00409 }
00410
00411 d = r.bottom() - p.y();
00412 if (d < min) {
00413 min = d;
00414 result = CETypes::DownDir;
00415 }
00416
00417 d = r.right() - p.x();
00418 if (d < min) {
00419 min = d;
00420 result = CETypes::RightDir;
00421 }
00422
00423 return result;
00424 }
00425
00426 static bool pointAboveLine(const QPoint &l1, const QPoint &l2, const QPoint &p)
00427 {
00428 if (l1.x() == l2.x())
00429 return p.x() >= l1.x();
00430 return p.y() <= l1.y() + (p.x() - l1.x())*(l2.y() - l1.y())/(l2.x() - l1.x());
00431 }
00432
00433 void Connection::updateKneeList()
00434 {
00435 LineDir old_source_label_dir = labelDir(EndPoint::Source);
00436 LineDir old_target_label_dir = labelDir(EndPoint::Target);
00437
00438 QPoint s = endPointPos(EndPoint::Source);
00439 QPoint t = endPointPos(EndPoint::Target);
00440 QRect sr = m_source_rect;
00441 QRect tr = m_target_rect;
00442
00443 m_knee_list.clear();
00444 m_arrow_head.clear();
00445
00446 if (m_source == 0 || s == QPoint(-1, -1) || t == QPoint(-1, -1))
00447 return;
00448
00449 QRect r = sr | tr;
00450
00451 m_knee_list.append(s);
00452 if (m_target == 0) {
00453 m_knee_list.append(QPoint(t.x(), s.y()));
00454 } else if (m_target == m_edit->m_bg_widget) {
00455 m_knee_list.append(QPoint(s.x(), t.y()));
00456 } else if (tr.contains(sr) || sr.contains(tr)) {
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 LineDir dir = closestEdge(t, tr);
00471 switch (dir) {
00472 case UpDir:
00473 m_knee_list.append(QPoint(s.x(), r.top() - LOOP_MARGIN));
00474 m_knee_list.append(QPoint(t.x(), r.top() - LOOP_MARGIN));
00475 break;
00476 case DownDir:
00477 m_knee_list.append(QPoint(s.x(), r.bottom() + LOOP_MARGIN));
00478 m_knee_list.append(QPoint(t.x(), r.bottom() + LOOP_MARGIN));
00479 break;
00480 case LeftDir:
00481 m_knee_list.append(QPoint(r.left() - LOOP_MARGIN, s.y()));
00482 m_knee_list.append(QPoint(r.left() - LOOP_MARGIN, t.y()));
00483 break;
00484 case RightDir:
00485 m_knee_list.append(QPoint(r.right() + LOOP_MARGIN, s.y()));
00486 m_knee_list.append(QPoint(r.right() + LOOP_MARGIN, t.y()));
00487 break;
00488 }
00489 } else {
00490 if (r.height() < sr.height() + tr.height()) {
00491 if (s.y() >= tr.top() && s.y() <= tr.bottom() || t.y() >= sr.bottom() || t.y() <= sr.top()) {
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504 if (m_edit->state() == ConnectionEdit::Dragging) {
00505 if (m_edit->m_drag_end_point.type == EndPoint::Source) {
00506 QPoint p(t.x(), s.y());
00507 m_knee_list.append(p);
00508 if (tr.contains(p))
00509 t = m_target_pos = p;
00510 } else {
00511 QPoint p(s.x(), t.y());
00512 m_knee_list.append(p);
00513 if (sr.contains(p))
00514 s = m_source_pos = p;
00515 }
00516 } else {
00517 m_knee_list.append(QPoint(s.x(), t.y()));
00518 }
00519 } else {
00520
00521
00522
00523
00524
00525
00526
00527
00528 m_knee_list.append(QPoint(t.x(), s.y()));
00529 }
00530 } else if (r.width() < sr.width() + tr.width()) {
00531 if (s.x() >= tr.left() && s.x() <= tr.right() || t.x() >= sr.right() || t.x() <= sr.left()) {
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 if (m_edit->state() == ConnectionEdit::Dragging) {
00546 if (m_edit->m_drag_end_point.type == EndPoint::Source) {
00547 QPoint p(s.x(), t.y());
00548 m_knee_list.append(p);
00549 if (tr.contains(p))
00550 t = m_target_pos = p;
00551 } else {
00552 QPoint p(t.x(), s.y());
00553 m_knee_list.append(p);
00554 if (sr.contains(p))
00555 s = m_source_pos = p;
00556 }
00557 } else {
00558 m_knee_list.append(QPoint(t.x(), s.y()));
00559 }
00560 } else {
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 m_knee_list.append(QPoint(s.x(), t.y()));
00573 }
00574 } else {
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 if (sr.topLeft() == r.topLeft()) {
00588 if (pointAboveLine(tr.topLeft(), tr.bottomRight(), t))
00589 m_knee_list.append(QPoint(t.x(), s.y()));
00590 else
00591 m_knee_list.append(QPoint(s.x(), t.y()));
00592 } else if (sr.topRight() == r.topRight()) {
00593 if (pointAboveLine(tr.bottomLeft(), tr.topRight(), t))
00594 m_knee_list.append(QPoint(t.x(), s.y()));
00595 else
00596 m_knee_list.append(QPoint(s.x(), t.y()));
00597 } else if (sr.bottomRight() == r.bottomRight()) {
00598 if (pointAboveLine(tr.topLeft(), tr.bottomRight(), t))
00599 m_knee_list.append(QPoint(s.x(), t.y()));
00600 else
00601 m_knee_list.append(QPoint(t.x(), s.y()));
00602 } else {
00603 if (pointAboveLine(tr.bottomLeft(), tr.topRight(), t))
00604 m_knee_list.append(QPoint(s.x(), t.y()));
00605 else
00606 m_knee_list.append(QPoint(t.x(), s.y()));
00607 }
00608 }
00609 }
00610 m_knee_list.append(t);
00611
00612 if (m_knee_list.size() == 2)
00613 m_knee_list.clear();
00614
00615 trimLine();
00616
00617 LineDir new_source_label_dir = labelDir(EndPoint::Source);
00618 LineDir new_target_label_dir = labelDir(EndPoint::Target);
00619 if (new_source_label_dir != old_source_label_dir)
00620 updatePixmap(EndPoint::Source);
00621 if (new_target_label_dir != old_target_label_dir)
00622 updatePixmap(EndPoint::Target);
00623 }
00624
00625 void Connection::trimLine()
00626 {
00627 if (m_source == 0 || m_source_pos == QPoint(-1, -1) || m_target_pos == QPoint(-1, -1))
00628 return;
00629 int cnt = m_knee_list.size();
00630 if (cnt < 2)
00631 return;
00632
00633 QRect sr = m_source_rect;
00634 QRect tr = m_target_rect;
00635
00636 if (sr.contains(m_knee_list.at(1)))
00637 m_knee_list.removeFirst();
00638
00639 cnt = m_knee_list.size();
00640 if (cnt < 2)
00641 return;
00642
00643 if (!tr.contains(sr) && tr.contains(m_knee_list.at(cnt - 2)))
00644 m_knee_list.removeLast();
00645
00646 cnt = m_knee_list.size();
00647 if (cnt < 2)
00648 return;
00649
00650 if (sr.contains(m_knee_list.at(0)) && !sr.contains(m_knee_list.at(1)))
00651 m_knee_list[0] = lineEntryPos(m_knee_list.at(1), m_knee_list.at(0), sr);
00652
00653 if (tr.contains(m_knee_list.at(cnt - 1)) && !tr.contains(m_knee_list.at(cnt - 2))) {
00654 m_knee_list[cnt - 1]
00655 = lineEntryPos(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1), tr);
00656 m_arrow_head = arrowHead(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1));
00657 }
00658 }
00659
00660 void Connection::setSource(QObject *source, const QPoint &pos)
00661 {
00662 if (source == m_source && m_source_pos == pos)
00663 return;
00664
00665 update(false);
00666
00667 m_source = source;
00668 if (QWidget *widget = qobject_cast<QWidget*>(source)) {
00669 m_source_pos = pos;
00670 m_source_rect = m_edit->widgetRect(widget);
00671 updateKneeList();
00672 }
00673
00674 update(false);
00675 }
00676
00677 void Connection::setTarget(QObject *target, const QPoint &pos)
00678 {
00679 if (target == m_target && m_target_pos == pos)
00680 return;
00681
00682 update(false);
00683
00684 m_target = target;
00685 if (QWidget *widget = qobject_cast<QWidget*>(target)) {
00686 m_target_pos = pos;
00687 m_target_rect = m_edit->widgetRect(widget);
00688 updateKneeList();
00689 }
00690
00691 update(false);
00692 }
00693
00694 static QRect lineRect(const QPoint &a, const QPoint &b)
00695 {
00696 QPoint c(qMin(a.x(), b.x()), qMin(a.y(), b.y()));
00697 QPoint d(qMax(a.x(), b.x()), qMax(a.y(), b.y()));
00698
00699 QRect result(c, d);
00700 return expand(result, LINE_PROXIMITY_RADIUS);
00701 }
00702
00703 QRect Connection::groundRect() const
00704 {
00705 if (!ground())
00706 return QRect();
00707 if (m_knee_list.isEmpty())
00708 return QRect();
00709
00710 QPoint p = m_knee_list.last();
00711 return QRect(p.x() - GROUND_W/2, p.y(), GROUND_W, GROUND_H);
00712 }
00713
00714 QRegion Connection::region() const
00715 {
00716 QRegion result;
00717
00718 for (int i = 0; i < m_knee_list.size() - 1; ++i)
00719 result = result.unite(lineRect(m_knee_list.at(i), m_knee_list.at(i + 1)));
00720
00721 if (!m_arrow_head.isEmpty()) {
00722 QRect r = m_arrow_head.boundingRect().toRect();
00723 r = expand(r, 1);
00724 result = result.unite(r);
00725 } else if (ground()) {
00726 result = result.unite(groundRect());
00727 }
00728
00729 result = result.unite(labelRect(EndPoint::Source));
00730 result = result.unite(labelRect(EndPoint::Target));
00731
00732 return result;
00733 }
00734
00735 void Connection::update(bool update_widgets) const
00736 {
00737 m_edit->update(region());
00738 if (update_widgets) {
00739 if (m_source != 0)
00740 m_edit->update(m_source_rect);
00741 if (m_target != 0)
00742 m_edit->update(m_target_rect);
00743 }
00744
00745 m_edit->update(endPointRect(EndPoint::Source));
00746 m_edit->update(endPointRect(EndPoint::Target));
00747 }
00748
00749 void Connection::paint(QPainter *p) const
00750 {
00751 for (int i = 0; i < m_knee_list.size() - 1; ++i)
00752 p->drawLine(m_knee_list.at(i), m_knee_list.at(i + 1));
00753
00754 if (!m_arrow_head.isEmpty()) {
00755 p->save();
00756 p->setBrush(p->pen().color());
00757 p->drawPolygon(m_arrow_head);
00758 p->restore();
00759 } else if (ground()) {
00760 paintGround(p, groundRect());
00761 }
00762 }
00763
00764 bool Connection::contains(const QPoint &pos) const
00765 {
00766 return region().contains(pos);
00767 }
00768
00769 QRect Connection::endPointRect(EndPoint::Type type) const
00770 {
00771 if (type == EndPoint::Source) {
00772 if (m_source_pos != QPoint(-1, -1))
00773 return qdesigner_internal::endPointRect(m_source_pos);
00774 } else {
00775 if (m_target_pos != QPoint(-1, -1))
00776 return qdesigner_internal::endPointRect(m_target_pos);
00777 }
00778 return QRect();
00779 }
00780
00781 CETypes::LineDir Connection::labelDir(EndPoint::Type type) const
00782 {
00783 int cnt = m_knee_list.size();
00784 if (cnt < 2)
00785 return RightDir;
00786
00787 LineDir dir;
00788 if (type == EndPoint::Source)
00789 dir = classifyLine(m_knee_list.at(0), m_knee_list.at(1));
00790 else
00791 dir = classifyLine(m_knee_list.at(cnt - 2), m_knee_list.at(cnt - 1));
00792
00793 if (dir == LeftDir)
00794 dir = RightDir;
00795 if (dir == UpDir)
00796 dir = DownDir;
00797
00798 return dir;
00799 }
00800
00801 QRect Connection::labelRect(EndPoint::Type type) const
00802 {
00803 int cnt = m_knee_list.size();
00804 if (cnt < 2)
00805 return QRect();
00806 QString text = label(type);
00807 if (text.isEmpty())
00808 return QRect();
00809
00810 QSize size = labelPixmap(type).size();
00811 QPoint p1, p2;
00812 if (type == EndPoint::Source) {
00813 p1 = m_knee_list.at(0);
00814 p2 = m_knee_list.at(1);
00815 } else {
00816 p1 = m_knee_list.at(cnt - 1);
00817 p2 = m_knee_list.at(cnt - 2);
00818 }
00819 LineDir dir = classifyLine(p1, p2);
00820
00821 QRect result;
00822 switch (dir) {
00823 case UpDir:
00824 result = QRect(p1 + QPoint(-size.width()/2, 0), size);
00825 break;
00826 case DownDir:
00827 result = QRect(p1 + QPoint(-size.width()/2, -size.height()), size);
00828 break;
00829 case LeftDir:
00830 result = QRect(p1 + QPoint(0, -size.height()/2), size);
00831 break;
00832 case RightDir:
00833 result = QRect(p1 + QPoint(-size.width(), -size.height()/2), size);
00834 break;
00835 }
00836
00837 return result;
00838 }
00839
00840 void Connection::setLabel(EndPoint::Type type, const QString &text)
00841 {
00842 if (text == label(type))
00843 return;
00844
00845 if (type == EndPoint::Source)
00846 m_source_label = text;
00847 else
00848 m_target_label = text;
00849
00850 updatePixmap(type);
00851 }
00852
00853 void Connection::updatePixmap(EndPoint::Type type)
00854 {
00855 QPixmap *pm = type == EndPoint::Source ? &m_source_label_pm : &m_target_label_pm;
00856 *pm = QPixmap();
00857
00858 QString text = label(type);
00859 if (text.isEmpty())
00860 return;
00861
00862 QFontMetrics fm = m_edit->fontMetrics();
00863 QSize size = fm.size(Qt::TextSingleLine, text) + QSize(HLABEL_MARGIN*2, VLABEL_MARGIN*2);
00864 *pm = QPixmap(size);
00865 pm->fill(m_edit->palette().color(QPalette::Normal, QPalette::Base));
00866
00867 QPainter p(pm);
00868 p.setPen(m_edit->palette().color(QPalette::Normal, QPalette::Text));
00869 p.drawText(-fm.leftBearing(text.at(0)) + HLABEL_MARGIN, fm.ascent() + VLABEL_MARGIN, text);
00870 p.end();
00871
00872 LineDir dir = labelDir(type);
00873
00874 if (dir == DownDir)
00875 *pm = pm->transformed(QMatrix(0.0, -1.0, 1.0, 0.0, 0.0, 0.0));
00876 }
00877
00878 void Connection::checkWidgets()
00879 {
00880 bool changed = false;
00881
00882 if (QWidget *sourceWidget = qobject_cast<QWidget*>(m_source)) {
00883 QRect r = m_edit->widgetRect(sourceWidget);
00884 if (r != m_source_rect) {
00885 if (m_source_pos != QPoint(-1, -1) && !r.contains(m_source_pos)) {
00886 QPoint offset = m_source_pos - m_source_rect.topLeft();
00887 QPoint old_pos = m_source_pos;
00888 m_source_pos = pointInsideRect(r, r.topLeft() + offset);
00889 }
00890 m_edit->update(m_source_rect);
00891 m_source_rect = r;
00892 changed = true;
00893 }
00894 }
00895
00896 if (QWidget *targetWidget = qobject_cast<QWidget*>(m_target)) {
00897 QRect r = m_edit->widgetRect(targetWidget);
00898 if (r != m_target_rect) {
00899 if (m_target_pos != QPoint(-1, -1) && !r.contains(m_target_pos)) {
00900 QPoint offset = m_target_pos - m_target_rect.topLeft();
00901 QPoint old_pos = m_target_pos;
00902 m_target_pos = pointInsideRect(r, r.topLeft() + offset);
00903 }
00904 m_edit->update(m_target_rect);
00905 m_target_rect = r;
00906 changed = true;
00907 }
00908 }
00909
00910 if (changed) {
00911 update();
00912 updateKneeList();
00913 update();
00914 }
00915 }
00916
00917
00918
00919
00920
00921 ConnectionEdit::ConnectionEdit(QWidget *parent, QDesignerFormWindowInterface *form)
00922 : QWidget(parent)
00923 {
00924 m_bg_widget = 0;
00925 m_widget_under_mouse = 0;
00926 m_tmp_con = 0;
00927 m_start_connection_on_drag = true;
00928 m_enable_update_background = false;
00929 m_undo_stack = form->commandHistory();
00930 m_active_color = Qt::red;
00931 m_inactive_color = Qt::blue;
00932 setAttribute(Qt::WA_MouseTracking, true);
00933 setFocusPolicy(Qt::ClickFocus);
00934
00935 connect(form, SIGNAL(widgetRemoved(QWidget*)), this, SLOT(widgetRemoved(QWidget*)));
00936 }
00937
00938
00939 void ConnectionEdit::clear()
00940 {
00941 m_con_list.clear();
00942 m_sel_con_set.clear();
00943 m_bg_widget = 0;
00944 m_widget_under_mouse = 0;
00945 m_tmp_con = 0;
00946 }
00947
00948 void ConnectionEdit::setBackground(QWidget *background)
00949 {
00950 if (background == m_bg_widget) {
00951
00952 return;
00953 }
00954
00955 m_bg_widget = background;
00956 updateBackground();
00957 }
00958
00959 void ConnectionEdit::enableUpdateBackground(bool enable)
00960 {
00961 m_enable_update_background = enable;
00962 if (enable)
00963 updateBackground();
00964 }
00965
00966 void ConnectionEdit::updateBackground()
00967 {
00968 if (m_bg_widget == 0)
00969 return;
00970
00971 if (!m_enable_update_background)
00972 return;
00973
00974 foreach(Connection *c, m_con_list)
00975 c->updateVisibility();
00976
00977 updateLines();
00978 update();
00979 }
00980
00981 QWidget *ConnectionEdit::widgetAt(const QPoint &pos) const
00982 {
00983 if (m_bg_widget == 0)
00984 return 0;
00985 QWidget *widget = m_bg_widget->childAt(pos);
00986 if (widget == 0)
00987 widget = m_bg_widget;
00988
00989 return widget;
00990 }
00991
00992
00993 QRect ConnectionEdit::widgetRect(QWidget *w) const
00994 {
00995 if (w == 0)
00996 return QRect();
00997 QRect r = w->geometry();
00998 QPoint pos = w->mapToGlobal(QPoint(0, 0));
00999 pos = mapFromGlobal(pos);
01000 r.moveTopLeft(pos);
01001 return r;
01002 }
01003
01004 ConnectionEdit::State ConnectionEdit::state() const
01005 {
01006 if (m_tmp_con != 0)
01007 return Connecting;
01008 if (!m_drag_end_point.isNull())
01009 return Dragging;
01010 return Editing;
01011 }
01012
01013 void ConnectionEdit::paintLabel(QPainter *p, EndPoint::Type type, Connection *con)
01014 {
01015 if (con->label(type).isEmpty())
01016 return;
01017
01018 bool heavy = selected(con) || con == m_tmp_con;
01019 p->setPen(heavy ? m_active_color : m_inactive_color);
01020 p->setBrush(Qt::NoBrush);
01021 QRect r = con->labelRect(type);
01022 p->drawPixmap(r.topLeft(), con->labelPixmap(type));
01023 p->drawRect(fixRect(r));
01024 }
01025
01026 void ConnectionEdit::paintConnection(QPainter *p, Connection *con,
01027 WidgetSet *heavy_highlight_set,
01028 WidgetSet *light_highlight_set) const
01029 {
01030 QWidget *source = con->widget(EndPoint::Source);
01031 QWidget *target = con->widget(EndPoint::Target);
01032
01033 bool heavy = selected(con) || con == m_tmp_con;
01034 WidgetSet *set = heavy ? heavy_highlight_set : light_highlight_set;
01035 p->setPen(heavy ? m_active_color : m_inactive_color);
01036 con->paint(p);
01037
01038 if (source != 0)
01039 set->insert(source, source);
01040
01041 if (target != 0 && target != m_bg_widget)
01042 set->insert(target, target);
01043 }
01044
01045 void ConnectionEdit::paintEvent(QPaintEvent *e)
01046 {
01047 QPainter p(this);
01048 p.setClipRegion(e->region());
01049
01050 WidgetSet heavy_highlight_set, light_highlight_set;
01051
01052 foreach (Connection *con, m_con_list) {
01053 if (!con->isVisible())
01054 continue;
01055
01056 paintConnection(&p, con, &heavy_highlight_set, &light_highlight_set);
01057 }
01058
01059 if (m_tmp_con != 0)
01060 paintConnection(&p, m_tmp_con, &heavy_highlight_set, &light_highlight_set);
01061
01062 if (!m_widget_under_mouse.isNull() && m_widget_under_mouse != m_bg_widget)
01063 heavy_highlight_set.insert(m_widget_under_mouse, m_widget_under_mouse);
01064
01065 QColor c = m_active_color;
01066 p.setPen(c);
01067 c.setAlpha(BG_ALPHA);
01068 p.setBrush(c);
01069
01070 foreach (QWidget *w, heavy_highlight_set) {
01071 p.drawRect(fixRect(widgetRect(w)));
01072 light_highlight_set.remove(w);
01073 }
01074
01075 c = m_inactive_color;
01076 p.setPen(c);
01077 c.setAlpha(BG_ALPHA);
01078 p.setBrush(c);
01079
01080 foreach (QWidget *w, light_highlight_set)
01081 p.drawRect(fixRect(widgetRect(w)));
01082
01083 p.setBrush(palette().color(QPalette::Base));
01084 p.setPen(palette().color(QPalette::Text));
01085 foreach (Connection *con, m_con_list) {
01086 if (!con->isVisible())
01087 continue;
01088
01089 paintLabel(&p, EndPoint::Source, con);
01090 paintLabel(&p, EndPoint::Target, con);
01091 }
01092
01093 p.setPen(m_active_color);
01094 p.setBrush(m_active_color);
01095
01096 foreach (Connection *con, m_con_list) {
01097 if (!selected(con) || !con->isVisible())
01098 continue;
01099
01100 paintEndPoint(&p, con->endPointPos(EndPoint::Source));
01101
01102 if (con->widget(EndPoint::Target) != 0)
01103 paintEndPoint(&p, con->endPointPos(EndPoint::Target));
01104 }
01105 }
01106
01107 void ConnectionEdit::abortConnection()
01108 {
01109 m_tmp_con->update();
01110 delete m_tmp_con;
01111 m_tmp_con = 0;
01112 setCursor(QCursor());
01113 if (m_widget_under_mouse == m_bg_widget)
01114 m_widget_under_mouse = 0;
01115 }
01116
01117 void ConnectionEdit::mousePressEvent(QMouseEvent *e)
01118 {
01119 e->accept();
01120
01121 Connection *con_under_mouse = connectionAt(e->pos());
01122 m_start_connection_on_drag = false;
01123
01124 switch (state()) {
01125 case Connecting:
01126 if (e->button() == Qt::RightButton)
01127 abortConnection();
01128 break;
01129 case Dragging:
01130 break;
01131 case Editing:
01132 if (!m_end_point_under_mouse.isNull()) {
01133 if (!(e->modifiers() & Qt::ShiftModifier)) {
01134 startDrag(m_end_point_under_mouse, e->pos());
01135 }
01136 } else if (con_under_mouse != 0) {
01137 if (!(e->modifiers() & Qt::ShiftModifier)) {
01138 selectNone();
01139 setSelected(con_under_mouse, true);
01140 } else {
01141 setSelected(con_under_mouse, !selected(con_under_mouse));
01142 }
01143 } else {
01144 if (!(e->modifiers() & Qt::ShiftModifier)) {
01145 selectNone();
01146 if (!m_widget_under_mouse.isNull())
01147 m_start_connection_on_drag = true;
01148 }
01149 }
01150 break;
01151 }
01152 }
01153
01154 void ConnectionEdit::mouseDoubleClickEvent(QMouseEvent *e)
01155 {
01156 e->accept();
01157 switch (state()) {
01158 case Connecting:
01159 abortConnection();
01160 break;
01161 case Dragging:
01162 break;
01163 case Editing:
01164 if (!m_widget_under_mouse.isNull()) {
01165 emit widgetActivated(m_widget_under_mouse);
01166 } else if (m_sel_con_set.size() == 1) {
01167 Connection *con = m_sel_con_set.keys().first();
01168 modifyConnection(con);
01169 }
01170 break;
01171 }
01172
01173 }
01174
01175 void ConnectionEdit::mouseReleaseEvent(QMouseEvent *e)
01176 {
01177 e->accept();
01178
01179 switch (state()) {
01180 case Connecting:
01181 if (m_widget_under_mouse.isNull())
01182 abortConnection();
01183 else
01184 endConnection(m_widget_under_mouse, e->pos());
01185 setCursor(QCursor());
01186 break;
01187 case Editing:
01188 break;
01189 case Dragging:
01190 endDrag(e->pos());
01191 break;
01192 }
01193 }
01194
01195
01196 void ConnectionEdit::findObjectsUnderMouse(const QPoint &pos)
01197 {
01198 Connection *con_under_mouse = connectionAt(pos);
01199 QWidget *w = con_under_mouse != 0 ? 0 : widgetAt(pos);
01200
01201 if (state() != Connecting && w == m_bg_widget)
01202 w = 0;
01203
01204 if (w != m_widget_under_mouse) {
01205 if (!m_widget_under_mouse.isNull())
01206 update(widgetRect(m_widget_under_mouse));
01207 m_widget_under_mouse = w;
01208 if (!m_widget_under_mouse.isNull())
01209 update(widgetRect(m_widget_under_mouse));
01210 }
01211
01212 EndPoint hs = endPointAt(pos);
01213 if (hs != m_end_point_under_mouse) {
01214 if (m_end_point_under_mouse.isNull())
01215 setCursor(Qt::PointingHandCursor);
01216 else
01217 setCursor(QCursor());
01218 m_end_point_under_mouse = hs;
01219 }
01220 }
01221
01222 void ConnectionEdit::mouseMoveEvent(QMouseEvent *e)
01223 {
01224 findObjectsUnderMouse(e->pos());
01225
01226 switch (state()) {
01227 case Connecting:
01228 continueConnection(m_widget_under_mouse, e->pos());
01229 break;
01230 case Editing:
01231 if ((e->buttons() & Qt::LeftButton)
01232 && m_start_connection_on_drag
01233 && !m_widget_under_mouse.isNull()) {
01234 m_start_connection_on_drag = false;
01235 startConnection(m_widget_under_mouse, e->pos());
01236 setCursor(Qt::CrossCursor);
01237 }
01238 break;
01239 case Dragging:
01240 continueDrag(e->pos());
01241 break;
01242 }
01243
01244 e->accept();
01245 }
01246
01247 void ConnectionEdit::keyPressEvent(QKeyEvent *e)
01248 {
01249 switch (e->key()) {
01250 case Qt::Key_Delete:
01251 if (state() == Editing)
01252 deleteSelected();
01253 break;
01254 case Qt::Key_Escape:
01255 if (state() == Connecting)
01256 abortConnection();
01257 break;
01258 }
01259
01260 e->accept();
01261 }
01262
01263 void ConnectionEdit::startConnection(QWidget *source, const QPoint &pos)
01264 {
01265 Q_ASSERT(m_tmp_con == 0);
01266
01267 m_tmp_con = new Connection(this);
01268 m_tmp_con->setEndPoint(EndPoint::Source, source, pos);
01269 }
01270
01271 void ConnectionEdit::endConnection(QWidget *target, const QPoint &pos)
01272 {
01273 Q_ASSERT(m_tmp_con != 0);
01274
01275 m_tmp_con->setEndPoint(EndPoint::Target, target, pos);
01276
01277 QWidget *source = m_tmp_con->widget(EndPoint::Source);
01278 Q_ASSERT(source != 0);
01279 Q_ASSERT(target != 0);
01280 setEnabled(false);
01281 Connection *new_con = createConnection(source, target);
01282 setEnabled(true);
01283 if (new_con != 0) {
01284 new_con->setEndPoint(EndPoint::Source, source, m_tmp_con->endPointPos(EndPoint::Source));
01285 new_con->setEndPoint(EndPoint::Target, target, m_tmp_con->endPointPos(EndPoint::Target));
01286 m_undo_stack->push(new AddConnectionCommand(this, new_con));
01287 }
01288
01289 delete m_tmp_con;
01290 m_tmp_con = 0;
01291
01292 findObjectsUnderMouse(mapFromGlobal(QCursor::pos()));
01293 }
01294
01295 void ConnectionEdit::continueConnection(QWidget *target, const QPoint &pos)
01296 {
01297 Q_ASSERT(m_tmp_con != 0);
01298
01299 m_tmp_con->setEndPoint(EndPoint::Target, target, pos);
01300 }
01301
01302 void ConnectionEdit::modifyConnection(Connection *)
01303 {
01304 }
01305
01306 Connection *ConnectionEdit::createConnection(QWidget *source, QWidget *target)
01307 {
01308 Connection *con = new Connection(this, source, target);
01309 return con;
01310 }
01311
01312 void ConnectionEdit::widgetRemoved(QWidget *widget)
01313 {
01314 QList<QWidget*> child_list = qFindChildren<QWidget*>(widget);
01315 child_list.prepend(widget);
01316
01317 ConnectionSet remove_set;
01318 foreach (QWidget *w, child_list) {
01319 foreach (Connection *con, m_con_list) {
01320 if (con->widget(EndPoint::Source) == w || con->widget(EndPoint::Target) == w)
01321 remove_set.insert(con, con);
01322 }
01323 }
01324
01325 if (!remove_set.isEmpty())
01326 m_undo_stack->push(new DeleteConnectionsCommand(this, remove_set.keys()));
01327
01328 updateBackground();
01329 }
01330
01331 void ConnectionEdit::setSelected(Connection *con, bool sel)
01332 {
01333 if (!con || sel == m_sel_con_set.contains(con))
01334 return;
01335
01336 if (sel) {
01337 m_sel_con_set.insert(con, con);
01338 emit connectionSelected(con);
01339 } else {
01340 m_sel_con_set.remove(con);
01341 }
01342
01343 con->update();
01344 }
01345
01346 bool ConnectionEdit::selected(const Connection *con) const
01347 {
01348 return m_sel_con_set.contains(const_cast<Connection*>(con));
01349 }
01350
01351 void ConnectionEdit::selectNone()
01352 {
01353 foreach (Connection *con, m_sel_con_set)
01354 con->update();
01355
01356 m_sel_con_set.clear();
01357 }
01358
01359 Connection *ConnectionEdit::connectionAt(const QPoint &pos) const
01360 {
01361 foreach (Connection *con, m_con_list) {
01362 if (con->contains(pos))
01363 return con;
01364 }
01365 return 0;
01366 }
01367
01368 CETypes::EndPoint ConnectionEdit::endPointAt(const QPoint &pos) const
01369 {
01370 foreach (Connection *con, m_con_list) {
01371 if (!selected(con))
01372 continue;
01373 QRect sr = con->endPointRect(EndPoint::Source);
01374 QRect tr = con->endPointRect(EndPoint::Target);
01375
01376 if (sr.contains(pos))
01377 return EndPoint(con, EndPoint::Source);
01378 if (tr.contains(pos))
01379 return EndPoint(con, EndPoint::Target);
01380 }
01381 return EndPoint();
01382 }
01383
01384 void ConnectionEdit::startDrag(const EndPoint &end_point, const QPoint &pos)
01385 {
01386 Q_ASSERT(m_drag_end_point.isNull());
01387 m_drag_end_point = end_point;
01388 m_old_source_pos = m_drag_end_point.con->endPointPos(EndPoint::Source);
01389 m_old_target_pos = m_drag_end_point.con->endPointPos(EndPoint::Target);
01390 adjustHotSopt(m_drag_end_point, pos);
01391 }
01392
01393 void ConnectionEdit::continueDrag(const QPoint &pos)
01394 {
01395 Q_ASSERT(!m_drag_end_point.isNull());
01396 adjustHotSopt(m_drag_end_point, pos);
01397 }
01398
01399 void ConnectionEdit::endDrag(const QPoint &pos)
01400 {
01401 Q_ASSERT(!m_drag_end_point.isNull());
01402 adjustHotSopt(m_drag_end_point, pos);
01403
01404 Connection *con = m_drag_end_point.con;
01405 QPoint new_source_pos = con->endPointPos(EndPoint::Source);
01406 QPoint new_target_pos = con->endPointPos(EndPoint::Target);
01407 m_undo_stack->push(new AdjustConnectionCommand(this, con, m_old_source_pos, m_old_target_pos,
01408 new_source_pos, new_target_pos));
01409
01410 m_drag_end_point = EndPoint();
01411 }
01412
01413 void ConnectionEdit::adjustHotSopt(const EndPoint &end_point, const QPoint &pos)
01414 {
01415 QWidget *w = end_point.con->widget(end_point.type);
01416 end_point.con->setEndPoint(end_point.type, w, pointInsideRect(widgetRect(w), pos));
01417 }
01418
01419 void ConnectionEdit::deleteSelected()
01420 {
01421 if (m_sel_con_set.isEmpty())
01422 return;
01423 m_undo_stack->push(new DeleteConnectionsCommand(this, m_sel_con_set.keys()));
01424 }
01425
01426 void ConnectionEdit::addConnection(Connection *con)
01427 {
01428 m_con_list.append(con);
01429 }
01430
01431 void ConnectionEdit::updateLines()
01432 {
01433 foreach (Connection *con, m_con_list)
01434 con->checkWidgets();
01435 }
01436
01437 void ConnectionEdit::resizeEvent(QResizeEvent *e)
01438 {
01439 updateBackground();
01440 QWidget::resizeEvent(e);
01441 }
01442
01443 void ConnectionEdit::setSource(Connection *con, const QString &obj_name)
01444 {
01445 QObject *object = qFindChild<QObject*>(m_bg_widget, obj_name);
01446 if (object == 0 && m_bg_widget->objectName() == obj_name)
01447 object = m_bg_widget;
01448
01449 if (object == con->object(EndPoint::Source))
01450 return;
01451
01452 m_undo_stack->push(new SetEndPointCommand(this, con, EndPoint::Source, object));
01453 }
01454
01455 void ConnectionEdit::setTarget(Connection *con, const QString &obj_name)
01456 {
01457 QObject *object = qFindChild<QObject*>(m_bg_widget, obj_name);
01458 if (object == 0 && m_bg_widget->objectName() == obj_name)
01459 object = m_bg_widget;
01460
01461 if (object == con->object(EndPoint::Target))
01462 return;
01463
01464 m_undo_stack->push(new SetEndPointCommand(this, con, EndPoint::Target, object));
01465 }
01466
01467 }