kexi

kexirelationwidget.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
3 Copyright (C) 2003 Joseph Wenninger<jowenn@kde.org>
4 Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this program; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include "kexirelationwidget.h"
23
24#include <tqlayout.h>
25#include <tqlistbox.h>
26#include <tqpushbutton.h>
27#include <tqtimer.h>
28
29#include <kcombobox.h>
30#include <tdelocale.h>
31#include <kdebug.h>
32#include <kiconloader.h>
33#include <kpushbutton.h>
34
35#include <kexidb/connection.h>
36#include <kexidb/utils.h>
37
38#include <kexiproject.h>
39#include <keximainwindow.h>
40#include "kexirelationview.h"
41#include "kexirelationviewtable.h"
42#include "kexirelationviewconnection.h"
43
44KexiRelationWidget::KexiRelationWidget(KexiMainWindow *win, TQWidget *parent,
45 const char *name)
46 : KexiViewBase(win, parent, name)
47 , m_win(win)
48{
49 m_conn = m_win->project()->dbConnection();
50
51 TQHBoxLayout *hlyr = new TQHBoxLayout(0);
52 TQGridLayout *g = new TQGridLayout(this);
53 g->addLayout( hlyr, 0, 0 );
54
55 m_tableCombo = new KComboBox(this, "tables_combo");
56 m_tableCombo->setMinimumWidth(TQFontMetrics(font()).width("w")*20);
57 TQLabel *lbl = new TQLabel(m_tableCombo, i18n("Table")+": ", this);
58 lbl->setIndent(3);
59 m_tableCombo->setInsertionPolicy(TQComboBox::NoInsertion);
60 hlyr->addWidget(lbl);
61 hlyr->addWidget(m_tableCombo);
62 m_tableCombo->setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred));
63 fillTablesCombo();
64
65 m_btnAdd = new KPushButton(i18n("&Add"), this);
66 hlyr->addWidget(m_btnAdd);
67 hlyr->addStretch(1);
68 connect(m_btnAdd, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotAddTable()));
69
70 m_relationView = new KexiRelationView(this, "relation_view");
71 setViewWidget(m_relationView);
72 g->addWidget(m_relationView, 1, 0);
73 //m_relationView->setFocus();
74
75 //actions
76 m_tableQueryPopup = new TDEPopupMenu(this, "m_popup");
77 m_tableQueryPopupTitleID = m_tableQueryPopup->insertTitle(SmallIcon("table"), "");
78 connect(m_tableQueryPopup, TQ_SIGNAL(aboutToShow()), this, TQ_SLOT(aboutToShowPopupMenu()));
79
80 m_connectionPopup = new TDEPopupMenu(this, "m_connectionPopup");
81 m_connectionPopupTitleID = m_connectionPopup->insertTitle("");
82 connect(m_connectionPopup, TQ_SIGNAL(aboutToShow()), this, TQ_SLOT(aboutToShowPopupMenu()));
83
84 m_areaPopup = new TDEPopupMenu(this, "m_areaPopup");
85
86 m_openSelectedTableAction = new TDEAction(i18n("&Open Table"), SmallIcon("document-open"), TDEShortcut(),
87 this, TQ_SLOT(openSelectedTable()), this, "relationsview_openTable");
88 m_openSelectedTableAction->plug( m_tableQueryPopup );
89 m_designSelectedTableAction = new TDEAction(i18n("&Design Table"), SmallIcon("edit"), TDEShortcut(),
90 this, TQ_SLOT(designSelectedTable()), this, "relationsview_designTable");
91 m_designSelectedTableAction->plug( m_tableQueryPopup );
92 m_tableQueryPopup->insertSeparator();
93
94 TDEAction* hide_action = plugSharedAction("edit_delete", i18n("&Hide Table"), m_tableQueryPopup);
95 hide_action->setIconSet(TQIconSet());
96
97 plugSharedAction("edit_delete",m_connectionPopup);
98 plugSharedAction("edit_delete",this, TQ_SLOT(removeSelectedObject()));
99
100 connect(m_relationView, TQ_SIGNAL(tableViewGotFocus()),
101 this, TQ_SLOT(tableViewGotFocus()));
102 connect(m_relationView, TQ_SIGNAL(connectionViewGotFocus()),
103 this, TQ_SLOT(connectionViewGotFocus()));
104 connect(m_relationView, TQ_SIGNAL(emptyAreaGotFocus()),
105 this, TQ_SLOT(emptyAreaGotFocus()));
106 connect(m_relationView, TQ_SIGNAL(tableContextMenuRequest( const TQPoint& )),
107 this, TQ_SLOT(tableContextMenuRequest( const TQPoint& )));
108 connect(m_relationView, TQ_SIGNAL(connectionContextMenuRequest( const TQPoint& )),
109 this, TQ_SLOT(connectionContextMenuRequest( const TQPoint& )));
110 connect(m_relationView, TQ_SIGNAL(tableHidden(KexiDB::TableSchema&)),
111 this, TQ_SLOT(slotTableHidden(KexiDB::TableSchema&)));
112 connect(m_relationView, TQ_SIGNAL(tablePositionChanged(KexiRelationViewTableContainer*)),
113 this, TQ_SIGNAL(tablePositionChanged(KexiRelationViewTableContainer*)));
114 connect(m_relationView, TQ_SIGNAL(aboutConnectionRemove(KexiRelationViewConnection*)),
115 this, TQ_SIGNAL(aboutConnectionRemove(KexiRelationViewConnection*)));
116
117#if 0
118 if(!embedd)
119 {
120/*todo setContextHelp(i18n("Relations"), i18n("To create a relationship simply drag the source field onto the target field. "
121 "An arrowhead is used to show which table is the parent (master) and which table is the child (slave) in the relationship."));*/
122 }
123#endif
124// else
125//js: while embedding means read-only? m_relationView->setReadOnly(true);
126
127#ifdef TESTING_KexiRelationWidget
128 for (int i=0;i<(int)m_db->tableNames().count();i++)
129 TQTimer::singleShot(100,this,TQ_SLOT(slotAddTable()));
130#endif
131
132 invalidateActions();
133}
134
135KexiRelationWidget::~KexiRelationWidget()
136{
137}
138
139TablesDict* KexiRelationWidget::tables() const
140{
141 return m_relationView->tables();
142}
143
144KexiRelationViewTableContainer* KexiRelationWidget::table(const TQString& name) const
145{
146 return m_relationView->tables()->find( name );
147}
148
149const ConnectionList* KexiRelationWidget::connections() const
150{
151 return m_relationView->connections();
152}
153
154void
155KexiRelationWidget::slotAddTable()
156{
157 if (m_tableCombo->currentItem()==-1)
158 return;
159 TQString tname = m_tableCombo->text(m_tableCombo->currentItem());
160 KexiDB::TableSchema *t = m_conn->tableSchema(tname);
161 addTable(t);
162}
163
164void
165KexiRelationWidget::addTable(KexiDB::TableSchema *t, const TQRect &rect)
166{
167 if (!t)
168 return;
169 if (!m_relationView->tableContainer(t)) {
170 KexiRelationViewTableContainer *c = m_relationView->addTableContainer(t, rect);
171 kdDebug() << "KexiRelationWidget::slotAddTable(): adding table " << t->name() << endl;
172 if (!c)
173 return;
174 connect(c->tableView(), TQ_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&,int)),
175 this, TQ_SLOT(slotTableFieldDoubleClicked(TQListViewItem*,const TQPoint&,int)));
176 }
177
178 const TQString tname = t->name().lower();
179 const int count = m_tableCombo->count();
180 int i = 0;
181 for (; i < count; i++ ) {
182 if (m_tableCombo->text(i).lower() == tname )
183 break;
184 }
185 if (i<count) {
186 int oi = m_tableCombo->currentItem();
187 kdDebug()<<"KexiRelationWidget::slotAddTable(): removing a table from the combo box"<<endl;
188 m_tableCombo->removeItem(i);
189 if (m_tableCombo->count()>0) {
190 if (oi>=m_tableCombo->count()) {
191 oi=m_tableCombo->count()-1;
192 }
193 m_tableCombo->setCurrentItem(oi);
194 }
195 else {
196 m_tableCombo->setEnabled(false);
197 m_btnAdd->setEnabled(false);
198 }
199 }
200 emit tableAdded(*t);
201}
202
203void
204KexiRelationWidget::addConnection(const SourceConnection& conn)
205{
206 m_relationView->addConnection(conn);
207}
208
209void
210KexiRelationWidget::addTable(const TQString& t)
211{
212 for(int i=0; i < m_tableCombo->count(); i++)
213 {
214 if(m_tableCombo->text(i) == t)
215 {
216 m_tableCombo->setCurrentItem(i);
217 slotAddTable();
218 }
219 }
220}
221
222void KexiRelationWidget::tableViewGotFocus()
223{
224// if (m_relationView->focusedTableView == sender())
225// return;
226// kdDebug() << "GOT FOCUS!" <<endl;
227// clearSelection();
228// if (m_focusedTableView)
229// m_focusedTableView->unsetFocus();
230// m_focusedTableView = (KexiRelationViewTableContainer*)sender();
231 invalidateActions();
232}
233
234void KexiRelationWidget::connectionViewGotFocus()
235{
236 invalidateActions();
237}
238
239void KexiRelationWidget::emptyAreaGotFocus()
240{
241 invalidateActions();
242}
243
244void KexiRelationWidget::tableContextMenuRequest(const TQPoint& pos)
245{
246 invalidateActions();
247 executePopup( pos );
248}
249
250void KexiRelationWidget::connectionContextMenuRequest(const TQPoint& pos)
251{
252 invalidateActions();
253 executePopup( pos );
254// m_connectionPopup->exec(pos);
255}
256
257void KexiRelationWidget::emptyAreaContextMenuRequest( const TQPoint& /*pos*/ )
258{
259 invalidateActions();
260 //TODO
261}
262
263void KexiRelationWidget::invalidateActions()
264{
265 setAvailable("edit_delete", m_relationView->selectedConnection() || m_relationView->focusedTableView());
266}
267
268void KexiRelationWidget::executePopup( TQPoint pos )
269{
270 if (pos==TQPoint(-1,-1)) {
271 pos = mapToGlobal(
272 m_relationView->focusedTableView() ? m_relationView->focusedTableView()->pos() + m_relationView->focusedTableView()->rect().center() : rect().center() );
273 }
274 if (m_relationView->focusedTableView())
275 m_tableQueryPopup->exec(pos);
276 else if (m_relationView->selectedConnection())
277 m_connectionPopup->exec(pos);
278}
279
280void KexiRelationWidget::removeSelectedObject()
281{
282 m_relationView->removeSelectedObject();
283}
284
285void KexiRelationWidget::openSelectedTable()
286{
288 if (!m_relationView->focusedTableView() || !m_relationView->focusedTableView()->schema()->table())
289 return;
290 bool openingCancelled;
291 m_win->openObject("kexi/table", m_relationView->focusedTableView()->schema()->name(),
292 Kexi::DataViewMode, openingCancelled);
293}
294
295void KexiRelationWidget::designSelectedTable()
296{
298 if (!m_relationView->focusedTableView() || !m_relationView->focusedTableView()->schema()->table())
299 return;
300 bool openingCancelled;
301 m_win->openObject("kexi/table", m_relationView->focusedTableView()->schema()->name(),
302 Kexi::DesignViewMode, openingCancelled);
303}
304
305TQSize KexiRelationWidget::sizeHint() const
306{
307 return m_relationView->sizeHint();
308}
309
310void KexiRelationWidget::slotTableHidden(KexiDB::TableSchema &table)
311{
312 const TQString &t = table.name().lower();
313 int i;
314 for (i=0; i<m_tableCombo->count() && t > m_tableCombo->text(i).lower(); i++)
315 ;
316 m_tableCombo->insertItem(table.name(), i);
317 if (!m_tableCombo->isEnabled()) {
318 m_tableCombo->setCurrentItem(0);
319 m_tableCombo->setEnabled(true);
320 m_btnAdd->setEnabled(true);
321 }
322
323 emit tableHidden(table);
324}
325
326void KexiRelationWidget::aboutToShowPopupMenu()
327{
329 if (m_relationView->focusedTableView() && m_relationView->focusedTableView()->schema()->table()) {
330 m_tableQueryPopup->changeTitle(m_tableQueryPopupTitleID, SmallIcon("table"),
331 TQString(m_relationView->focusedTableView()->schema()->name()) + " : " + i18n("Table"));
332 }
333 else if (m_relationView->selectedConnection()) {
334 m_connectionPopup->changeTitle( m_connectionPopupTitleID,
335 m_relationView->selectedConnection()->toString() + " : " + i18n("Relationship") );
336 }
337}
338
339void
340KexiRelationWidget::slotTableFieldDoubleClicked(TQListViewItem *i,const TQPoint&,int)
341{
342 if (!sender()->isA("KexiRelationViewTable"))
343 return;
344 const KexiRelationViewTable* t = static_cast<const KexiRelationViewTable*>(sender());
345 const TQStringList selectedFieldNames( t->selectedFieldNames() );
346 if (selectedFieldNames.count()==1)
347 emit tableFieldDoubleClicked( t->schema()->table(), selectedFieldNames.first() );
348}
349
350void
351KexiRelationWidget::clear()
352{
353 m_relationView->clear();
354 fillTablesCombo();
355}
356
358void KexiRelationWidget::removeAllConnections()
359{
360 m_relationView->removeAllConnections();
361}
362
363void
364KexiRelationWidget::fillTablesCombo()
365{
366 m_tableCombo->clear();
367 TQStringList tmp = m_conn->tableNames();
368 tmp.sort();
369 m_tableCombo->insertStringList(tmp);
370}
371
372void
373KexiRelationWidget::objectCreated(const TQCString &mime, const TQCString& name)
374{
375 if (mime=="kexi/table" || mime=="kexi/query") {
377 m_tableCombo->insertItem(TQString(name));
378 m_tableCombo->listBox()->sort();
379 }
380}
381
382void
383KexiRelationWidget::objectDeleted(const TQCString &mime, const TQCString& name)
384{
385 if (mime=="kexi/table" || mime=="kexi/query") {
386 TQString strName(name);
387 for (int i=0; i<m_tableCombo->count(); i++) {
389 if (m_tableCombo->text(i)==strName) {
390 m_tableCombo->removeItem(i);
391 if (m_tableCombo->currentItem()==i) {
392 if (i==(m_tableCombo->count()-1))
393 m_tableCombo->setCurrentItem(i-1);
394 else
395 m_tableCombo->setCurrentItem(i);
396 }
397 break;
398 }
399 }
400 }
401}
402
403void
404KexiRelationWidget::objectRenamed(const TQCString &mime, const TQCString& name, const TQCString& newName)
405{
406 if (mime=="kexi/table" || mime=="kexi/query") {
407 TQString strName(name);
408 for (int i=0; i<m_tableCombo->count(); i++) {
410 if (m_tableCombo->text(i)==strName) {
411 m_tableCombo->changeItem(TQString(newName), i);
412 m_tableCombo->listBox()->sort();
413 break;
414 }
415 }
416 }
417}
418
419void
420KexiRelationWidget::hideAllTablesExcept( KexiDB::TableSchema::List* tables )
421{
422 m_relationView->hideAllTablesExcept(tables);
423}
424
425#include "kexirelationwidget.moc"
TableSchema * table() const
TQPtrList< TableSchema > List
Type of tables list.
Definition tableschema.h:45
KexiDB::TableOrQuerySchema * schema() const
TQStringList selectedFieldNames() const
Kexi's main window interface This interface is implemented by KexiMainWindowImpl class.
provides a view for displaying relations between database tables.
Base class for single view embeddable of in KexiDialogBase.
virtual void setAvailable(const char *action_name, bool set)