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 if (dynamic_cast<KexiFormDataItemInterface*>(childrenIt.current())) {
00282 kexipluginsdbg << "KexiDBForm::updateTabStopsOrder(): also adding '" << childrenIt.current()->className() << " " << childrenIt.current()->name() << "' child to filtered widgets" << endl;
00283 it.current()->widget()->installEventFilter(static_cast<QWidget*>(childrenIt.current()));
00284 }
00285 }
00286 delete children;
00287 if (fromWidget) {
00288 kexipluginsdbg << "KexiDBForm::updateTabStopsOrder() tab order: " << fromWidget->name()
00289 << " -> " << it.current()->widget()->name() << endl;
00290
00291 }
00292 fromWidget = it.current()->widget();
00293 d->orderedFocusWidgets.append( it.current()->widget() );
00294 }
00295
00296 KexiFormDataItemInterface* dataItem = dynamic_cast<KexiFormDataItemInterface*>( it.current()->widget() );
00297 if (dataItem && !dataItem->dataSource().isEmpty()) {
00298 kexipluginsdbg << "#" << numberOfDataAwareWidgets << ": "
00299 << dataItem->dataSource() << " (" << it.current()->widget()->name() << ")" << endl;
00300
00301
00302
00303 d->indicesForDataAwareWidgets.replace(
00304 dataItem,
00305 numberOfDataAwareWidgets );
00306 numberOfDataAwareWidgets++;
00307
00308 d->orderedDataAwareWidgets.append( it.current()->widget() );
00309 }
00310 }
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 }
00325
00326 void KexiDBForm::updateTabStopsOrder()
00327 {
00328 for (QPtrListIterator<QWidget> it( d->orderedFocusWidgets ); it.current();) {
00329 if (! (it.current()->focusPolicy() & QWidget::TabFocus))
00330 d->orderedFocusWidgets.remove( it.current() );
00331 else
00332 ++it;
00333 }
00334 }
00335
00336 bool KexiDBForm::eventFilter( QObject * watched, QEvent * e )
00337 {
00338 if (e->type()==QEvent::Resize && watched == this)
00339 kexipluginsdbg << "RESIZE" << endl;
00340 if (e->type()==QEvent::KeyPress) {
00341 if (preview()) {
00342 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
00343 if (ke->state() == Qt::NoButton && ke->key() == Qt::Key_Escape) {
00344
00345 if (d->dataAwareObject->editor()) {
00346 d->dataAwareObject->cancelEditor();
00347 }
00348 else if (d->dataAwareObject->rowEditing()) {
00349 d->dataAwareObject->cancelRowEdit();
00350 }
00351 ke->accept();
00352 return true;
00353 }
00354
00355
00356
00357 if (ke->isAccepted() && (ke->state() & Qt::AltButton) && ke->text()>="0" && ke->text()<="9")
00358 return true;
00359 const bool tab = ke->state() == Qt::NoButton && ke->key() == Qt::Key_Tab;
00360 const bool backtab = ((ke->state() == Qt::NoButton || ke->state() == Qt::ShiftButton) && ke->key() == Qt::Key_Backtab)
00361 || (ke->state() == Qt::ShiftButton && ke->key() == Qt::Key_Tab);
00362
00363 if (tab || backtab) {
00364 if (d->orderedFocusWidgetsIterator.current() != static_cast<QWidget*>(watched)) {
00365 d->orderedFocusWidgetsIterator.toFirst();
00366 while (d->orderedFocusWidgetsIterator.current() && d->orderedFocusWidgetsIterator.current()!=static_cast<QWidget*>(watched)) {
00367
00368 ++d->orderedFocusWidgetsIterator;
00369 }
00370 }
00371 kexipluginsdbg << watched->name() << endl;
00372 if (tab) {
00373 if (d->orderedFocusWidgets.first() && watched == d->orderedFocusWidgets.last()) {
00374 d->orderedFocusWidgetsIterator.toFirst();
00375 }
00376 else if (watched == d->orderedFocusWidgetsIterator.current()) {
00377
00378
00379
00380
00381 ++d->orderedFocusWidgetsIterator;
00382 }
00383 else
00384 return true;
00385
00386
00387
00388 SET_FOCUS_USING_REASON(d->orderedFocusWidgetsIterator.current(), QFocusEvent::Tab);
00389 kexipluginsdbg << "focusing " << d->orderedFocusWidgetsIterator.current()->name() << endl;
00390 return true;
00391 } else if (backtab) {
00392 if (d->orderedFocusWidgets.last() && watched == d->orderedFocusWidgets.first()) {
00393 d->orderedFocusWidgetsIterator.toLast();
00394 }
00395 else if (watched == d->orderedFocusWidgetsIterator.current()) {
00396 --d->orderedFocusWidgetsIterator;
00397 }
00398 else
00399 return true;
00400
00401 SET_FOCUS_USING_REASON(d->orderedFocusWidgetsIterator.current(), QFocusEvent::Backtab);
00402 kexipluginsdbg << "focusing " << d->orderedFocusWidgetsIterator.current()->name() << endl;
00403 return true;
00404 }
00405 }
00406 }
00407 }
00408 else if (e->type()==QEvent::FocusIn) {
00409 if (preview()) {
00410 if (dynamic_cast<KexiDataItemInterface*>(watched) && d->dataAwareObject) {
00411 uint index = d->indicesForDataAwareWidgets[ dynamic_cast<KexiDataItemInterface*>(watched) ];
00412 kexipluginsdbg << "KexiDBForm: moving cursor to column #" << index << endl;
00413 editedItem = 0;
00414 if ((int)index!=d->dataAwareObject->currentColumn()) {
00415 d->dataAwareObject->setCursorPosition( d->dataAwareObject->currentRow(), index );
00416 }
00417 }
00418 }
00419 }
00420 return KexiDBFormBase::eventFilter(watched, e);
00421 }
00422
00423 bool KexiDBForm::valueIsNull()
00424 {
00425 return true;
00426 }
00427
00428 bool KexiDBForm::valueIsEmpty()
00429 {
00430 return true;
00431 }
00432
00433 bool KexiDBForm::isReadOnly() const
00434 {
00435 if (d->dataAwareObject)
00436 return d->dataAwareObject->isReadOnly();
00438 return false;
00439 }
00440
00441 QWidget* KexiDBForm::widget()
00442 {
00443 return this;
00444 }
00445
00446 bool KexiDBForm::cursorAtStart()
00447 {
00448 return false;
00449 }
00450
00451 bool KexiDBForm::cursorAtEnd()
00452 {
00453 return false;
00454 }
00455
00456 void KexiDBForm::clear()
00457 {
00459 }
00460
00461 bool KexiDBForm::preview() const {
00462 return dynamic_cast<KexiScrollView*>(d->dataAwareObject)
00463 ? dynamic_cast<KexiScrollView*>(d->dataAwareObject)->preview() : false;
00464 }
00465
00466 int KexiDBForm::indexForDataItem( KexiDataItemInterface* item ) const
00467 {
00468 if (!item)
00469 return -1;
00470 QMapConstIterator<KexiDataItemInterface*, uint> it = d->indicesForDataAwareWidgets.find( item );
00471 if (it==d->indicesForDataAwareWidgets.constEnd())
00472 return -1;
00473 return it.data();
00474 }
00475
00476 void KexiDBForm::dragMoveEvent( QDragMoveEvent *e )
00477 {
00478 emit handleDragMoveEvent(e);
00479 }
00480
00481 void KexiDBForm::dropEvent( QDropEvent *e )
00482 {
00483 emit handleDropEvent(e);
00484 }
00485
00486 void KexiDBForm::setCursor( const QCursor & cursor )
00487 {
00488
00490
00491 if (KFormDesigner::FormManager::self()->isInserting())
00492 KexiDBFormBase::setCursor(cursor);
00493 }
00494
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 #include "kexidbform.moc"