22#include <tqobjectlist.h>
25#include <tqapplication.h>
26#include <tqfocusdata.h>
30#include "kexidbform.h"
31#include "kexiformpart.h"
32#include "kexiformscrollview.h"
34#include <formeditor/objecttree.h>
35#include <formeditor/formmanager.h>
36#include <formeditor/widgetlibrary.h>
37#include <widget/tableview/kexidataawareobjectiface.h>
38#include <widget/kexiscrollview.h>
39#include <kexiutils/utils.h>
42class KexiDBForm::Private
47 , orderedFocusWidgetsIterator(orderedFocusWidgets)
58 int indexOfDataAwareWidget(TQWidget *
widget)
const
68 TQMapConstIterator<KexiDataItemInterface*, uint> indicesForDataAwareWidgetsIt(
69 indicesForDataAwareWidgets.find(item));
70 if (indicesForDataAwareWidgetsIt == indicesForDataAwareWidgets.constEnd())
72 kexipluginsdbg <<
"KexiDBForm: column # for item: "
73 << indicesForDataAwareWidgetsIt.data() << endl;
74 return indicesForDataAwareWidgetsIt.data();
78 void setOrderedFocusWidgetsIteratorTo( TQWidget *
widget )
80 if (orderedFocusWidgetsIterator.current() ==
widget)
82 orderedFocusWidgetsIterator.toFirst();
83 while (orderedFocusWidgetsIterator.current() && orderedFocusWidgetsIterator.current()!=
widget)
84 ++orderedFocusWidgetsIterator;
89 TQPtrList<TQWidget> orderedFocusWidgets;
91 TQPtrList<TQWidget> orderedDataAwareWidgets;
92 TQMap<KexiDataItemInterface*, uint> indicesForDataAwareWidgets;
93 TQPtrListIterator<TQWidget> orderedFocusWidgetsIterator;
97 bool autoTabStops : 1;
98 bool popupFocused : 1;
105 : KexiDBFormBase(parent, name)
109 installEventFilter(
this);
112 d->dataAwareObject = dataAwareObject;
113 m_hasFocusableWidget =
false;
115 kexipluginsdbg <<
"KexiDBForm::KexiDBForm(): " << endl;
116 setCursor(TQCursor(TQt::ArrowCursor));
117 setAcceptDrops(
true );
120KexiDBForm::~KexiDBForm()
122 kexipluginsdbg <<
"KexiDBForm::~KexiDBForm(): close" << endl;
129static void repaintAll(TQWidget *w)
131 TQObjectList *list = w->queryList(
"TQWidget");
132 TQObjectListIt it(*list);
133 for (TQObject *obj; (obj=it.current()); ++it ) {
134 static_cast<TQWidget*
>(obj)->repaint();
140KexiDBForm::drawRect(
const TQRect& r,
int type)
142 TQValueList<TQRect> l;
152 bool unclipped = testWFlags( WPaintUnclipped );
153 setWFlags( WPaintUnclipped );
155 if (d->prev_rect.isValid()) {
157 p.drawPixmap( TQPoint(d->prev_rect.x()-2, d->prev_rect.y()-2), d->buffer,
158 TQRect(d->prev_rect.x()-2, d->prev_rect.y()-2, d->prev_rect.width()+4, d->prev_rect.height()+4));
160 p.setBrush(TQBrush::NoBrush);
162 p.setPen(TQPen(white, 1, TQt::DotLine));
164 p.setPen(TQPen(white, 2));
165 p.setRasterOp(XorROP);
167 d->prev_rect = TQRect();
168 TQValueList<TQRect>::ConstIterator endIt = list.constEnd();
169 for(TQValueList<TQRect>::ConstIterator it = list.constBegin(); it != endIt; ++it) {
171 if (d->prev_rect.isValid())
172 d->prev_rect = d->prev_rect.unite(*it);
178 clearWFlags( WPaintUnclipped );
186 d->buffer.resize( width(), height() );
187 d->buffer = TQPixmap::grabWindow( winId() );
188 d->prev_rect = TQRect();
196 bool unclipped = testWFlags( WPaintUnclipped );
197 setWFlags( WPaintUnclipped );
200 p.drawPixmap( TQPoint(0,0), d->buffer, TQRect(0,0,d->buffer.width(), d->buffer.height()) );
203 clearWFlags( WPaintUnclipped );
212 TQPoint fromPoint, toPoint;
213 if(from && from->parentWidget() && (from !=
this))
214 fromPoint = from->parentWidget()->mapTo(
this, from->pos());
215 if(to && to->parentWidget() && (to !=
this))
216 toPoint = to->parentWidget()->mapTo(
this, to->pos());
220 bool unclipped = testWFlags( WPaintUnclipped );
221 setWFlags( WPaintUnclipped );
223 if (d->prev_rect.isValid()) {
225 p.drawPixmap( TQPoint(d->prev_rect.x(), d->prev_rect.y()), d->buffer,
226 TQRect(d->prev_rect.x(), d->prev_rect.y(), d->prev_rect.width(), d->prev_rect.height()));
229 p.setPen( TQPen(TQt::red, 2) );
233 TQPixmap pix1 = TQPixmap::grabWidget(from);
234 TQPixmap pix2 = TQPixmap::grabWidget(to);
236 if((from !=
this) && (to !=
this))
237 p.drawLine( from->parentWidget()->mapTo(
this, from->geometry().center()), to->parentWidget()->mapTo(
this, to->geometry().center()) );
239 p.drawPixmap(fromPoint.x(), fromPoint.y(), pix1);
240 p.drawPixmap(toPoint.x(), toPoint.y(), pix2);
243 p.drawRoundRect(2, 2, width()-4, height()-4, 4, 4);
245 p.drawRoundRect(toPoint.x(), toPoint.y(), to->width(), to->height(), 5, 5);
249 p.drawRoundRect(2, 2, width()-4, height()-4, 4, 4);
251 p.drawRoundRect(fromPoint.x(), fromPoint.y(), from->width(), from->height(), 5, 5);
253 if((to ==
this) || (from ==
this))
254 d->prev_rect = TQRect(0, 0, d->buffer.width(), d->buffer.height());
257 d->prev_rect.setX( (fromPoint.x() < toPoint.x()) ? (fromPoint.x() - 5) : (toPoint.x() - 5) );
258 d->prev_rect.setY( (fromPoint.y() < toPoint.y()) ? (fromPoint.y() - 5) : (toPoint.y() - 5) );
259 d->prev_rect.setRight( (fromPoint.x() < toPoint.x()) ? (toPoint.x() + to->width() + 10) : (fromPoint.x() + from->width() + 10) );
260 d->prev_rect.setBottom( (fromPoint.y() < toPoint.y()) ? (toPoint.y() + to->height() + 10) : (fromPoint.y() + from->height() + 10) ) ;
263 d->prev_rect = TQRect(fromPoint.x()- 5, fromPoint.y() -5, from->width() + 10, from->height() + 10);
266 clearWFlags( WPaintUnclipped );
271KexiDBForm::sizeHint()
const
274 return TQSize(400,300);
279 Q_UNUSED( displayText );
284bool KexiDBForm::autoTabStops()
const
286 return d->autoTabStops;
289void KexiDBForm::setAutoTabStops(
bool set)
291 d->autoTabStops = set;
294TQPtrList<TQWidget>* KexiDBForm::orderedFocusWidgets()
const
296 return &d->orderedFocusWidgets;
299TQPtrList<TQWidget>* KexiDBForm::orderedDataAwareWidgets()
const
301 return &d->orderedDataAwareWidgets;
306 TQWidget *fromWidget = 0;
309 uint numberOfDataAwareWidgets = 0;
313 if (it.current()->widget()->focusPolicy() & TQWidget::TabFocus) {
315 it.current()->widget()->installEventFilter(
this);
317 TQObjectList *children = it.current()->widget()->queryList(
"TQWidget");
318 for (TQObjectListIt childrenIt(*children); childrenIt.current(); ++childrenIt) {
320 kexipluginsdbg <<
"KexiDBForm::updateTabStopsOrder(): also adding '"
321 << childrenIt.current()->className() <<
" " << childrenIt.current()->name()
322 <<
"' child to filtered widgets" << endl;
324 childrenIt.current()->installEventFilter(
this);
329 kexipluginsdbg <<
"KexiDBForm::updateTabStopsOrder() tab order: " << fromWidget->name()
330 <<
" -> " << it.current()->widget()->name() << endl;
333 fromWidget = it.current()->widget();
334 d->orderedFocusWidgets.append( it.current()->widget() );
338 if (dataItem && !dataItem->
dataSource().isEmpty()) {
339 kexipluginsdbg <<
"#" << numberOfDataAwareWidgets <<
": "
340 << dataItem->
dataSource() <<
" (" << it.current()->widget()->name() <<
")" << endl;
345 d->indicesForDataAwareWidgets.replace(
347 numberOfDataAwareWidgets );
348 numberOfDataAwareWidgets++;
350 d->orderedDataAwareWidgets.append( it.current()->widget() );
368void KexiDBForm::updateTabStopsOrder()
370 for (TQPtrListIterator<TQWidget> it( d->orderedFocusWidgets ); it.current();) {
371 if (! (it.current()->focusPolicy() & TQWidget::TabFocus))
372 d->orderedFocusWidgets.remove( it.current() );
380 for (TQPtrListIterator<TQWidget> it(d->orderedDataAwareWidgets); it.current(); ++it) {
382 if (dataItem && !dataItem->
dataSource().isEmpty()) {
390bool KexiDBForm::eventFilter( TQObject * watched, TQEvent * e )
393 if (e->type()==TQEvent::Resize && watched ==
this)
394 kexipluginsdbg <<
"RESIZE" << endl;
395 if (e->type()==TQEvent::KeyPress) {
397 TQKeyEvent *ke =
static_cast<TQKeyEvent*
>(e);
398 const int key = ke->key();
399 bool tab = ke->state() == TQt::NoButton && key == TQt::Key_Tab;
400 bool backtab = ((ke->state() == TQt::NoButton || ke->state() == TQt::ShiftButton) && key == TQt::Key_Backtab)
401 || (ke->state() == TQt::ShiftButton && key == TQt::Key_Tab);
402 TQObject *o = watched;
403 TQWidget* realWidget =
dynamic_cast<TQWidget*
>(o);
405 if (!tab && !backtab) {
407 if (realWidget->inherits(
"TQButton")) {
408 if (ke->state() == TQt::NoButton && (key == TQt::Key_Right || key == TQt::Key_Down))
410 else if (ke->state() == TQt::NoButton && (key == TQt::Key_Left || key == TQt::Key_Up))
415 if (!tab && !backtab) {
418 if (!o || o ==
dynamic_cast<TQObject*
>(d->dataAwareObject))
421 realWidget =
dynamic_cast<TQWidget*
>(o);
422 if (realWidget ==
this)
425 while (dataItemIface) {
426 if (dataItemIface->keyPressed(ke))
436 int curRow = d->dataAwareObject->currentRow();
437 int curCol = d->dataAwareObject->currentColumn();
438 bool moveToFirstField;
439 bool moveToLastField;
440 if (! (ke->state() == TQt::NoButton && (key == TQt::Key_Home
441 || key == TQt::Key_End || key == TQt::Key_Down || key == TQt::Key_Up))
443 && d->dataAwareObject->handleKeyPress(
444 ke, curRow, curCol,
false, &moveToFirstField, &moveToLastField))
446 if (ke->isAccepted())
448 TQWidget* widgetToFocus;
449 if (moveToFirstField) {
450 widgetToFocus = d->orderedFocusWidgets.first();
451 curCol = d->indexOfDataAwareWidget( widgetToFocus );
453 else if (moveToLastField) {
454 widgetToFocus = d->orderedFocusWidgets.last();
455 curCol = d->indexOfDataAwareWidget( widgetToFocus );
458 widgetToFocus = d->orderedDataAwareWidgets.at( curCol );
460 d->dataAwareObject->setCursorPosition( curRow, curCol );
463 widgetToFocus->setFocus();
465 kexipluginswarn <<
"KexiDBForm::eventFilter(): widgetToFocus not found!" << endl;
470 if (key == TQt::Key_Delete && ke->state()==TQt::ControlButton) {
472 d->dataAwareObject->deleteCurrentRow();
477 if (ke->state() == TQt::NoButton && key == TQt::Key_Escape) {
479 if (d->dataAwareObject->cancelEditor())
481 else if (d->dataAwareObject->cancelRowEdit())
488 if (ke->isAccepted() && (ke->state() & TQt::AltButton) && ke->text()>=
"0" && ke->text()<=
"9")
491 if (tab || backtab) {
494 realWidget = realWidget->parentWidget();
502 d->setOrderedFocusWidgetsIteratorTo( realWidget );
503 kexipluginsdbg << realWidget->name() << endl;
506 TQWidget *widgetToUnfocus = realWidget;
507 TQWidget *widgetToFocus = 0;
508 bool wasAtFirstWidget =
false;
511 if (d->orderedFocusWidgets.first() && realWidget == d->orderedFocusWidgets.last()) {
512 if (wasAtFirstWidget)
514 d->orderedFocusWidgetsIterator.toFirst();
515 wasAtFirstWidget =
true;
517 else if (realWidget == d->orderedFocusWidgetsIterator.current()) {
518 ++d->orderedFocusWidgetsIterator;
524 if (d->orderedFocusWidgets.last() && realWidget == d->orderedFocusWidgets.first()) {
525 d->orderedFocusWidgetsIterator.toLast();
527 else if (realWidget == d->orderedFocusWidgetsIterator.current()) {
528 --d->orderedFocusWidgetsIterator;
534 widgetToFocus = d->orderedFocusWidgetsIterator.current();
536 TQObject *pageFor_widgetToFocus = 0;
539 widgetToFocus,
"KFormDesigner::TabWidget", pageFor_widgetToFocus);
540 if (tabWidgetFor_widgetToFocus && tabWidgetFor_widgetToFocus->currentPage()!=pageFor_widgetToFocus) {
541 realWidget = widgetToFocus;
550 if (widgetToFocus->focusProxy())
551 widgetToFocus = widgetToFocus->focusProxy();
552 if (widgetToFocus && d->dataAwareObject->acceptEditor()) {
557 kexipluginsdbg <<
"focusing " << widgetToFocus->name() << endl;
563 kexipluginsdbg <<
"focusing " << d->orderedFocusWidgetsIterator.current()->name() << endl;
570 else if (e->type()==TQEvent::FocusIn) {
571 bool focusDataWidget = preview();
572 if (
static_cast<TQFocusEvent*
>(e)->reason()==TQFocusEvent::Popup) {
573 kdDebug() <<
"->>> focus IN, popup" <<endl;
574 focusDataWidget = !d->popupFocused;
575 d->popupFocused =
false;
582 if (focusDataWidget) {
583 kexipluginsdbg <<
"KexiDBForm: FocusIn: " << watched->className() <<
" " << watched->name() << endl;
584 if (d->dataAwareObject) {
585 TQWidget *dataItem =
dynamic_cast<TQWidget*
>(watched);
588 dataItem = dataItem->parentWidget();
591 kexipluginsdbg <<
"KexiDBForm: FocusIn: FOUND " << dataItem->className() <<
" " << dataItem->name() << endl;
593 const int index = d->indexOfDataAwareWidget(dataItem);
595 kexipluginsdbg <<
"KexiDBForm: moving cursor to column #" << index << endl;
597 if ((
int)index!=d->dataAwareObject->currentColumn()) {
598 d->dataAwareObject->setCursorPosition( d->dataAwareObject->currentRow(), index );
603 dataItem = dataItem->parentWidget();
610 else if (e->type()==TQEvent::FocusOut) {
611 if (
static_cast<TQFocusEvent*
>(e)->reason()==TQFocusEvent::Popup) {
613 d->popupFocused =
true;
616 d->popupFocused =
false;
621 return KexiDBFormBase::eventFilter(watched, e);
636 if (d->dataAwareObject)
637 return d->dataAwareObject->isReadOnly();
644 if (d->dataAwareObject)
645 d->dataAwareObject->setReadOnly( readOnly );
668bool KexiDBForm::preview()
const {
670 ?
dynamic_cast<KexiScrollView*
>(d->dataAwareObject)->preview() :
false;
675 KexiDBFormBase::dragMoveEvent( e );
676 emit handleDragMoveEvent(e);
681 KexiDBFormBase::dropEvent( e );
682 emit handleDropEvent(e);
685void KexiDBForm::setCursor(
const TQCursor & cursor )
691 KexiDBFormBase::setCursor(cursor);
694#include "kexidbform.moc"
The KexiDataAwareObjectInterface is an interface for record-based data object.
virtual bool isReadOnly() const
An interface for declaring widgets to be data-aware.
KexiDataItemInterface * parentInterface() const
KEXIUTILS_EXPORT void unsetFocusWithReason(TQWidget *widget, TQFocusEvent::Reason reason)
Unsets focus for widget widget with reason reason.
KEXIUTILS_EXPORT void setFocusWithReason(TQWidget *widget, TQFocusEvent::Reason reason)
Sets focus for widget widget with reason reason.