00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qpainter.h>
00022 #include <qpixmap.h>
00023 #include <qcolor.h>
00024 #include <qapplication.h>
00025 #include <qpointarray.h>
00026
00027 #include <kdebug.h>
00028
00029 #include <math.h>
00030
00031 #include "kexirelationview.h"
00032 #include "kexirelationviewtable.h"
00033 #include "kexirelationviewconnection.h"
00034 #include <kexidb/tableschema.h>
00035 #include <kexidb/utils.h>
00036 #include <core/kexi.h>
00037
00038
00039
00040
00041 KexiRelationViewConnection::KexiRelationViewConnection(
00042 KexiRelationViewTableContainer *masterTbl, KexiRelationViewTableContainer *detailsTbl,
00043 SourceConnection &c, KexiRelationView *parent)
00044 {
00045 m_parent = parent;
00046 kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << endl;
00047
00048 m_masterTable = masterTbl;
00049 if(!masterTbl || !detailsTbl)
00050 {
00051 kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection(): expect sig11" << endl;
00052 kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << masterTbl << endl;
00053 kdDebug() << "KexiRelationViewConnection::KexiRelationViewConnection()" << detailsTbl << endl;
00054 }
00055
00056 m_detailsTable = detailsTbl;
00057 m_masterField = c.masterField;
00058 m_detailsField = c.detailsField;
00059
00060 m_selected = false;
00061 }
00062
00063 KexiRelationViewConnection::~KexiRelationViewConnection()
00064 {
00065 }
00066
00067 void
00068 KexiRelationViewConnection::drawConnection(QPainter *p)
00069 {
00070 p->setPen(m_parent->palette().active().foreground());
00071 int sx = m_masterTable->x() + m_masterTable->width() + m_parent->contentsX();
00072 int sy = m_masterTable->globalY(m_masterField);
00073 int rx = m_detailsTable->x() + m_parent->contentsX();
00074 int ry = m_detailsTable->globalY(m_detailsField);
00075
00076 QFont f( Kexi::smallFont( m_parent ) );
00077 QFontMetrics fm(f);
00078 int side1x=0, side1y=sy - fm.height(),
00079 sideNx=0, sideNy=ry - fm.height();
00081 QChar sideNChar(0x221E);
00082 uint sideNCharWidth = 2+2+ fm.width( sideNChar );
00083 QChar side1Char('1');
00084 uint side1CharWidth = 2+2+ fm.width( side1Char );
00085 p->setBrush(p->pen().color());
00086
00087 if(m_masterTable->x() < m_detailsTable->x())
00088 {
00089
00090 p->drawLine(rx - sideNCharWidth, ry, rx, ry);
00091 QPointArray pa(3);
00092 pa.setPoint(0, rx - 4, ry - 3);
00093 pa.setPoint(1, rx - 4, ry + 3);
00094 pa.setPoint(2, rx - 1, ry);
00095 p->drawPolygon(pa, true);
00096
00097
00098 p->drawLine(sx, sy - 1, sx + side1CharWidth -1, sy - 1);
00099 p->drawLine(sx, sy, sx + side1CharWidth -1, sy);
00100 p->drawLine(sx, sy + 1, sx + side1CharWidth -1, sy + 1);
00101
00102 side1x = sx;
00103
00104
00105 sideNx = rx - sideNCharWidth - 1;
00106
00107
00108 QPen pen(p->pen());
00109 if(m_selected)
00110 {
00111 QPen pen(p->pen());
00112 pen.setWidth(2);
00113 p->setPen(pen);
00114 }
00115
00116 p->drawLine(sx + side1CharWidth, sy, rx - sideNCharWidth, ry);
00117
00118 if(m_selected)
00119 {
00120 QPen pen(p->pen());
00121 pen.setWidth(1);
00122 p->setPen(pen);
00123 }
00124
00125 }
00126 else
00127 {
00128 int lx = rx + m_detailsTable->width();
00129 int rx = sx - m_masterTable->width();
00130
00131
00132 p->drawLine(lx, ry, lx + sideNCharWidth, ry);
00133 QPointArray pa(3);
00134 pa.setPoint(0, lx + 3, ry - 3);
00135 pa.setPoint(1, lx + 3, ry + 3);
00136 pa.setPoint(2, lx, ry);
00137 p->drawPolygon(pa, true);
00138
00139
00140
00141
00142
00143
00144
00145 p->drawLine(rx - side1CharWidth +1, sy - 1, rx, sy - 1);
00146 p->drawLine(rx - side1CharWidth +1, sy + 1, rx, sy + 1);
00147 p->drawLine(rx - side1CharWidth +1, sy, rx, sy);
00148
00149 side1x = rx - side1CharWidth;
00150
00151
00152 sideNx = lx + 1;
00153
00154
00155 if(m_selected)
00156 {
00157 QPen pen(p->pen());
00158 pen.setWidth(2);
00159 p->setPen(pen);
00160 }
00161
00162 p->drawLine(lx + sideNCharWidth, ry, rx - side1CharWidth, sy);
00163
00164 if(m_selected)
00165 {
00166 QPen pen(p->pen());
00167 pen.setWidth(1);
00168 p->setPen(pen);
00169 }
00170 }
00171
00172 p->drawText(side1x, side1y, side1CharWidth, fm.height(), Qt::AlignCenter, side1Char);
00173 p->drawText(sideNx, sideNy, sideNCharWidth, fm.height(), Qt::AlignCenter, sideNChar);
00174
00175
00176
00177 }
00178
00179 const QRect
00180 KexiRelationViewConnection::connectionRect()
00181 {
00182 int sx = m_masterTable->x() + m_parent->contentsX();
00183 int rx = m_detailsTable->x() + m_parent->contentsX();
00184 int ry = m_detailsTable->globalY(m_detailsField);
00185 int sy = m_masterTable->globalY(m_masterField);
00186
00187 int width, leftX, rightX;
00188
00189 if(sx < rx)
00190 {
00191 leftX = sx;
00192 rightX = rx;
00193 width = m_masterTable->width();
00194 }
00195 else
00196 {
00197 leftX = rx;
00198 rightX = sx;
00199 width = m_detailsTable->width();
00200 }
00201
00202
00203 int dx = QABS((leftX + width) - rightX);
00204 int dy = QABS(sy - ry) + 2;
00205
00206 int top = QMIN(sy, ry);
00207 int left = leftX + width;
00208
00209
00210
00211 QRect rect(left - 150, top - 150, dx + 150, dy + 150);
00212 kdDebug() << "KexiRelationViewConnection::connectionRect():" << m_oldRect << "," << rect << endl;
00213
00214 m_oldRect = rect;
00215
00216 return rect;
00217 }
00218
00219 bool
00220 KexiRelationViewConnection::matchesPoint(const QPoint &p, int tolerance)
00221 {
00222 QRect we = connectionRect();
00223
00224 if(!we.contains(p))
00225 return false;
00226
00234 int sx = m_masterTable->x() + m_masterTable->width();
00235 int sy = m_masterTable->globalY(m_masterField);
00236 int rx = m_detailsTable->x();
00237 int ry = m_detailsTable->globalY(m_detailsField);
00238
00239 int x1 = sx + 8;
00240 int y1 = sy;
00241 int x2 = rx - 8;
00242 int y2 = ry;
00243
00244 if(sx > rx)
00245 {
00246 x1 = m_detailsTable->x() + m_detailsTable->width();
00247 x2 = m_masterTable->x();
00248 y2 = sy;
00249 y1 = ry;
00250 }
00251
00252
00253
00254
00255
00256
00257 float mx = x2-x1;
00258 float my = y2-y1;
00259 float mag = sqrt(mx * mx + my * my);
00260 float u = (((p.x() - x1)*(x2 - x1))+((p.y() - y1)*(y2 - y1)))/(mag * mag);
00261 kdDebug() << "KexiRelationViewConnection::matchesPoint(): u: " << u << endl;
00262
00263 float iX = x1 + u * (x2 - x1);
00264 float iY = y1 + u * (y2 - y1);
00265 kdDebug() << "KexiRelationViewConnection::matchesPoint(): px: " << p.x() << endl;
00266 kdDebug() << "KexiRelationViewConnection::matchesPoint(): py: " << p.y() << endl;
00267 kdDebug() << "KexiRelationViewConnection::matchesPoint(): ix: " << iX << endl;
00268 kdDebug() << "KexiRelationViewConnection::matchesPoint(): iy: " << iY << endl;
00269
00270 float dX = iX - p.x();
00271 float dY = iY - p.y();
00272
00273 kdDebug() << "KexiRelationViewConnection::matchesPoint(): dx: " << dX << endl;
00274 kdDebug() << "KexiRelationViewConnection::matchesPoint(): dy: " << dY << endl;
00275
00276 float distance = sqrt(dX * dX + dY * dY);
00277 kdDebug() << "KexiRelationViewConnection::matchesPoint(): distance: " << distance << endl;
00278
00279 if(distance <= tolerance)
00280 return true;
00281
00282 return false;
00283 }
00284
00285 QString
00286 KexiRelationViewConnection::toString() const
00287 {
00288 QString str;
00290 if (m_masterTable && m_masterTable->schema()->table()) {
00291 str += (QString(m_masterTable->schema()->name()) + "." + m_masterField);
00292 }
00293 if (m_detailsTable && m_detailsTable->schema()->table()) {
00294 str += " - ";
00295 str += (QString(m_detailsTable->schema()->name()) + "." + m_detailsField);
00296 }
00297 return str;
00298 }