00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <kdebug.h>
00022
00023 #include <qstringlist.h>
00024 #include <qlayout.h>
00025 #include <qlabel.h>
00026 #include <qheader.h>
00027 #include <qevent.h>
00028 #include <qpainter.h>
00029 #include <qstyle.h>
00030 #include <qlineedit.h>
00031 #include <qpopupmenu.h>
00032
00033 #include <klocale.h>
00034 #include <kaction.h>
00035 #include <kpopupmenu.h>
00036 #include <kglobalsettings.h>
00037 #include <kmessagebox.h>
00038
00039 #include <kexidb/tableschema.h>
00040 #include <kexidb/indexschema.h>
00041 #include <kexidb/utils.h>
00042
00043 #include "kexirelationview.h"
00044 #include "kexirelationviewtable.h"
00045 #include "kexirelationviewconnection.h"
00046 #include <kexi.h>
00047
00048 KexiRelationView::KexiRelationView(QWidget *parent, const char *name)
00049 : QScrollView(parent, name, WStaticContents)
00050 {
00051
00052
00053 m_selectedConnection = 0;
00054 m_readOnly=false;
00055 m_focusedTableView = 0;
00056 setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
00057
00058
00059
00060 viewport()->setPaletteBackgroundColor(colorGroup().mid());
00061 setFocusPolicy(WheelFocus);
00062 setResizePolicy(Manual);
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #if 0
00076 m_removeSelectedTableQueryAction = new KAction(i18n("&Hide Selected Table/Query"), "editdelete", "",
00077 this, SLOT(removeSelectedTableQuery()), parent->actionCollection(), "relationsview_removeSelectedTableQuery");
00078 m_removeSelectedConnectionAction = new KAction(i18n("&Remove Selected Relationship"), "button_cancel", "",
00079 this, SLOT(removeSelectedConnection()), parent->actionCollection(), "relationsview_removeSelectedConnection");
00080 m_openSelectedTableQueryAction = new KAction(i18n("&Open Selected Table/Query"), "", "",
00081 this, SLOT(openSelectedTableQuery()), 0, "relationsview_openSelectedTableQuery");
00082 #endif
00083
00084
00085
00086 #if 0
00087
00088
00089 m_popup = new KPopupMenu(this, "m_popup");
00090 m_openSelectedTableQueryAction->plug( m_popup );
00091 m_removeSelectedTableQueryAction->plug( m_popup );
00092 m_removeSelectedConnectionAction->plug( m_popup );
00093
00094 invalidateActions();
00095 #endif
00096
00097 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding, true);
00098 }
00099
00100 KexiRelationView::~KexiRelationView()
00101 {
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 KexiRelationViewTableContainer*
00117 KexiRelationView::addTable(KexiDB::TableSchema *t, const QRect &rect)
00118 {
00119 if(!t)
00120 return 0;
00121
00122 kdDebug() << "KexiRelationView::addTable(): " << t->name() << ", " << viewport() << endl;
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 KexiRelationViewTableContainer* c = m_tables.find(t->name());
00133 if (c) {
00134 kdWarning() << "KexiRelationView::addTable(): table already added" << endl;
00135 return c;
00136 }
00137
00138 c = new KexiRelationViewTableContainer(this,
00140 new KexiDB::TableOrQuerySchema(t)
00141 );
00142 connect(c, SIGNAL(endDrag()), this, SLOT(slotTableViewEndDrag()));
00143 connect(c, SIGNAL(gotFocus()), this, SLOT(slotTableViewGotFocus()));
00144
00145
00146 connect(c, SIGNAL(contextMenuRequest(const QPoint&)),
00147 this, SIGNAL(tableContextMenuRequest(const QPoint&)));
00148
00149 addChild(c, 100,100);
00150 if (rect.isValid()) {
00151 QSize finalSize = c->size().expandedTo( c->sizeHint() );
00152 QRect r = rect;
00153 r.setSize( finalSize + QSize(0,10) );
00154 moveChild( c, rect.left(), rect.top() );
00155
00156
00157 c->resize(c->sizeHint());
00158
00159
00160
00161
00162
00163
00164 }
00165 c->show();
00166 updateGeometry();
00167 if (!rect.isValid()) {
00168 c->updateGeometry();
00169 c->resize(c->sizeHint());
00170 }
00171 int x, y;
00172
00173 if(m_tables.count() > 0)
00174 {
00175 int place = -10;
00176 QDictIterator<KexiRelationViewTableContainer> it(m_tables);
00177 for(; it.current(); ++it)
00178 {
00179 int right = (*it)->x() + (*it)->width();
00180 if(right > place)
00181 place = right;
00182 }
00183
00184 x = place + 30;
00185 }
00186 else
00187 {
00188 x = 5;
00189 }
00190
00191 y = 5;
00192 QPoint p = viewportToContents(QPoint(x, y));
00193 recalculateSize(p.x() + c->width(), p.y() + c->height());
00194 if (!rect.isValid()) {
00195 moveChild(c, x, y);
00196 }
00197
00198 m_tables.insert(t->name(), c);
00199
00200 connect(c, SIGNAL(moved(KexiRelationViewTableContainer *)), this,
00201 SLOT(containerMoved(KexiRelationViewTableContainer *)));
00202
00203 if (hasFocus())
00204 c->setFocus();
00205
00206 return c;
00207 }
00208
00209 void
00210 KexiRelationView::addConnection(const SourceConnection& _conn)
00211 {
00212 SourceConnection conn = _conn;
00213 kdDebug() << "KexiRelationView::addConnection()" << endl;
00214
00215 KexiRelationViewTableContainer *master = m_tables[conn.masterTable];
00216 KexiRelationViewTableContainer *details = m_tables[conn.detailsTable];
00217 if (!master || !details)
00218 return;
00219
00221 KexiDB::TableSchema *masterTable = master->schema()->table();
00223 KexiDB::TableSchema *detailsTable = details->schema()->table();
00224 if (!masterTable || !detailsTable)
00225 return;
00226
00227
00228 KexiDB::Field *masterFld = masterTable->field(conn.masterField);
00229 KexiDB::Field *detailsFld = detailsTable->field(conn.detailsField);
00230 if (!masterFld || !detailsFld)
00231 return;
00232
00233 if (!masterFld->isUniqueKey()) {
00234 if (detailsFld->isUniqueKey()) {
00235
00236 KexiDB::Field *tmpFld = masterFld;
00237 masterFld = detailsFld;
00238 detailsFld = tmpFld;
00239 KexiDB::TableSchema *tmpTable = masterTable;
00240 masterTable = detailsTable;
00241 detailsTable = tmpTable;
00242 KexiRelationViewTableContainer *tmp = master;
00243 master = details;
00244 details = tmp;
00245 QString tmp_masterTable = conn.masterTable;
00246 conn.masterTable = conn.detailsTable;
00247 conn.detailsTable = tmp_masterTable;
00248 QString tmp_masterField = conn.masterField;
00249 conn.masterField = conn.detailsField;
00250 conn.detailsField = tmp_masterField;
00251 }
00252 }
00253
00254
00255
00256 KexiRelationViewConnection *connView = new KexiRelationViewConnection(master, details, conn, this);
00257 m_connectionViews.append(connView);
00258 updateContents(connView->connectionRect());
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 #if 0
00269 if(!interactive)
00270 {
00271 kdDebug() << "KexiRelationView::addConnection: adding self" << endl;
00272 RelationList l = m_relation->projectRelations();
00273 l.append(conn);
00274 m_relation->updateRelationList(this, l);
00275 }
00276 #endif
00277 }
00278
00279 void
00280 KexiRelationView::drawContents(QPainter *p, int cx, int cy, int cw, int ch)
00281 {
00282 KexiRelationViewConnection *cview;
00283
00284
00285 QRect clipping(cx, cy, cw, ch);
00286 for(cview = m_connectionViews.first(); cview; cview = m_connectionViews.next())
00287 {
00288 if(clipping.intersects(cview->oldRect() | cview->connectionRect()))
00289 cview->drawConnection(p);
00290 }
00291 }
00292
00293 void
00294 KexiRelationView::slotTableScrolling(QString table)
00295 {
00296 KexiRelationViewTableContainer *c = m_tables[table];
00297
00298 if(c)
00299 containerMoved(c);
00300 }
00301
00302 void
00303 KexiRelationView::containerMoved(KexiRelationViewTableContainer *c)
00304 {
00305 KexiRelationViewConnection *cview;
00306 QRect r;
00307 for (ConnectionListIterator it(m_connectionViews); ((cview=it.current())); ++it) {
00309 if(cview->masterTable() == c || cview->detailsTable() == c
00310 || cview->connectionRect().intersects(r))
00311 {
00312 r |= cview->oldRect();
00313 kdDebug() << r << endl;
00314 r |= cview->connectionRect();
00315 kdDebug() << r << endl;
00316 }
00317
00318
00319
00320 }
00322
00323 updateContents();
00324
00325
00326
00327
00328 QPoint p = viewportToContents(QPoint(c->x(), c->y()));
00329 recalculateSize(p.x() + c->width(), p.y() + c->height());
00330
00331 emit tablePositionChanged(c);
00332 }
00333
00334 void
00335 KexiRelationView::setReadOnly(bool b)
00336 {
00337 m_readOnly=b;
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 }
00348
00349 void
00350 KexiRelationView::slotListUpdate(QObject *)
00351 {
00352 #if 0
00353 if(s != this)
00354 {
00355 m_connectionViews.clear();
00356 RelationList rl = m_relation->projectRelations();
00357 if(!rl.isEmpty())
00358 {
00359 for(RelationList::Iterator it = rl.begin(); it != rl.end(); it++)
00360 {
00361 addConnection((*it), true);
00362 }
00363 }
00364 }
00365
00366 updateContents();
00367 #endif
00368 }
00369
00370 void
00371 KexiRelationView::contentsMousePressEvent(QMouseEvent *ev)
00372 {
00373 KexiRelationViewConnection *cview;
00374 for(cview = m_connectionViews.first(); cview; cview = m_connectionViews.next())
00375 {
00376 if(!cview->matchesPoint(ev->pos(), 3))
00377 continue;
00378 clearSelection();
00379 setFocus();
00380 cview->setSelected(true);
00381 updateContents(cview->connectionRect());
00382 m_selectedConnection = cview;
00383 emit connectionViewGotFocus();
00384
00385
00386 if(ev->button() == RightButton) {
00387 kdDebug() << "KexiRelationView::contentsMousePressEvent(): context" << endl;
00388
00389
00390
00391 emit connectionContextMenuRequest( ev->globalPos() );
00392
00393 }
00394 return;
00395 }
00396
00397 clearSelection();
00398
00399 if(ev->button() == RightButton) {
00400
00401
00402 emit emptyAreaContextMenuRequest( ev->globalPos() );
00403
00404 }
00405 else {
00406 emit emptyAreaGotFocus();
00407 }
00408 setFocus();
00409
00410 }
00411
00412 void KexiRelationView::clearSelection()
00413 {
00414 if (m_focusedTableView) {
00415 m_focusedTableView->unsetFocus();
00416 m_focusedTableView = 0;
00417
00418
00419 }
00420 if (m_selectedConnection) {
00421 m_selectedConnection->setSelected(false);
00422 updateContents(m_selectedConnection->connectionRect());
00423 m_selectedConnection = 0;
00424
00425 }
00426 }
00427
00428 void
00429 KexiRelationView::keyPressEvent(QKeyEvent *ev)
00430 {
00431 kdDebug() << "KexiRelationView::keyPressEvent()" << endl;
00432
00433 if (ev->key()==KGlobalSettings::contextMenuKey()) {
00434 if (m_selectedConnection) {
00435 emit connectionContextMenuRequest(
00436 mapToGlobal(m_selectedConnection->connectionRect().center()) );
00437 }
00438
00439
00440 }
00441 else {
00442 if(ev->key() == Key_Delete)
00443 removeSelectedObject();
00444 }
00445 }
00446
00447 void
00448 KexiRelationView::recalculateSize(int width, int height)
00449 {
00450 kdDebug() << "recalculateSize(" << width << ", " << height << ")" << endl;
00451 int newW = contentsWidth(), newH = contentsHeight();
00452 kdDebug() << "contentsSize(" << newW << ", " << newH << ")" << endl;
00453
00454 if(newW < width)
00455 newW = width;
00456
00457 if(newH < height)
00458 newH = height;
00459
00460 resizeContents(newW, newH);
00461 }
00462
00466 void
00467 KexiRelationView::stretchExpandSize()
00468 {
00469 int max_x=-1, max_y=-1;
00470 QDictIterator<KexiRelationViewTableContainer> it(m_tables);
00471 for (;it.current(); ++it) {
00472 if (it.current()->right()>max_x)
00473 max_x = it.current()->right();
00474 if (it.current()->bottom()>max_y)
00475 max_y = it.current()->bottom();
00476 }
00477 QPoint p = viewportToContents(QPoint(max_x, max_y) + QPoint(3,3));
00478 resizeContents(p.x(), p.y());
00479 }
00480
00481 void KexiRelationView::slotTableViewEndDrag()
00482 {
00483 kdDebug() << "END DRAG!" <<endl;
00484 stretchExpandSize();
00485
00486 }
00487
00488 void
00489 KexiRelationView::removeSelectedObject()
00490 {
00491 if (m_selectedConnection) {
00492 removeConnection(m_selectedConnection);
00493
00494 #if 0
00495 RelationList l = m_relation->projectRelations();
00496 RelationList nl;
00497 for(RelationList::Iterator it = l.begin(); it != l.end(); ++it)
00498 {
00499 if((*it).srcTable == m_selectedConnection->connection().srcTable
00500 && (*it).rcvTable == m_selectedConnection->connection().rcvTable
00501 && (*it).srcField == m_selectedConnection->connection().srcField
00502 && (*it).rcvField == m_selectedConnection->connection().rcvField)
00503 {
00504 kdDebug() << "KexiRelationView::removeSelectedConnection(): matching found!" << endl;
00505
00506 }
00507 else
00508 {
00509 nl.append(*it);
00510 }
00511 }
00512
00513 kdDebug() << "KexiRelationView::removeSelectedConnection(): d2" << endl;
00514 m_relation->updateRelationList(this, nl);
00515 kdDebug() << "KexiRelationView::removeSelectedConnection(): d3" << endl;
00516 #endif
00517 delete m_selectedConnection;
00518 m_selectedConnection = 0;
00519
00520 }
00521 else if (m_focusedTableView) {
00522 KexiRelationViewTableContainer *tmp = m_focusedTableView;
00523 m_focusedTableView = 0;
00524 hideTable(tmp);
00525 }
00526 }
00527
00528 void
00529 KexiRelationView::hideTable(KexiRelationViewTableContainer* tableView)
00530 {
00532 KexiDB::TableSchema *ts = tableView->schema()->table();
00533
00534 QPtrListIterator<KexiRelationViewConnection> it(m_connectionViews);
00535 for (;it.current();) {
00536 if (it.current()->masterTable() == tableView
00537 || it.current()->detailsTable() == tableView)
00538 {
00539
00540 removeConnection(it.current());
00541 }
00542 else {
00543 ++it;
00544 }
00545 }
00546 m_tables.take(tableView->schema()->name());
00547 delete tableView;
00548 emit tableHidden( *ts );
00549 }
00550
00551 void
00552 KexiRelationView::hideAllTablesExcept( KexiDB::TableSchema::List* tables )
00553 {
00555 for (TablesDictIterator it(m_tables); it.current();) {
00556 KexiDB::TableSchema *table = it.current()->schema()->table();
00557 if (!table || tables->findRef( table )!=-1) {
00558 ++it;
00559 continue;
00560 }
00561 hideTable(it.current());
00562 }
00563 }
00564
00565 void
00566 KexiRelationView::removeConnection(KexiRelationViewConnection *conn)
00567 {
00568 emit aboutConnectionRemove(conn);
00569 m_connectionViews.remove(conn);
00570 updateContents(conn->connectionRect());
00571 kdDebug() << "KexiRelationView::removeConnection()" << endl;
00572 }
00573
00574 void KexiRelationView::slotTableViewGotFocus()
00575 {
00576 if (m_focusedTableView == sender())
00577 return;
00578 kdDebug() << "GOT FOCUS!" <<endl;
00579 clearSelection();
00580
00581
00582 m_focusedTableView = (KexiRelationViewTableContainer*)sender();
00583
00584 emit tableViewGotFocus();
00585 }
00586
00587 QSize KexiRelationView::sizeHint() const
00588 {
00589 return QSize(QScrollView::sizeHint());
00590 }
00591
00592 void KexiRelationView::clear()
00593 {
00594 removeAllConnections();
00595 m_tables.setAutoDelete(true);
00596 m_tables.clear();
00597 m_tables.setAutoDelete(false);
00598 updateContents();
00599 }
00600
00601 void KexiRelationView::removeAllConnections()
00602 {
00603 clearSelection();
00604 m_connectionViews.setAutoDelete(true);
00605 m_connectionViews.clear();
00606 m_connectionViews.setAutoDelete(false);
00607 updateContents();
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 #include "kexirelationview.moc"