⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connectionedit.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the Qt Designer of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include <QtGui/QPainter>#include <QtGui/QPaintEvent>#include <QtGui/QFontMetrics>#include <QtGui/QPixmap>#include <QtGui/QMatrix>#include <QtGui/qevent.h>#include <QtCore/qdebug.h>#include <QtDesigner/abstractformwindow.h>#include "connectionedit_p.h"#define BG_ALPHA                32#define LINE_PROXIMITY_RADIUS   3#define LOOP_MARGIN             20#define VLABEL_MARGIN            1#define HLABEL_MARGIN            3#define GROUND_W                20#define GROUND_H                25namespace qdesigner_internal {/********************************************************************************* Tools*/static QRect fixRect(const QRect &r){    return QRect(r.x(), r.y(), r.width() - 1, r.height() - 1);}static QRect expand(const QRect &r, int i){    return QRect(r.x() - i, r.y() - i, r.width() + 2*i, r.height() + 2*i);}static QRect endPointRect(const QPoint &pos){    QRect r(pos + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS),            QSize(2*LINE_PROXIMITY_RADIUS, 2*LINE_PROXIMITY_RADIUS));    return r;}static void paintGround(QPainter *p, QRect r){    QPoint mid = r.center();    p->drawLine(mid.x(), r.top(), mid.x(), mid.y());    p->drawLine(r.left(), mid.y(), r.right(), mid.y());    int y = r.top() + 4*r.height()/6;    int x = GROUND_W/6;    p->drawLine(r.left() + x, y, r.right() - x, y);    y = r.top() + 5*r.height()/6;    x = 2*GROUND_W/6;    p->drawLine(r.left() + x, y, r.right() - x, y);    p->drawLine(mid.x(), r.bottom(), mid.x() + 1, r.bottom());}static void paintEndPoint(QPainter *p, const QPoint &pos){    QRect r(pos + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS),            QSize(2*LINE_PROXIMITY_RADIUS, 2*LINE_PROXIMITY_RADIUS));    p->fillRect(fixRect(r), p->pen().color());}static CETypes::LineDir classifyLine(const QPoint &p1, const QPoint &p2){    if (p1.x() == p2.x())        return p1.y() < p2.y() ? CETypes::DownDir : CETypes::UpDir;    Q_ASSERT(p1.y() == p2.y());    return p1.x() < p2.x() ? CETypes::RightDir : CETypes::LeftDir;}static QPoint pointInsideRect(const QRect &r, QPoint p){    if (p.x() < r.left())        p.setX(r.left());    else if (p.x() > r.right())        p.setX(r.right());    if (p.y() < r.top())        p.setY(r.top());    else if (p.y() > r.bottom())        p.setY(r.bottom());    return p;}/********************************************************************************* Commands*/AddConnectionCommand::AddConnectionCommand(ConnectionEdit *edit, Connection *con)    : CECommand(edit), m_con(con){    setDescription(tr("Add connection"));}void AddConnectionCommand::redo(){    edit()->selectNone();    emit edit()->aboutToAddConnection(edit()->m_con_list.size());    edit()->m_con_list.append(m_con);    m_con->inserted();    edit()->setSelected(m_con, true);    emit edit()->connectionAdded(m_con);}void AddConnectionCommand::undo(){    int idx = edit()->indexOfConnection(m_con);    emit edit()->aboutToRemoveConnection(m_con);    edit()->setSelected(m_con, false);    m_con->update();    m_con->removed();    edit()->m_con_list.removeAll(m_con);    emit edit()->connectionRemoved(idx);}class AdjustConnectionCommand : public CECommand{    Q_OBJECTpublic:    AdjustConnectionCommand(ConnectionEdit *edit, Connection *con,                            const QPoint &old_source_pos,                            const QPoint &old_target_pos,                            const QPoint &new_source_pos,                            const QPoint &new_target_pos);    virtual void redo();    virtual void undo();private:    Connection *m_con;    QPoint m_old_source_pos, m_old_target_pos,            m_new_source_pos, m_new_target_pos;};AdjustConnectionCommand::AdjustConnectionCommand(ConnectionEdit *edit, Connection *con,                                                    const QPoint &old_source_pos,                                                    const QPoint &old_target_pos,                                                    const QPoint &new_source_pos,                                                    const QPoint &new_target_pos)    : CECommand(edit){    setDescription(tr("Adjust connection"));    m_con = con;    m_old_source_pos = old_source_pos;    m_old_target_pos = old_target_pos;    m_new_source_pos = new_source_pos;    m_new_target_pos = new_target_pos;}void AdjustConnectionCommand::undo(){    m_con->setEndPoint(EndPoint::Source, m_con->widget(EndPoint::Source), m_old_source_pos);    m_con->setEndPoint(EndPoint::Target, m_con->widget(EndPoint::Target), m_old_target_pos);}void AdjustConnectionCommand::redo(){    m_con->setEndPoint(EndPoint::Source, m_con->widget(EndPoint::Source), m_new_source_pos);    m_con->setEndPoint(EndPoint::Target, m_con->widget(EndPoint::Target), m_new_target_pos);}DeleteConnectionsCommand::DeleteConnectionsCommand(ConnectionEdit *edit,                                                    const ConnectionList &con_list)    : CECommand(edit), m_con_list(con_list){   setDescription(tr("Delete connections"));}void DeleteConnectionsCommand::redo(){    foreach (Connection *con, m_con_list) {        int idx = edit()->indexOfConnection(con);        emit edit()->aboutToRemoveConnection(con);        Q_ASSERT(edit()->m_con_list.contains(con));        edit()->setSelected(con, false);        con->update();        con->removed();        edit()->m_con_list.removeAll(con);        emit edit()->connectionRemoved(idx);    }}void DeleteConnectionsCommand::undo(){    foreach (Connection *con, m_con_list) {        Q_ASSERT(!edit()->m_con_list.contains(con));        emit edit()->aboutToAddConnection(edit()->m_con_list.size());        edit()->m_con_list.append(con);        edit()->setSelected(con, true);        con->update();        con->inserted();        emit edit()->connectionAdded(con);    }}class SetEndPointCommand : public CECommand{    Q_OBJECTpublic:    SetEndPointCommand(ConnectionEdit *edit, Connection *con, EndPoint::Type type, QObject *object);    virtual void redo();    virtual void undo();private:    Connection *m_con;    EndPoint::Type m_type;    QObject *m_old_widget, *m_new_widget;    QPoint m_old_pos, m_new_pos;};SetEndPointCommand::SetEndPointCommand(ConnectionEdit *edit, Connection *con,                                        EndPoint::Type type, QObject *object)    : CECommand(edit){    m_con = con;    m_type = type;    m_old_widget = con->object(type);    m_old_pos = con->endPointPos(type);    m_new_widget = object;    if (QWidget *widget = qobject_cast<QWidget*>(object)) {        m_new_pos = edit->widgetRect(widget).center();    }    setDescription(tr("Change %1").arg(m_type == EndPoint::Source ? tr("source") : tr("target")));}void SetEndPointCommand::redo(){    m_con->setEndPoint(m_type, m_new_widget, m_new_pos);    emit edit()->connectionChanged(m_con);}void SetEndPointCommand::undo(){    m_con->setEndPoint(m_type, m_old_widget, m_old_pos);    emit edit()->connectionChanged(m_con);}/********************************************************************************* Connection*/Connection::Connection(ConnectionEdit *edit){    m_edit = edit;    m_source = 0;    m_target = 0;    m_visible = true;    m_source_pos = QPoint(-1, -1);    m_target_pos = QPoint(-1, -1);}Connection::Connection(ConnectionEdit *edit, QObject *source, QObject *target){    m_edit = edit;    m_source = source;    m_target = target;    m_visible = true;    m_source_pos = QPoint(-1, -1);    m_target_pos = QPoint(-1, -1);}void Connection::setVisible(bool b){    m_visible = b;}void Connection::updateVisibility(){    QWidget *source = widget(EndPoint::Source);    QWidget *target = widget(EndPoint::Target);    if (source == 0 || target == 0) {        setVisible(false);        return;    }    QWidget *w = source;    while (w && w->parentWidget()) {        if (!w->isVisibleTo(w->parentWidget())) {            setVisible(false);            return;        }        w = w->parentWidget();    }    w = target;    while (w && w->parentWidget()) {        if (!w->isVisibleTo(w->parentWidget())) {            setVisible(false);            return;        }        w = w->parentWidget();    }    setVisible(true);}bool Connection::isVisible() const{    return m_visible;}bool Connection::ground() const{    return m_target != 0 && m_target == m_edit->m_bg_widget;}QPoint Connection::endPointPos(EndPoint::Type type) const{    if (type == EndPoint::Source)        return m_source_pos;    else        return m_target_pos;}static QPoint lineEntryPos(const QPoint &p1, const QPoint &p2, const QRect &rect){    QPoint result;    CETypes::LineDir dir = classifyLine(p1, p2);    switch (dir) {        case CETypes::UpDir:            result = QPoint(p1.x(), rect.bottom());            break;        case CETypes::DownDir:            result = QPoint(p1.x(), rect.top());            break;        case CETypes::LeftDir:            result = QPoint(rect.right(), p1.y());            break;        case CETypes::RightDir:            result = QPoint(rect.left(), p1.y());            break;    }    return result;}static QPolygonF arrowHead(const QPoint &p1, const QPoint &p2){    QPolygonF result;    CETypes::LineDir dir = classifyLine(p1, p2);    switch (dir) {        case CETypes::UpDir:            result.append(p2 + QPoint(0, 1));            result.append(p2 + QPoint(LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS*2 + 1));            result.append(p2 + QPoint(-LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS*2 + 1));            break;        case CETypes::DownDir:            result.append(p2);            result.append(p2 + QPoint(LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS*2));            result.append(p2 + QPoint(-LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS*2));            break;        case CETypes::LeftDir:            result.append(p2 + QPoint(1, 0));            result.append(p2 + QPoint(2*LINE_PROXIMITY_RADIUS + 1, -LINE_PROXIMITY_RADIUS));            result.append(p2 + QPoint(2*LINE_PROXIMITY_RADIUS + 1, LINE_PROXIMITY_RADIUS));            break;        case CETypes::RightDir:            result.append(p2);            result.append(p2 + QPoint(-2*LINE_PROXIMITY_RADIUS, -LINE_PROXIMITY_RADIUS));            result.append(p2 + QPoint(-2*LINE_PROXIMITY_RADIUS, LINE_PROXIMITY_RADIUS));            break;    }    return result;}static CETypes::LineDir closestEdge(const QPoint &p, const QRect &r){    CETypes::LineDir result = CETypes::UpDir;    int min = p.y() - r.top();    int d = p.x() - r.left();    if (d < min) {        min = d;        result = CETypes::LeftDir;    }    d = r.bottom() - p.y();    if (d < min) {        min = d;        result = CETypes::DownDir;    }    d = r.right() - p.x();    if (d < min) {        min = d;        result = CETypes::RightDir;    }    return result;}static bool pointAboveLine(const QPoint &l1, const QPoint &l2, const QPoint &p){    if (l1.x() == l2.x())        return p.x() >= l1.x();    return p.y() <= l1.y() + (p.x() - l1.x())*(l2.y() - l1.y())/(l2.x() - l1.x());}void Connection::updateKneeList(){    LineDir old_source_label_dir = labelDir(EndPoint::Source);    LineDir old_target_label_dir = labelDir(EndPoint::Target);    QPoint s = endPointPos(EndPoint::Source);    QPoint t = endPointPos(EndPoint::Target);    QRect sr = m_source_rect;    QRect tr = m_target_rect;    m_knee_list.clear();    m_arrow_head.clear();    if (m_source == 0 || s == QPoint(-1, -1) || t == QPoint(-1, -1))        return;    QRect r = sr | tr;    m_knee_list.append(s);    if (m_target == 0) {        m_knee_list.append(QPoint(t.x(), s.y()));    } else if (m_target == m_edit->m_bg_widget) {        m_knee_list.append(QPoint(s.x(), t.y()));    } else if (tr.contains(sr) || sr.contains(tr)) {/*        +------------------+        | +----------+     |        | |          |     |        | |   o      |     |        | +---|------+     |        |     |     x      |        +-----|-----|------+              +-----+        We find out which edge of the outer rectangle is closest to the target        point, and make a loop which exits and re-enters through that edge.*/        LineDir dir = closestEdge(t, tr);        switch (dir) {            case UpDir:                m_knee_list.append(QPoint(s.x(), r.top() - LOOP_MARGIN));                m_knee_list.append(QPoint(t.x(), r.top() - LOOP_MARGIN));                break;            case DownDir:                m_knee_list.append(QPoint(s.x(), r.bottom() + LOOP_MARGIN));                m_knee_list.append(QPoint(t.x(), r.bottom() + LOOP_MARGIN));                break;            case LeftDir:                m_knee_list.append(QPoint(r.left() - LOOP_MARGIN, s.y()));                m_knee_list.append(QPoint(r.left() - LOOP_MARGIN, t.y()));                break;            case RightDir:                m_knee_list.append(QPoint(r.right() + LOOP_MARGIN, s.y()));                m_knee_list.append(QPoint(r.right() + LOOP_MARGIN, t.y()));                break;        }    } else {        if (r.height() < sr.height() + tr.height()) {            if (s.y() >= tr.top() && s.y() <= tr.bottom() || t.y() >= sr.bottom() || t.y() <= sr.top()) {/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -