00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <qobjectlist.h>
00023 #include <qpainter.h>
00024 #include <qcursor.h>
00025 #include <qapplication.h>
00026 #include <qfocusdata.h>
00027
00028 #include <kdebug.h>
00029
00030 #include "kexidbform.h"
00031 #include "kexiformscrollview.h"
00032
00033 #include <formeditor/objecttree.h>
00034 #include <formeditor/formmanager.h>
00035 #include <widget/tableview/kexidataawareobjectiface.h>
00036 #include <widget/kexiscrollview.h>
00037
00039 class KexiDBForm::Private
00040 {
00041 public:
00042 Private()
00043 : dataAwareObject(0)
00044 , orderedFocusWidgetsIterator(orderedFocusWidgets)
00045 , autoTabStops(false)
00046 {
00047 }
00048 KexiDataAwareObjectInterface* dataAwareObject;
00050 QPtrList<QWidget> orderedFocusWidgets;
00052 QPtrList<QWidget> orderedDataAwareWidgets;
00053 QMap<KexiDataItemInterface*, uint> indicesForDataAwareWidgets;
00054 QPtrListIterator<QWidget> orderedFocusWidgetsIterator;
00055 QPixmap buffer;
00056 QRect prev_rect;
00057 bool autoTabStops : 1;
00058 };
00059
00060
00061
00062 KexiDBForm::KexiDBForm(QWidget *parent, KexiDataAwareObjectInterface* dataAwareObject,
00063 const char *name)
00064 : KexiDBFormBase(parent, name)
00065 , KexiFormDataItemInterface()
00066 , d(new Private())
00067 {
00068 installEventFilter(this);
00069
00070 editedItem = 0;
00071 d->dataAwareObject = dataAwareObject;
00072 m_hasFocusableWidget = false;
00073
00074
00075
00076
00077 kexipluginsdbg << "KexiDBForm::KexiDBForm(): " << endl;
00078 setCursor(QCursor(Qt::ArrowCursor));
00079 setAcceptDrops( true );
00080 }
00081
00082 KexiDBForm::~KexiDBForm()
00083 {
00084 kexipluginsdbg << "KexiDBForm::~KexiDBForm(): close" << endl;
00085 delete d;
00086 }
00087
00088 KexiDataAwareObjectInterface* KexiDBForm::dataAwareObject() const { return d->dataAwareObject; }
00089
00090
00091 static void repaintAll(QWidget *w)
00092 {
00093 QObjectList *list = w->queryList("QWidget");
00094 QObjectListIt it(*list);
00095 for (QObject *obj; (obj=it.current()); ++it ) {
00096 static_cast<QWidget*>(obj)->repaint();
00097 }
00098 delete list;
00099 }
00100
00101 void
00102 KexiDBForm::drawRect(const QRect& r, int type)
00103 {
00104 QValueList<QRect> l;
00105 l.append(r);
00106 drawRects(l, type);
00107 }
00108
00109 void
00110 KexiDBForm::drawRects(const QValueList<QRect> &list, int type)
00111 {
00112 QPainter p;
00113 p.begin(this, true);
00114 bool unclipped = testWFlags( WPaintUnclipped );
00115 setWFlags( WPaintUnclipped );
00116
00117 if (d->prev_rect.isValid()) {
00118
00119 p.drawPixmap( QPoint(d->prev_rect.x()-2, d->prev_rect.y()-2), d->buffer,
00120 QRect(d->prev_rect.x()-2, d->prev_rect.y()-2, d->prev_rect.width()+4, d->prev_rect.height()+4));
00121 }
00122 p.setBrush(QBrush::NoBrush);
00123 if(type == 1)
00124 p.setPen(QPen(white, 1, Qt::DotLine));
00125 else if(type == 2)
00126 p.setPen(QPen(white, 2));
00127 p.setRasterOp(XorROP);
00128
00129 d->prev_rect = QRect();
00130 QValueList<QRect>::ConstIterator endIt = list.constEnd();
00131 for(QValueList<QRect>::ConstIterator it = list.constBegin(); it != endIt; ++it) {
00132 p.drawRect(*it);
00133 if (d->prev_rect.isValid())
00134 d->prev_rect = d->prev_rect.unite(*it);
00135 else
00136 d->prev_rect = *it;
00137 }
00138
00139 if (!unclipped)
00140 clearWFlags( WPaintUnclipped );
00141 p.end();
00142 }
00143
00144 void
00145 KexiDBForm::initBuffer()
00146 {
00147 repaintAll(this);
00148 d->buffer.resize( width(), height() );
00149 d->buffer = QPixmap::grabWindow( winId() );
00150 d->prev_rect = QRect();
00151 }
00152
00153 void
00154 KexiDBForm::clearForm()
00155 {
00156 QPainter p;
00157 p.begin(this, true);
00158 bool unclipped = testWFlags( WPaintUnclipped );
00159 setWFlags( WPaintUnclipped );
00160
00161
00162 p.drawPixmap( QPoint(0,0), d->buffer, QRect(0,0,d->buffer.width(), d->buffer.height()) );
00163
00164 if (!unclipped)
00165 clearWFlags( WPaintUnclipped );
00166 p.end();
00167
00168 repaintAll(this);
00169 }
00170
00171 void
00172 KexiDBForm::highlightWidgets(QWidget *from, QWidget *to)
00173 {
00174 QPoint fromPoint, toPoint;
00175 if(from && from->parentWidget() && (from != this))
00176 fromPoint = from->parentWidget()->mapTo(this, from->pos());
00177 if(to && to->parentWidget() && (to != this))
00178 toPoint = to->parentWidget()->mapTo(this, to->pos());
00179
00180 QPainter p;
00181 p.begin(this, true);
00182 bool unclipped = testWFlags( WPaintUnclipped );
00183 setWFlags( WPaintUnclipped );
00184
00185 if (d->prev_rect.isValid()) {
00186
00187 p.drawPixmap( QPoint(d->prev_rect.x(), d->prev_rect.y()), d->buffer,
00188 QRect(d->prev_rect.x(), d->prev_rect.y(), d->prev_rect.width(), d->prev_rect.height()));
00189 }
00190
00191 p.setPen( QPen(Qt::red, 2) );
00192
00193 if(to)
00194 {
00195 QPixmap pix1 = QPixmap::grabWidget(from);
00196 QPixmap pix2 = QPixmap::grabWidget(to);
00197
00198 if((from != this) && (to != this))
00199 p.drawLine( from->parentWidget()->mapTo(this, from->geometry().center()), to->parentWidget()->mapTo(this, to->geometry().center()) );
00200
00201 p.drawPixmap(fromPoint.x(), fromPoint.y(), pix1);
00202 p.drawPixmap(toPoint.x(), toPoint.y(), pix2);
00203
00204 if(to == this)
00205 p.drawRoundRect(2, 2, width()-4, height()-4, 4, 4);
00206 else
00207 p.drawRoundRect(toPoint.x(), toPoint.y(), to->width(), to->height(), 5, 5);
00208 }
00209
00210 if(from == this)
00211 p.drawRoundRect(2, 2, width()-4, height()-4, 4, 4);
00212 else
00213 p.drawRoundRect(fromPoint.x(), fromPoint.y(), from->width(), from->height(), 5, 5);
00214
00215 if((to == this) || (from == this))
00216 d->prev_rect = QRect(0, 0, d->buffer.width(), d->buffer.height());
00217 else if(to)
00218 {
00219 d->prev_rect.setX( (fromPoint.x() < toPoint.x()) ? (fromPoint.x() - 5) : (toPoint.x() - 5) );
00220 d->prev_rect.setY( (fromPoint.y() < toPoint.y()) ? (fromPoint.y() - 5) : (toPoint.y() - 5) );
00221 d->prev_rect.setRight( (fromPoint.x() < toPoint.x()) ? (toPoint.x() + to->width() + 10) : (fromPoint.x() + from->width() + 10) );
00222 d->prev_rect.setBottom( (fromPoint.y() < toPoint.y()) ? (toPoint.y() + to->height() + 10) : (fromPoint.y() + from->height() + 10) ) ;
00223 }
00224 else
00225 d->prev_rect = QRect(fromPoint.x()- 5, fromPoint.y() -5, from->width() + 10, from->height() + 10);
00226
00227 if (!unclipped)
00228 clearWFlags( WPaintUnclipped );
00229 p.end();
00230 }
00231
00232 QSize
00233 KexiDBForm::sizeHint() const
00234 {
00235
00236 return QSize(400,300);
00237 }
00238
00239 void KexiDBForm::setInvalidState( const QString& displayText )
00240 {
00241 Q_UNUSED( displayText );
00242
00244 }
00245
00246 bool KexiDBForm::autoTabStops() const
00247 {
00248 return d->autoTabStops;
00249 }
00250
00251 void KexiDBForm::setAutoTabStops(bool set)
00252 {
00253 d->autoTabStops = set;
00254 }
00255
00256 QPtrList<QWidget>* KexiDBForm::orderedFocusWidgets() const
00257 {
00258 return &d->orderedFocusWidgets;
00259 }
00260
00261 QPtrList<QWidget>* KexiDBForm::orderedDataAwareWidgets() const
00262 {
00263 return &d->orderedDataAwareWidgets;
00264 }
00265
00266 void KexiDBForm::updateTabStopsOrder(KFormDesigner::Form* form)
00267 {
00268 QWidget *fromWidget = 0;
00269
00270
00271 uint numberOfDataAwareWidgets = 0;
00272
00273
00274 for (KFormDesigner::ObjectTreeListIterator it(form->tabStopsIterator()); it.current(); ++it) {
00275 if (it.current()->widget()->focusPolicy() & QWidget::TabFocus) {
00276
00277 it.current()->widget()->installEventFilter(this);
00278
00279 QObjectList *children = it.current()->widget()->queryList("QWidget");
00280 for (QObjectListIt childrenIt(*children); childrenIt.current(); ++childrenIt) {
00281
00282 kexipluginsdbg << "KexiDBForm::updateTabStopsOrder(): also adding '" << childrenIt.current()->className() << " " << childrenIt.current()->name() << "' child to filtered widgets" << endl;
00283
00284 childrenIt.current()->installEventFilter(this);
00285
00286 }
00287 delete children;
00288 if (fromWidget) {
00289 kexipluginsdbg << "KexiDBForm::updateTabStopsOrder() tab order: " << fromWidget->name()
00290 << " -> " << it.current()->widget()->name() << endl;
00291
00292 }
00293 fromWidget = it.current()->widget();
00294 d->orderedFocusWidgets.append( it.current()->widget() );
00295 }
00296
00297 KexiFormDataItemInterface* dataItem = dynamic_cast<KexiFormDataItemInterface*>( it.current()->widget() );
00298 if (dataItem && !dataItem->dataSource().isEmpty()) {
00299 kexipluginsdbg << "#" << numberOfDataAwareWidgets << ": "
00300 << dataItem->dataSource() << " (" << it.current()->widget()->name() << ")" << endl;
00301
00302
00303
00304
00305 d->indicesForDataAwareWidgets.replace(
00306 dataItem,
00307 numberOfDataAwareWidgets );
00308 numberOfDataAwareWidgets++;
00309
00310 d->orderedDataAwareWidgets.append( it.current()->widget() );
00311 }
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 }
00327
00328 void KexiDBForm::updateTabStopsOrder()
00329 {
00330 for (QPtrListIterator<QWidget> it( d->orderedFocusWidgets ); it.current();) {
00331 if (! (it.current()->focusPolicy() & QWidget::TabFocus))
00332 d->orderedFocusWidgets.remove( it.current() );
00333 else
00334 ++it;
00335 }
00336 }
00337
00338 bool KexiDBForm::eventFilter( QObject * watched, QEvent * e )
00339 {
00340
00341 if (e->type()==QEvent::Resize && watched == this)
00342 kexipluginsdbg << "RESIZE" << endl;
00343 if (e->type()==QEvent::KeyPress) {
00344 if (preview()) {
00345 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
00346
00347 QObject *o = watched;
00348 QWidget* realWidget = 0;
00349 while (true) {
00350 if (!o || o == dynamic_cast<QObject*>(d->dataAwareObject))
00351 break;
00352 if (dynamic_cast<KexiDataItemInterface*>(o)) {
00353 realWidget = dynamic_cast<QWidget*>(o);
00354
00355
00356 break;
00357 }
00358 o = o->parent();
00359 }
00360
00361 if (ke->state() == Qt::NoButton && ke->key() == Qt::Key_Escape) {
00362
00363 if (d->dataAwareObject->editor()) {
00364 d->dataAwareObject->cancelEditor();
00365 }
00366 else if (d->dataAwareObject->rowEditing()) {
00367 d->dataAwareObject->cancelRowEdit();
00368 }
00369 ke->accept();
00370 return true;
00371 }
00372
00373
00374
00375 if (ke->isAccepted() && (ke->state() & Qt::AltButton) && ke->text()>="0" && ke->text()<="9")
00376 return true;
00377 const bool tab = ke->state() == Qt::NoButton && ke->key() == Qt::Key_Tab;
00378 const bool backtab = ((ke->state() == Qt::NoButton || ke->state() == Qt::ShiftButton) && ke->key() == Qt::Key_Backtab)
00379 || (ke->state() == Qt::ShiftButton && ke->key() == Qt::Key_Tab);
00380
00381 if (tab || backtab) {
00382
00383
00384 while (dynamic_cast<KexiDataItemInterface*>(realWidget) && dynamic_cast<KexiDataItemInterface*>(realWidget)->parentInterface())
00385 realWidget = dynamic_cast<QWidget*>( dynamic_cast<KexiDataItemInterface*>(realWidget)->parentInterface() );
00386
00387 if (d->orderedFocusWidgetsIterator.current() != realWidget) {
00388 d->orderedFocusWidgetsIterator.toFirst();
00389 while (d->orderedFocusWidgetsIterator.current() && d->orderedFocusWidgetsIterator.current()!=realWidget) {
00390
00391 ++d->orderedFocusWidgetsIterator;
00392 }
00393 }
00394 kexipluginsdbg << realWidget->name() << endl;
00395 if (tab) {
00396 if (d->orderedFocusWidgets.first() && realWidget == d->orderedFocusWidgets.last()) {
00397 d->orderedFocusWidgetsIterator.toFirst();
00398 }
00399 else if (realWidget == d->orderedFocusWidgetsIterator.current()) {
00400
00401
00402
00403
00404 ++d->orderedFocusWidgetsIterator;
00405 }
00406 else
00407 return true;
00408
00409
00410
00411 QWidget *widgetToFocus = d->orderedFocusWidgetsIterator.current();
00412 widgetToFocus = widgetToFocus->focusProxy();
00413 if (d->dataAwareObject->acceptEditor()) {
00414
00415 SET_FOCUS_USING_REASON(d->orderedFocusWidgetsIterator.current(), QFocusEvent::Tab);
00416 kexipluginsdbg << "focusing " << d->orderedFocusWidgetsIterator.current()->name() << endl;
00417 }
00418 return true;
00419 } else if (backtab) {
00420 if (d->orderedFocusWidgets.last() && realWidget == d->orderedFocusWidgets.first()) {
00421 d->orderedFocusWidgetsIterator.toLast();
00422 }
00423 else if (realWidget == d->orderedFocusWidgetsIterator.current()) {
00424 --d->orderedFocusWidgetsIterator;
00425 }
00426 else
00427 return true;
00428 if (d->dataAwareObject->acceptEditor()) {
00429
00430
00431 SET_FOCUS_USING_REASON(d->orderedFocusWidgetsIterator.current(), QFocusEvent::Backtab);
00432 kexipluginsdbg << "focusing " << d->orderedFocusWidgetsIterator.current()->name() << endl;
00433 }
00434 return true;
00435 }
00436 }
00437 }
00438 }
00439 else if (e->type()==QEvent::FocusIn) {
00440 if (preview()) {
00441 kexipluginsdbg << "KexiDBForm: FocusIn: " << watched->className() << " " << watched->name() << endl;
00442 if (d->dataAwareObject) {
00443 QWidget *dataItem = dynamic_cast<QWidget*>(watched);
00444 while (dataItem) {
00445 while (dataItem && !dynamic_cast<KexiDataItemInterface*>(dataItem))
00446 dataItem = dataItem->parentWidget();
00447 if (!dataItem)
00448 break;
00449 kexipluginsdbg << "KexiDBForm: FocusIn: FOUND " << dataItem->className() << " " << dataItem->name() << endl;
00450 QMapConstIterator<KexiDataItemInterface*, uint> indicesForDataAwareWidgetsIt(
00451 d->indicesForDataAwareWidgets.find(dynamic_cast<KexiDataItemInterface*>(dataItem)));
00452 if (indicesForDataAwareWidgetsIt!=d->indicesForDataAwareWidgets.constEnd()) {
00453 const uint index = indicesForDataAwareWidgetsIt.data();
00454 kexipluginsdbg << "KexiDBForm: moving cursor to column #" << index << endl;
00455 editedItem = 0;
00456 if ((int)index!=d->dataAwareObject->currentColumn()) {
00457 d->dataAwareObject->setCursorPosition( d->dataAwareObject->currentRow(), index );
00458 }
00459 break;
00460 }
00461 else
00462 dataItem = dataItem->parentWidget();
00463 }
00464 }
00465 }
00466 }
00467 return KexiDBFormBase::eventFilter(watched, e);
00468 }
00469
00470 bool KexiDBForm::valueIsNull()
00471 {
00472 return true;
00473 }
00474
00475 bool KexiDBForm::valueIsEmpty()
00476 {
00477 return true;
00478 }
00479
00480 bool KexiDBForm::isReadOnly() const
00481 {
00482 if (d->dataAwareObject)
00483 return d->dataAwareObject->isReadOnly();
00485 return false;
00486 }
00487
00488 QWidget* KexiDBForm::widget()
00489 {
00490 return this;
00491 }
00492
00493 bool KexiDBForm::cursorAtStart()
00494 {
00495 return false;
00496 }
00497
00498 bool KexiDBForm::cursorAtEnd()
00499 {
00500 return false;
00501 }
00502
00503 void KexiDBForm::clear()
00504 {
00506 }
00507
00508 bool KexiDBForm::preview() const {
00509 return dynamic_cast<KexiScrollView*>(d->dataAwareObject)
00510 ? dynamic_cast<KexiScrollView*>(d->dataAwareObject)->preview() : false;
00511 }
00512
00513 int KexiDBForm::indexForDataItem( KexiDataItemInterface* item ) const
00514 {
00515 if (!item)
00516 return -1;
00517 QMapConstIterator<KexiDataItemInterface*, uint> it = d->indicesForDataAwareWidgets.find( item );
00518 if (it==d->indicesForDataAwareWidgets.constEnd())
00519 return -1;
00520 return it.data();
00521 }
00522
00523 void KexiDBForm::dragMoveEvent( QDragMoveEvent *e )
00524 {
00525 emit handleDragMoveEvent(e);
00526 }
00527
00528 void KexiDBForm::dropEvent( QDropEvent *e )
00529 {
00530 emit handleDropEvent(e);
00531 }
00532
00533 void KexiDBForm::setCursor( const QCursor & cursor )
00534 {
00535
00537
00538 if (KFormDesigner::FormManager::self()->isInserting())
00539 KexiDBFormBase::setCursor(cursor);
00540 }
00541
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 #include "kexidbform.moc"