/* This file is part of the KDE project Copyright (C) 2004 Lucijan Busch Copyright (C) 2004-2005 Jaroslaw Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include "kexirelationview.h" #include "kexirelationviewtable.h" #include "kexirelationviewconnection.h" #include #include #include //#include "r1.xpm" //#include "rn.xpm" KexiRelationViewConnection::KexiRelationViewConnection( KexiRelationViewTableContainer *masterTbl, KexiRelationViewTableContainer *detailsTbl, SourceConnection &c, KexiRelationView *parent) { m_parent = parent; // kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << endl; m_masterTable = masterTbl; if(!masterTbl || !detailsTbl) { kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection(): expect sig11" << endl; kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << masterTbl << endl; kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << detailsTbl << endl; } m_detailsTable = detailsTbl; m_masterField = c.masterField; m_detailsField = c.detailsField; m_selected = false; } KexiRelationViewConnection::~KexiRelationViewConnection() { } void KexiRelationViewConnection::drawConnection(TQPainter *p) { p->setPen(m_parent->palette().active().foreground()); int sx = m_masterTable->x() + m_masterTable->width() + m_parent->contentsX(); int sy = m_masterTable->globalY(m_masterField); int rx = m_detailsTable->x() + m_parent->contentsX(); int ry = m_detailsTable->globalY(m_detailsField); TQFont f( Kexi::smallFont( m_parent ) ); TQFontMetrics fm(f); int side1x=0, side1y=sy - fm.height(), sideNx=0, sideNy=ry - fm.height(); //! @todo details char can be also just a '1' for some cases TQChar sideNChar(0x221E); //infinity char uint sideNCharWidth = 2+2+ fm.width( sideNChar ); TQChar side1Char('1'); uint side1CharWidth = 2+2+ fm.width( side1Char ); p->setBrush(p->pen().color()); if(m_masterTable->x() < m_detailsTable->x()) { //det. side p->drawLine(rx - sideNCharWidth, ry, rx, ry); TQPointArray pa(3); pa.setPoint(0, rx - 4, ry - 3); pa.setPoint(1, rx - 4, ry + 3); pa.setPoint(2, rx - 1, ry); p->drawPolygon(pa, true); //master side p->drawLine(sx, sy - 1, sx + side1CharWidth -1, sy - 1); p->drawLine(sx, sy, sx + side1CharWidth -1, sy); p->drawLine(sx, sy + 1, sx + side1CharWidth -1, sy + 1); side1x = sx; // side1y = sy - 7; sideNx = rx - sideNCharWidth - 1; // sideNy = ry - 6; TQPen pen(p->pen()); if(m_selected) { TQPen pen(p->pen()); pen.setWidth(2); p->setPen(pen); } p->drawLine(sx + side1CharWidth, sy, rx - sideNCharWidth, ry); if(m_selected) { TQPen pen(p->pen()); pen.setWidth(1); p->setPen(pen); } } else { int lx = rx + m_detailsTable->width(); int rx = sx - m_masterTable->width(); //det. side p->drawLine(lx, ry, lx + sideNCharWidth, ry); TQPointArray pa(3); pa.setPoint(0, lx + 3, ry - 3); pa.setPoint(1, lx + 3, ry + 3); pa.setPoint(2, lx, ry); p->drawPolygon(pa, true); // p->drawLine(lx, ry, lx + 8, ry); // p->drawPoint(lx + 1, ry - 1); // p->drawPoint(lx + 1, ry + 1); // p->drawLine(lx + 2, ry - 2, lx + 2, ry + 2); //master side p->drawLine(rx - side1CharWidth +1, sy - 1, rx, sy - 1); p->drawLine(rx - side1CharWidth +1, sy + 1, rx, sy + 1); p->drawLine(rx - side1CharWidth +1, sy, rx, sy); side1x = rx - side1CharWidth; // side1y = sy - 7; sideNx = lx + 1; // sideNy = ry - 6; if(m_selected) { TQPen pen(p->pen()); pen.setWidth(2); p->setPen(pen); } p->drawLine(lx + sideNCharWidth, ry, rx - side1CharWidth, sy); if(m_selected) { TQPen pen(p->pen()); pen.setWidth(1); p->setPen(pen); } } p->drawText(side1x, side1y, side1CharWidth, fm.height(), TQt::AlignCenter, side1Char); p->drawText(sideNx, sideNy, sideNCharWidth, fm.height(), TQt::AlignCenter, sideNChar); //p->drawRect(TQRect(connectionRect().topLeft(), TQSize(50,50))); // p->drawPixmap(side1, TQPixmap(r1_xpm)); // p->drawPixmap(sideN, TQPixmap(rn_xpm)); } const TQRect KexiRelationViewConnection::connectionRect() { int sx = m_masterTable->x() + m_parent->contentsX(); int rx = m_detailsTable->x() + m_parent->contentsX(); int ry = m_detailsTable->globalY(m_detailsField); int sy = m_masterTable->globalY(m_masterField); int width, leftX, rightX; if(sx < rx) { leftX = sx; rightX = rx; width = m_masterTable->width(); } else { leftX = rx; rightX = sx; width = m_detailsTable->width(); } int dx = TQABS((leftX + width) - rightX); int dy = TQABS(sy - ry) + 2; int top = TQMIN(sy, ry); int left = leftX + width; // return TQRect(sx - 1, sy - 1, (rx + m_detailsTable->width()) - sx + 1, ry - sy + 1); TQRect rect(left - 150, top - 150, dx + 150, dy + 150); // kdDebug() << "KexiRelationViewConnection::connectionRect():" << m_oldRect << "," << rect << endl; m_oldRect = rect; return rect; } bool KexiRelationViewConnection::matchesPoint(const TQPoint &p, int tolerance) { TQRect we = connectionRect(); if(!we.contains(p)) return false; /** get our coordinats * you know what i mean the x1, y1 is the top point * and the x2, y2 is the bottom point * (quite tirvial :) although that was the entrace to the magic * gate... */ int sx = m_masterTable->x() + m_masterTable->width(); int sy = m_masterTable->globalY(m_masterField); int rx = m_detailsTable->x(); int ry = m_detailsTable->globalY(m_detailsField); int x1 = sx + 8; int y1 = sy; int x2 = rx - 8; int y2 = ry; if(sx > rx) { x1 = m_detailsTable->x() + m_detailsTable->width(); x2 = m_masterTable->x(); y2 = sy; y1 = ry; } /* here we call pythagoras (the greek math geek :p) see: http://w1.480.telia.com/%7Eu48019406/geekporn.gif if you don't know how these people have got sex :) */ float mx = x2-x1; float my = y2-y1; float mag = sqrt(mx * mx + my * my); float u = (((p.x() - x1)*(x2 - x1))+((p.y() - y1)*(y2 - y1)))/(mag * mag); kdDebug() << "KexiRelationViewConnection::matchesPoint(): u: " << u << endl; float iX = x1 + u * (x2 - x1); float iY = y1 + u * (y2 - y1); kdDebug() << "KexiRelationViewConnection::matchesPoint(): px: " << p.x() << endl; kdDebug() << "KexiRelationViewConnection::matchesPoint(): py: " << p.y() << endl; kdDebug() << "KexiRelationViewConnection::matchesPoint(): ix: " << iX << endl; kdDebug() << "KexiRelationViewConnection::matchesPoint(): iy: " << iY << endl; float dX = iX - p.x(); float dY = iY - p.y(); kdDebug() << "KexiRelationViewConnection::matchesPoint(): dx: " << dX << endl; kdDebug() << "KexiRelationViewConnection::matchesPoint(): dy: " << dY << endl; float distance = sqrt(dX * dX + dY * dY); kdDebug() << "KexiRelationViewConnection::matchesPoint(): distance: " << distance << endl; if(distance <= tolerance) return true; return false; } TQString KexiRelationViewConnection::toString() const { TQString str; /*! @todo what about query? */ if (m_masterTable && m_masterTable->schema()->table()) { str += (TQString(m_masterTable->schema()->name()) + "." + m_masterField); } if (m_detailsTable && m_detailsTable->schema()->table()) { str += " - "; str += (TQString(m_detailsTable->schema()->name()) + "." + m_detailsField); } return str; }