kexi

kexirelationviewtable.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2002, 2003 Lucijan Busch <lucijan@gmx.at>
3 Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include <stdlib.h>
22
23#include <tqheader.h>
24#include <tqlayout.h>
25#include <tqlabel.h>
26#include <tqpushbutton.h>
27#include <tqcursor.h>
28#include <tqpoint.h>
29#include <tqapplication.h>
30#include <tqbitmap.h>
31#include <tqstyle.h>
32
33#include <kdebug.h>
34#include <kiconloader.h>
35#include <tdeconfig.h>
36#include <tdeglobalsettings.h>
37
38#include <kexidb/tableschema.h>
39#include <kexidb/utils.h>
40#include <kexidragobjects.h>
41#include "kexirelationviewtable.h"
42#include "kexirelationview.h"
43
44KexiRelationViewTableContainer::KexiRelationViewTableContainer(
46 : TQFrame(parent,"KexiRelationViewTableContainer" )
47// , m_table(t)
48 , m_parent(parent)
49// , m_mousePressed(false)
50{
51
52// setFixedSize(100, 150);
53//js: resize(100, 150);
54 //setMouseTracking(true);
55
56 setFrameStyle( TQFrame::WinPanel | TQFrame::Raised );
57
58 TQVBoxLayout *lyr = new TQVBoxLayout(this,4,1); //js: using Q*BoxLayout is a good idea
59
60 m_tableHeader = new KexiRelationViewTableContainerHeader(schema->name(), this);
61
62 m_tableHeader->unsetFocus();
63 m_tableHeader->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed));
64 lyr->addWidget(m_tableHeader);
65 connect(m_tableHeader,TQ_SIGNAL(moved()),this,TQ_SLOT(moved()));
66 connect(m_tableHeader, TQ_SIGNAL(endDrag()), this, TQ_SIGNAL(endDrag()));
67
68 m_tableView = new KexiRelationViewTable(schema, parent, this, "KexiRelationViewTable");
69 //m_tableHeader->setFocusProxy( m_tableView );
70 m_tableView->setSizePolicy(TQSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Minimum));
71
72 m_tableView->setMaximumSize( m_tableView->sizeHint() );
73
74// m_tableView->resize( m_tableView->sizeHint() );
75 lyr->addWidget(m_tableView, 0);
76 connect(m_tableView, TQ_SIGNAL(tableScrolling()), this, TQ_SLOT(moved()));
77 connect(m_tableView, TQ_SIGNAL(contextMenu(TDEListView*, TQListViewItem*, const TQPoint&)),
78 this, TQ_SLOT(slotContextMenu(TDEListView*, TQListViewItem*, const TQPoint&)));
79}
80
81KexiRelationViewTableContainer::~KexiRelationViewTableContainer()
82{
83}
84
85KexiDB::TableOrQuerySchema* KexiRelationViewTableContainer::schema() const
86{
87 return m_tableView->schema();
88}
89
90void KexiRelationViewTableContainer::slotContextMenu(TDEListView *, TQListViewItem *, const TQPoint &p)
91{
92// m_parent->executePopup(p);
93 emit contextMenuRequest( p );
94}
95
96void KexiRelationViewTableContainer::moved() {
97// kdDebug()<<"finally emitting moved"<<endl;
98 emit moved(this);
99}
100
101int KexiRelationViewTableContainer::globalY(const TQString &field)
102{
103// kdDebug() << "KexiRelationViewTableContainer::globalY()" << endl;
104// TQPoint o = mapFromGlobal(TQPoint(0, (m_tableView->globalY(field))/*+m_parent->contentsY()*/));
105
106 TQPoint o(0, (m_tableView->globalY(field)) + m_parent->contentsY());
107// kdDebug() << "KexiRelationViewTableContainer::globalY() db2" << endl;
108 return m_parent->viewport()->mapFromGlobal(o).y();
109}
110
111#if 0//js
112TQSize KexiRelationViewTableContainer::sizeHint()
113{
114#ifdef TQ_WS_WIN
115 TQSize s = m_tableView->sizeHint()
116 + TQSize( 2 * 5 , m_tableHeader->height() + 2 * 5 );
117#else
118 TQSize s = m_tableView->sizeHint();
119 s.setWidth(s.width() + 4);
120 s.setHeight(m_tableHeader->height() + s.height());
121#endif
122 return s;
123}
124#endif
125
126void KexiRelationViewTableContainer::setFocus()
127{
128 kdDebug() << "SET FOCUS" << endl;
129 //select 1st:
130 if (m_tableView->firstChild()) {
131 if (!m_tableView->selectedItems().first())
132 m_tableView->setSelected( m_tableView->firstChild(), true );
133 }
134 m_tableHeader->setFocus();
135 m_tableView->setFocus();
136/* TQPalette p = tqApp->palette();
137 p.setColor( TQPalette::Active, TQColorGroup::Highlight, TDEGlobalSettings::highlightColor() );
138 p.setColor( TQPalette::Active, TQColorGroup::HighlightedText, TDEGlobalSettings::highlightedTextColor() );
139 m_tableView->setPalette(p);*/
140
141 raise();
142 repaint();
143 emit gotFocus();
144}
145
146void KexiRelationViewTableContainer::unsetFocus()
147{
148 kdDebug() << "UNSET FOCUS" << endl;
149// if (m_tableView->selectedItem()) //unselect item if was selected
150// m_tableView->setSelected(m_tableView->selectedItem(), false);
151// m_tableView->clearSelection();
152 m_tableHeader->unsetFocus();
153
154 m_tableView->clearSelection();
155
156// m_tableView->unsetPalette();
157/* TQPalette p = m_tableView->palette();
158// p.setColor( TQPalette::Active, TQColorGroup::Highlight, TDEGlobalSettings::highlightColor() );
159// p.setColor( TQPalette::Active, TQColorGroup::HighlightedText, TDEGlobalSettings::highlightedTextColor() );
160 p.setColor( TQPalette::Active, TQColorGroup::Highlight, p.color(TQPalette::Active, TQColorGroup::Background ) );
161// p.setColor( TQPalette::Active, TQColorGroup::Highlight, gray );
162 p.setColor( TQPalette::Active, TQColorGroup::HighlightedText, p.color(TQPalette::Active, TQColorGroup::Foreground ) );
163// p.setColor( TQPalette::Active, TQColorGroup::Highlight, green );
164// p.setColor( TQPalette::Active, TQColorGroup::HighlightedText, blue );
165 m_tableView->setPalette(p);*/
166
167 clearFocus();
168 repaint();
169}
170
171
172//END KexiRelationViewTableContainer
173
174//============================================================================
175//BEGIN KexiRelatoinViewTableContainerHeader
176
177KexiRelationViewTableContainerHeader::KexiRelationViewTableContainerHeader(
178 const TQString& text,TQWidget *parent)
179 :TQLabel(text,parent),m_dragging(false)
180{
181 setMargin(1);
182 m_activeBG = TDEGlobalSettings::activeTitleColor();
183 m_activeFG = TDEGlobalSettings::activeTextColor();
184 m_inactiveBG = TDEGlobalSettings::inactiveTitleColor();
185 m_inactiveFG = TDEGlobalSettings::inactiveTextColor();
186
187 installEventFilter(this);
188}
189
190KexiRelationViewTableContainerHeader::~KexiRelationViewTableContainerHeader()
191{
192}
193
194void KexiRelationViewTableContainerHeader::setFocus()
195{
196 setPaletteBackgroundColor(m_activeBG);
197 setPaletteForegroundColor(m_activeFG);
198}
199
200void KexiRelationViewTableContainerHeader::unsetFocus()
201{
202 setPaletteBackgroundColor(m_inactiveBG);
203 setPaletteForegroundColor(m_inactiveFG);
204}
205
206bool KexiRelationViewTableContainerHeader::eventFilter(TQObject *, TQEvent *ev)
207{
208 if (ev->type()==TQEvent::MouseMove)
209 {
210 if (m_dragging && static_cast<TQMouseEvent*>(ev)->state()==TQt::LeftButton) {
211 int diffX,diffY;
212 diffX=static_cast<TQMouseEvent*>(ev)->globalPos().x()-m_grabX;
213 diffY=static_cast<TQMouseEvent*>(ev)->globalPos().y()-m_grabY;
214 if ((abs(diffX)>2) || (abs(diffY)>2))
215 {
216 TQPoint newPos=parentWidget()->pos()+TQPoint(diffX,diffY);
217//correct the x position
218 if (newPos.x()<0) {
219 m_offsetX+=newPos.x();
220 newPos.setX(0);
221 }
222 else if (m_offsetX<0) {
223 m_offsetX+=newPos.x();
224 if (m_offsetX>0) {
225 newPos.setX(m_offsetX);
226 m_offsetX=0;
227 }
228 else newPos.setX(0);
229 }
230//correct the y position
231 if (newPos.y()<0) {
232 m_offsetY+=newPos.y();
233 newPos.setY(0);
234 }
235 else
236 if (m_offsetY<0) {
237 m_offsetY+=newPos.y();
238 if (m_offsetY>0) {
239 newPos.setY(m_offsetY);
240 m_offsetY=0;
241 }
242 else newPos.setY(0);
243 }
244//move and update helpers
245
246 parentWidget()->move(newPos);
247 m_grabX=static_cast<TQMouseEvent*>(ev)->globalPos().x();
248 m_grabY=static_cast<TQMouseEvent*>(ev)->globalPos().y();
249// kdDebug()<<"HEADER:emitting moved"<<endl;
250 emit moved();
251 }
252 return true;
253 }
254 }
255 return false;
256}
257
258void KexiRelationViewTableContainerHeader::mousePressEvent(TQMouseEvent *ev) {
259 kdDebug()<<"KexiRelationViewTableContainerHeader::Mouse Press Event"<<endl;
260 parentWidget()->setFocus();
261 ev->accept();
262 if (ev->button()==TQt::LeftButton) {
263 m_dragging=true;
264 m_grabX=ev->globalPos().x();
265 m_grabY=ev->globalPos().y();
266 m_offsetX=0;
267 m_offsetY=0;
268 setCursor(TQt::SizeAllCursor);
269 return;
270 }
271 if (ev->button()==TQt::RightButton) {
272 emit static_cast<KexiRelationViewTableContainer*>(parentWidget())
273 ->contextMenuRequest(ev->globalPos());
274 }
275// TQLabel::mousePressEvent(ev);
276}
277
278void KexiRelationViewTableContainerHeader::mouseReleaseEvent(TQMouseEvent *ev) {
279 kdDebug()<<"KexiRelationViewTableContainerHeader::Mouse Release Event"<<endl;
280 if (m_dragging && ev->button() & TQt::LeftButton) {
281 setCursor(TQt::ArrowCursor);
282 m_dragging=false;
283 emit endDrag();
284 }
285 ev->accept();
286}
287
288//END KexiRelatoinViewTableContainerHeader
289
290
291//=====================================================================================
292
293KexiRelationViewTable::KexiRelationViewTable(KexiDB::TableOrQuerySchema* tableOrQuerySchema,
294 KexiRelationView *view, TQWidget *parent, const char *name)
295 : KexiFieldListView(parent, name, KexiFieldListView::ShowAsterisk)
296 , m_view(view)
297{
298 setSchema(tableOrQuerySchema);
299 header()->hide();
300
301 connect(this, TQ_SIGNAL(dropped(TQDropEvent *, TQListViewItem *)), this, TQ_SLOT(slotDropped(TQDropEvent *)));
302 connect(this, TQ_SIGNAL(contentsMoving(int, int)), this, TQ_SLOT(slotContentsMoving(int,int)));
303}
304
305KexiRelationViewTable::~KexiRelationViewTable()
306{
307}
308
309TQSize KexiRelationViewTable::sizeHint() const
310{
311 TQFontMetrics fm(fontMetrics());
312
313// kdDebug() << schema()->name() << " cw=" << columnWidth(0) + fm.width("i")
314// << ", " << fm.width(schema()->name()+" ") << endl;
315
316 int maxWidth = -1;
317 const int iconWidth = IconSize(TDEIcon::Small) + fm.width("i")+20;
318 for (TQListViewItem *item = firstChild(); item; item = item->nextSibling())
319 maxWidth = TQMAX(maxWidth, iconWidth + fm.width(item->text(0)));
320
321 const uint rowCount = TQMIN( 8, childCount() );
322
323 TQSize s(
324 TQMAX( maxWidth, fm.width(schema()->name()+" ")),
325 rowCount*firstChild()->totalHeight() + 4 );
326 return s;
327}
328
329#if 0
330void KexiRelationViewTable::setReadOnly(bool b)
331{
332 setAcceptDrops(!b);
333 viewport()->setAcceptDrops(!b);
334}
335#endif
336
337int
338KexiRelationViewTable::globalY(const TQString &item)
339{
340 TQListViewItem *i = findItem(item, 0);
341 if (!i)
342 return -1;
343 int y = itemRect(i).y() + (itemRect(i).height() / 2);
344 if (contentsY() > itemPos(i))
345 y = 0;
346 else if (y == 0)
347 y = height();
348 return mapToGlobal(TQPoint(0, y)).y();
349}
350
351bool
352KexiRelationViewTable::acceptDrag(TQDropEvent *ev) const
353{
354// kdDebug() << "KexiRelationViewTable::acceptDrag()" << endl;
355 TQListViewItem *receiver = itemAt(ev->pos() - TQPoint(0,contentsY()));
356 if (!receiver || !KexiFieldDrag::canDecodeSingle(ev))
357 return false;
358 TQString sourceMimeType;
359 TQString srcTable;
360 TQString srcField;
361 if (!KexiFieldDrag::decodeSingle(ev,sourceMimeType,srcTable,srcField))
362 return false;
363 if (sourceMimeType!="kexi/table" && sourceMimeType=="kexi/query")
364 return false;
365 TQString f = receiver->text(0).stripWhiteSpace();
366 if (!srcField.stripWhiteSpace().startsWith("*") && !f.startsWith("*") && ev->source() != (TQWidget*)this)
367 return true;
368
369 return false;
370}
371
372void
373KexiRelationViewTable::slotDropped(TQDropEvent *ev)
374{
375 TQListViewItem *recever = itemAt(ev->pos() - TQPoint(0,contentsY()));
376 if (!recever || !KexiFieldDrag::canDecodeSingle(ev)) {
377 ev->ignore();
378 return;
379 }
380 TQString sourceMimeType;
381 TQString srcTable;
382 TQString srcField;
383 if (!KexiFieldDrag::decodeSingle(ev,sourceMimeType,srcTable,srcField))
384 return;
385 if (sourceMimeType!="kexi/table" && sourceMimeType=="kexi/query")
386 return;
387// kdDebug() << "KexiRelationViewTable::slotDropped() srcfield: " << srcField << endl;
388
389 TQString rcvField = recever->text(0);
390
391 SourceConnection s;
392 s.masterTable = srcTable;
393 s.detailsTable = schema()->name();
394 s.masterField = srcField;
395 s.detailsField = rcvField;
396
397 m_view->addConnection(s);
398
399 kdDebug() << "KexiRelationViewTable::slotDropped() " << srcTable << ":" << srcField << " "
400 << schema()->name() << ":" << rcvField << endl;
401 ev->accept();
402}
403
404void
405KexiRelationViewTable::slotContentsMoving(int,int)
406{
407 emit tableScrolling();
408}
409
410void KexiRelationViewTable::contentsMousePressEvent(TQMouseEvent *ev)
411{
412 parentWidget()->setFocus();
413 setFocus();
414 TDEListView::contentsMousePressEvent(ev);
415// if (ev->button()==TQt::RightButton)
416// static_cast<KexiRelationView*>(parentWidget())->executePopup(ev->pos());
417}
418
419TQRect KexiRelationViewTable::drawItemHighlighter(TQPainter *painter, TQListViewItem *item)
420{
421 if (painter) {
422 style().drawPrimitive(TQStyle::PE_FocusRect, painter, itemRect(item), colorGroup(),
423 TQStyle::Style_FocusAtBorder);
424 }
425 return itemRect(item);
426}
427
428#include "kexirelationviewtable.moc"
static bool canDecodeSingle(TQMimeSource *e)
static bool decodeSingle(TQDropEvent *e, TQString &sourceMimeType, TQString &sourceName, TQString &field)
KexiDB::TableOrQuerySchema * schema() const
provides a view for displaying relations between database tables.
int rowCount(Connection &conn, const TQString &sql)