kexi

kexidbform.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Lucijan Busch <lucijan@kde.org>
00003    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00004    Copyright (C) 2005-2007 Jaroslaw Staniek <js@iidea.pl>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
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 "kexiformpart.h"
00032 #include "kexiformscrollview.h"
00033 
00034 #include <formeditor/objecttree.h>
00035 #include <formeditor/formmanager.h> 
00036 #include <formeditor/widgetlibrary.h>
00037 #include <widget/tableview/kexidataawareobjectiface.h>
00038 #include <widget/kexiscrollview.h>
00039 #include <kexiutils/utils.h>
00040 
00042 class KexiDBForm::Private
00043 {
00044     public:
00045         Private()
00046          : dataAwareObject(0)
00047          , orderedFocusWidgetsIterator(orderedFocusWidgets)
00048          , autoTabStops(false)
00049          , popupFocused(false)
00050         {
00051         }
00052 
00053         ~Private()
00054         {
00055         }
00056 
00058         int indexOfDataAwareWidget(QWidget *widget) const
00059         {
00060             if (!dynamic_cast<KexiDataItemInterface*>(widget))
00061                 return -1;
00062             return indexOfDataItem( dynamic_cast<KexiDataItemInterface*>(widget) );
00063         }
00064 
00066         int indexOfDataItem( KexiDataItemInterface* item ) const
00067         {
00068             QMapConstIterator<KexiDataItemInterface*, uint> indicesForDataAwareWidgetsIt(
00069                 indicesForDataAwareWidgets.find(item));
00070             if (indicesForDataAwareWidgetsIt == indicesForDataAwareWidgets.constEnd())
00071                 return -1;
00072             kexipluginsdbg << "KexiDBForm: column # for item: "
00073                 << indicesForDataAwareWidgetsIt.data() << endl;
00074             return indicesForDataAwareWidgetsIt.data();
00075         }
00076 
00078         void setOrderedFocusWidgetsIteratorTo( QWidget *widget )
00079         {
00080             if (orderedFocusWidgetsIterator.current() == widget)
00081                 return;
00082             orderedFocusWidgetsIterator.toFirst();
00083             while (orderedFocusWidgetsIterator.current() && orderedFocusWidgetsIterator.current()!=widget)
00084                 ++orderedFocusWidgetsIterator;
00085         }
00086 
00087         KexiDataAwareObjectInterface* dataAwareObject;
00089         QPtrList<QWidget> orderedFocusWidgets; 
00091         QPtrList<QWidget> orderedDataAwareWidgets;
00092         QMap<KexiDataItemInterface*, uint> indicesForDataAwareWidgets; 
00093         QPtrListIterator<QWidget> orderedFocusWidgetsIterator;
00094         QPixmap buffer; 
00095         QRect prev_rect; 
00096 //      QGuardedPtr<QWidget> widgetFocusedBeforePopup;
00097         bool autoTabStops : 1;
00098         bool popupFocused : 1; 
00099 };
00100 
00101 //========================
00102 
00103 KexiDBForm::KexiDBForm(QWidget *parent, KexiDataAwareObjectInterface* dataAwareObject, 
00104     const char *name/*, KexiDB::Connection *conn*/)
00105  : KexiDBFormBase(parent, name)
00106  , KexiFormDataItemInterface()
00107  , d(new Private())
00108 {
00109     installEventFilter(this);
00110 //test  setDisplayMode( KexiGradientWidget::SimpleGradient );
00111     editedItem = 0;
00112     d->dataAwareObject = dataAwareObject;
00113     m_hasFocusableWidget = false;
00114 
00115     kexipluginsdbg << "KexiDBForm::KexiDBForm(): " << endl;
00116     setCursor(QCursor(Qt::ArrowCursor)); //to avoid keeping Size cursor when moving from form's boundaries
00117     setAcceptDrops( true );
00118 }
00119 
00120 KexiDBForm::~KexiDBForm()
00121 {
00122     kexipluginsdbg << "KexiDBForm::~KexiDBForm(): close" << endl;
00123     delete d;
00124 }
00125 
00126 KexiDataAwareObjectInterface* KexiDBForm::dataAwareObject() const { return d->dataAwareObject; }
00127 
00128 //repaint all children widgets
00129 static void repaintAll(QWidget *w)
00130 {
00131     QObjectList *list = w->queryList("QWidget");
00132     QObjectListIt it(*list);
00133     for (QObject *obj; (obj=it.current()); ++it ) {
00134         static_cast<QWidget*>(obj)->repaint();
00135     }
00136     delete list;
00137 }
00138 
00139 void
00140 KexiDBForm::drawRect(const QRect& r, int type)
00141 {
00142     QValueList<QRect> l;
00143     l.append(r);
00144     drawRects(l, type);
00145 }
00146 
00147 void
00148 KexiDBForm::drawRects(const QValueList<QRect> &list, int type)
00149 {
00150     QPainter p;
00151     p.begin(this, true);
00152     bool unclipped = testWFlags( WPaintUnclipped );
00153     setWFlags( WPaintUnclipped );
00154 
00155     if (d->prev_rect.isValid()) {
00156         //redraw prev. selection's rectangle
00157         p.drawPixmap( QPoint(d->prev_rect.x()-2, d->prev_rect.y()-2), d->buffer, 
00158             QRect(d->prev_rect.x()-2, d->prev_rect.y()-2, d->prev_rect.width()+4, d->prev_rect.height()+4));
00159     }
00160     p.setBrush(QBrush::NoBrush);
00161     if(type == 1) // selection rect
00162         p.setPen(QPen(white, 1, Qt::DotLine));
00163     else if(type == 2) // insert rect
00164         p.setPen(QPen(white, 2));
00165     p.setRasterOp(XorROP);
00166 
00167     d->prev_rect = QRect();
00168     QValueList<QRect>::ConstIterator endIt = list.constEnd();
00169     for(QValueList<QRect>::ConstIterator it = list.constBegin(); it != endIt; ++it) {
00170         p.drawRect(*it);
00171         if (d->prev_rect.isValid())
00172             d->prev_rect = d->prev_rect.unite(*it);
00173         else
00174             d->prev_rect = *it;
00175     }
00176 
00177     if (!unclipped)
00178         clearWFlags( WPaintUnclipped );
00179     p.end();
00180 }
00181 
00182 void
00183 KexiDBForm::initBuffer()
00184 {
00185     repaintAll(this);
00186     d->buffer.resize( width(), height() );
00187     d->buffer = QPixmap::grabWindow( winId() );
00188     d->prev_rect = QRect();
00189 }
00190 
00191 void
00192 KexiDBForm::clearForm()
00193 {
00194     QPainter p;
00195     p.begin(this, true);
00196     bool unclipped = testWFlags( WPaintUnclipped );
00197     setWFlags( WPaintUnclipped );
00198 
00199     //redraw entire form surface
00200     p.drawPixmap( QPoint(0,0), d->buffer, QRect(0,0,d->buffer.width(), d->buffer.height()) );
00201 
00202     if (!unclipped)
00203         clearWFlags( WPaintUnclipped );
00204     p.end();
00205 
00206     repaintAll(this);
00207 }
00208 
00209 void
00210 KexiDBForm::highlightWidgets(QWidget *from, QWidget *to)//, const QPoint &point)
00211 {
00212     QPoint fromPoint, toPoint;
00213     if(from && from->parentWidget() && (from != this))
00214         fromPoint = from->parentWidget()->mapTo(this, from->pos());
00215     if(to && to->parentWidget() && (to != this))
00216         toPoint = to->parentWidget()->mapTo(this, to->pos());
00217 
00218     QPainter p;
00219     p.begin(this, true);
00220     bool unclipped = testWFlags( WPaintUnclipped );
00221     setWFlags( WPaintUnclipped );
00222 
00223     if (d->prev_rect.isValid()) {
00224         //redraw prev. selection's rectangle
00225         p.drawPixmap( QPoint(d->prev_rect.x(), d->prev_rect.y()), d->buffer, 
00226             QRect(d->prev_rect.x(), d->prev_rect.y(), d->prev_rect.width(), d->prev_rect.height()));
00227     }
00228 
00229     p.setPen( QPen(Qt::red, 2) );
00230 
00231     if(to)
00232     {
00233         QPixmap pix1 = QPixmap::grabWidget(from);
00234         QPixmap pix2 = QPixmap::grabWidget(to);
00235 
00236         if((from != this) && (to != this))
00237             p.drawLine( from->parentWidget()->mapTo(this, from->geometry().center()), to->parentWidget()->mapTo(this, to->geometry().center()) );
00238 
00239         p.drawPixmap(fromPoint.x(), fromPoint.y(), pix1);
00240         p.drawPixmap(toPoint.x(), toPoint.y(), pix2);
00241 
00242         if(to == this)
00243             p.drawRoundRect(2, 2, width()-4, height()-4, 4, 4);
00244         else
00245             p.drawRoundRect(toPoint.x(), toPoint.y(), to->width(), to->height(), 5, 5);
00246     }
00247 
00248     if(from == this)
00249         p.drawRoundRect(2, 2, width()-4, height()-4, 4, 4);
00250     else
00251         p.drawRoundRect(fromPoint.x(),  fromPoint.y(), from->width(), from->height(), 5, 5);
00252 
00253     if((to == this) || (from == this))
00254         d->prev_rect = QRect(0, 0, d->buffer.width(), d->buffer.height());
00255     else if(to)
00256     {
00257         d->prev_rect.setX( (fromPoint.x() < toPoint.x()) ? (fromPoint.x() - 5) : (toPoint.x() - 5) );
00258         d->prev_rect.setY( (fromPoint.y() < toPoint.y()) ? (fromPoint.y() - 5) : (toPoint.y() - 5) );
00259         d->prev_rect.setRight( (fromPoint.x() < toPoint.x()) ? (toPoint.x() + to->width() + 10) : (fromPoint.x() + from->width() + 10) );
00260         d->prev_rect.setBottom( (fromPoint.y() < toPoint.y()) ? (toPoint.y() + to->height() + 10) : (fromPoint.y() + from->height() + 10) ) ;
00261     }
00262     else
00263         d->prev_rect = QRect(fromPoint.x()- 5,  fromPoint.y() -5, from->width() + 10, from->height() + 10);
00264 
00265     if (!unclipped)
00266         clearWFlags( WPaintUnclipped );
00267     p.end();
00268 }
00269 
00270 QSize
00271 KexiDBForm::sizeHint() const
00272 {
00273     //todo: find better size (user configured?)
00274     return QSize(400,300);
00275 }
00276 
00277 void KexiDBForm::setInvalidState( const QString& displayText )
00278 {
00279     Q_UNUSED( displayText );
00280 
00282 }
00283 
00284 bool KexiDBForm::autoTabStops() const
00285 {
00286     return d->autoTabStops;
00287 }
00288 
00289 void KexiDBForm::setAutoTabStops(bool set)
00290 {
00291     d->autoTabStops = set;
00292 }
00293 
00294 QPtrList<QWidget>* KexiDBForm::orderedFocusWidgets() const
00295 {
00296     return &d->orderedFocusWidgets;
00297 }
00298 
00299 QPtrList<QWidget>* KexiDBForm::orderedDataAwareWidgets() const
00300 {
00301     return &d->orderedDataAwareWidgets;
00302 }
00303 
00304 void KexiDBForm::updateTabStopsOrder(KFormDesigner::Form* form)
00305 {
00306     QWidget *fromWidget = 0;
00307     //QWidget *topLevelWidget = form->widget()->topLevelWidget();
00308 //js    form->updateTabStopsOrder(); //certain widgets can have now updated focusPolicy properties, fix this
00309     uint numberOfDataAwareWidgets = 0;
00310 //  if (d->orderedFocusWidgets.isEmpty()) {
00311         //generate a new list
00312         for (KFormDesigner::ObjectTreeListIterator it(form->tabStopsIterator()); it.current(); ++it) {
00313             if (it.current()->widget()->focusPolicy() & QWidget::TabFocus) {
00314                 //this widget has tab focus:
00315                 it.current()->widget()->installEventFilter(this);
00316                 //also filter events for data-aware children of this widget (i.e. KexiDBAutoField's editors)
00317                 QObjectList *children = it.current()->widget()->queryList("QWidget");
00318                 for (QObjectListIt childrenIt(*children); childrenIt.current(); ++childrenIt) {
00319     //              if (dynamic_cast<KexiFormDataItemInterface*>(childrenIt.current())) {
00320                         kexipluginsdbg << "KexiDBForm::updateTabStopsOrder(): also adding '" 
00321                             << childrenIt.current()->className() << " " << childrenIt.current()->name()  
00322                             << "' child to filtered widgets" << endl;
00323                         //it.current()->widget()->installEventFilter(static_cast<QWidget*>(childrenIt.current()));
00324                         childrenIt.current()->installEventFilter(this);
00325         //          }
00326                 }
00327                 delete children;
00328                 if (fromWidget) {
00329                     kexipluginsdbg << "KexiDBForm::updateTabStopsOrder() tab order: " << fromWidget->name() 
00330                         << " -> " << it.current()->widget()->name() << endl;
00331     //              setTabOrder( fromWidget, it.current()->widget() );
00332                 }
00333                 fromWidget = it.current()->widget();
00334                 d->orderedFocusWidgets.append( it.current()->widget() );
00335             }
00336 
00337             KexiFormDataItemInterface* dataItem = dynamic_cast<KexiFormDataItemInterface*>( it.current()->widget() );
00338             if (dataItem && !dataItem->dataSource().isEmpty()) {
00339                 kexipluginsdbg << "#" << numberOfDataAwareWidgets << ": " 
00340                     << dataItem->dataSource() << " (" << it.current()->widget()->name() << ")" << endl;
00341 
00342 //  /*! @todo d->indicesForDataAwareWidgets SHOULDNT BE UPDATED HERE BECAUSE
00343 //  THERE CAN BE ALSO NON-TABSTOP DATA WIDGETS!
00344 //  */
00345                 d->indicesForDataAwareWidgets.replace( 
00346                     dataItem, 
00347                     numberOfDataAwareWidgets );
00348                 numberOfDataAwareWidgets++;
00349 
00350                 d->orderedDataAwareWidgets.append( it.current()->widget() );
00351             }
00352         }//for
00353 //  }
00354 /*  else {
00355         //restore ordering
00356         for (QPtrListIterator<QWidget> it(d->orderedFocusWidgets); it.current(); ++it) {
00357             if (fromWidget) {
00358                 kdDebug() << "KexiDBForm::updateTabStopsOrder() tab order: " << fromWidget->name() 
00359                     << " -> " << it.current()->name() << endl;
00360                 setTabOrder( fromWidget, it.current() );
00361             }
00362             fromWidget = it.current();
00363         }
00364 //      SET_FOCUS_USING_REASON(focusWidget(), QFocusEvent::Tab);
00365     }*/
00366 }
00367 
00368 void KexiDBForm::updateTabStopsOrder()
00369 {
00370     for (QPtrListIterator<QWidget> it( d->orderedFocusWidgets ); it.current();) {
00371         if (! (it.current()->focusPolicy() & QWidget::TabFocus))
00372             d->orderedFocusWidgets.remove( it.current() );
00373         else
00374             ++it;
00375     }
00376 }
00377 
00378 void KexiDBForm::updateReadOnlyFlags()
00379 {
00380     for (QPtrListIterator<QWidget> it(d->orderedDataAwareWidgets); it.current(); ++it) {
00381         KexiFormDataItemInterface* dataItem = dynamic_cast<KexiFormDataItemInterface*>( it.current() );
00382         if (dataItem && !dataItem->dataSource().isEmpty()) {
00383             if (dataAwareObject()->isReadOnly()) {
00384                 dataItem->setReadOnly( true );
00385             }
00386         }
00387     }
00388 }
00389 
00390 bool KexiDBForm::eventFilter( QObject * watched, QEvent * e )
00391 {
00392     //kexipluginsdbg << e->type() << endl;
00393     if (e->type()==QEvent::Resize && watched == this)
00394         kexipluginsdbg << "RESIZE" << endl;
00395     if (e->type()==QEvent::KeyPress) {
00396         if (preview()) {
00397             QKeyEvent *ke = static_cast<QKeyEvent*>(e);
00398             const int key = ke->key();
00399             bool tab = ke->state() == Qt::NoButton && key == Qt::Key_Tab;
00400             bool backtab = ((ke->state() == Qt::NoButton || ke->state() == Qt::ShiftButton) && key == Qt::Key_Backtab)
00401                 || (ke->state() == Qt::ShiftButton && key == Qt::Key_Tab);
00402             QObject *o = watched; //focusWidget();
00403             QWidget* realWidget = dynamic_cast<QWidget*>(o); //will beused below (for tab/backtab handling)
00404 
00405             if (!tab && !backtab) {
00406                 //for buttons, left/up and right/down keys act like tab/backtab (see qbutton.cpp)
00407                 if (realWidget->inherits("QButton")) {
00408                     if (ke->state() == Qt::NoButton && (key == Qt::Key_Right || key == Qt::Key_Down))
00409                         tab = true;
00410                     else if (ke->state() == Qt::NoButton && (key == Qt::Key_Left || key == Qt::Key_Up))
00411                         backtab = true;
00412                 }
00413             }
00414 
00415             if (!tab && !backtab) {
00416                 // allow the editor widget to grab the key press event
00417                 while (true) {
00418                     if (!o || o == dynamic_cast<QObject*>(d->dataAwareObject))
00419                         break;
00420                     if (dynamic_cast<KexiFormDataItemInterface*>(o)) {
00421                         realWidget = dynamic_cast<QWidget*>(o); //will be used below
00422                         if (realWidget == this) //we have encountered 'this' form surface, give up
00423                             return false;
00424                         KexiFormDataItemInterface* dataItemIface = dynamic_cast<KexiFormDataItemInterface*>(o);
00425                         while (dataItemIface) {
00426                             if (dataItemIface->keyPressed(ke))
00427                                 return false;
00428                             dataItemIface = dynamic_cast<KexiFormDataItemInterface*>(dataItemIface->parentInterface()); //try in parent, e.g. in combobox
00429                         }
00430                         break;
00431                     }
00432                     o = o->parent();
00433                 }
00434                 // try to handle global shortcuts at the KexiDataAwareObjectInterface 
00435                 // level (e.g. for "next record" action)
00436                 int curRow = d->dataAwareObject->currentRow();
00437                 int curCol = d->dataAwareObject->currentColumn();
00438                 bool moveToFirstField; //if true, we'll move focus to the first field (in tab order)
00439                 bool moveToLastField; //if true, we'll move focus to the first field (in tab order)
00440                 if (! (ke->state() == Qt::NoButton && (key == Qt::Key_Home 
00441                          || key == Qt::Key_End || key == Qt::Key_Down || key == Qt::Key_Up)) 
00442                                 /* ^^ home/end/down/up are already handled by widgets */
00443                     && d->dataAwareObject->handleKeyPress(
00444                         ke, curRow, curCol, false, &moveToFirstField, &moveToLastField))
00445                 {
00446                     if (ke->isAccepted())
00447                         return true;
00448                     QWidget* widgetToFocus;
00449                     if (moveToFirstField) {
00450                         widgetToFocus = d->orderedFocusWidgets.first(); //?
00451                         curCol = d->indexOfDataAwareWidget( widgetToFocus );
00452                     }
00453                     else if (moveToLastField) {
00454                         widgetToFocus = d->orderedFocusWidgets.last(); //?
00455                         curCol = d->indexOfDataAwareWidget( widgetToFocus );
00456                     }
00457                     else
00458                         widgetToFocus = d->orderedDataAwareWidgets.at( curCol ); //?
00459 
00460                     d->dataAwareObject->setCursorPosition( curRow, curCol );
00461 
00462                     if (widgetToFocus)
00463                         widgetToFocus->setFocus();
00464                     else
00465                         kexipluginswarn << "KexiDBForm::eventFilter(): widgetToFocus not found!" << endl;
00466 
00467                     ke->accept();
00468                     return true;
00469                 }
00470                 if (key == Qt::Key_Delete && ke->state()==Qt::ControlButton) {
00472                     d->dataAwareObject->deleteCurrentRow();
00473                     return true;
00474                 }
00475             }
00476             // handle Esc key
00477             if (ke->state() == Qt::NoButton && key == Qt::Key_Escape) {
00478                 //cancel field editing/row editing if possible
00479                 if (d->dataAwareObject->cancelEditor())
00480                     return true;
00481                 else if (d->dataAwareObject->cancelRowEdit())
00482                     return true;
00483                 return false; // canceling not needed - pass the event to the active widget
00484             }
00485             // jstaniek: Fix for Qt bug (handling e.g. Alt+2, Ctrl+2 keys on every platform)
00486             //           It's important because we're using alt+2 short cut by default
00487             //           Damn! I've reported this to Trolltech in November 2004 - still not fixed.
00488             if (ke->isAccepted() && (ke->state() & Qt::AltButton) && ke->text()>="0" && ke->text()<="9")
00489                 return true;
00490 
00491             if (tab || backtab) {
00492                 //the watched widget can be a subwidget of a real widget, e.g. a drop down button of image box: find it
00493                 while (!KexiFormPart::library()->widgetInfoForClassName(realWidget->className()))
00494                     realWidget = realWidget->parentWidget();
00495                 if (!realWidget)
00496                     return true; //ignore
00497                 //the watched widget can be a subwidget of a real widget, e.g. autofield: find it
00498                 //QWidget* realWidget = static_cast<QWidget*>(watched);
00499                 while (dynamic_cast<KexiDataItemInterface*>(realWidget) && dynamic_cast<KexiDataItemInterface*>(realWidget)->parentInterface())
00500                     realWidget = dynamic_cast<QWidget*>( dynamic_cast<KexiDataItemInterface*>(realWidget)->parentInterface() );
00501 
00502                 d->setOrderedFocusWidgetsIteratorTo( realWidget );
00503                 kexipluginsdbg << realWidget->name() << endl;
00504 
00505                 // find next/prev widget to focus
00506                 QWidget *widgetToUnfocus = realWidget;
00507                 QWidget *widgetToFocus = 0;
00508                 bool wasAtFirstWidget = false; //used to protect against infinite loop
00509                 while (true) {
00510                     if (tab) {
00511                         if (d->orderedFocusWidgets.first() && realWidget == d->orderedFocusWidgets.last()) {
00512                             if (wasAtFirstWidget)
00513                                 break;
00514                             d->orderedFocusWidgetsIterator.toFirst();
00515                             wasAtFirstWidget = true;
00516                         }
00517                         else if (realWidget == d->orderedFocusWidgetsIterator.current()) {
00518                             ++d->orderedFocusWidgetsIterator; //next
00519                         }
00520                         else
00521                             return true; //ignore
00522                     }
00523                     else {//backtab
00524                         if (d->orderedFocusWidgets.last() && realWidget == d->orderedFocusWidgets.first()) {
00525                             d->orderedFocusWidgetsIterator.toLast();
00526                         }
00527                         else if (realWidget == d->orderedFocusWidgetsIterator.current()) {
00528                             --d->orderedFocusWidgetsIterator; //prev
00529                         }
00530                         else
00531                             return true; //ignore
00532                     }
00533 
00534                     widgetToFocus = d->orderedFocusWidgetsIterator.current();
00535 
00536                     QObject *pageFor_widgetToFocus = 0;
00537                     KFormDesigner::TabWidget *tabWidgetFor_widgetToFocus 
00538                         = KFormDesigner::findParent<KFormDesigner::TabWidget>(
00539                             widgetToFocus, "KFormDesigner::TabWidget", pageFor_widgetToFocus);
00540                     if (tabWidgetFor_widgetToFocus && tabWidgetFor_widgetToFocus->currentPage()!=pageFor_widgetToFocus) {
00541                         realWidget = widgetToFocus;
00542                         continue; //the new widget to focus is placed on invisible tab page: move to next widget
00543                     }
00544                     break;
00545                 }//while
00546             
00547                 //set focus, but don't use just setFocus() because certain widgets
00548                 //behaves differently (e.g. QLineEdit calls selectAll()) when 
00549                 //focus event's reason is QFocusEvent::Tab
00550                 if (widgetToFocus->focusProxy())
00551                     widgetToFocus = widgetToFocus->focusProxy();
00552                 if (widgetToFocus && d->dataAwareObject->acceptEditor()) {
00553                     if (tab) {
00554                         //try to accept this will validate the current input (if any)
00555                         KexiUtils::unsetFocusWithReason(widgetToUnfocus, QFocusEvent::Tab);
00556                         KexiUtils::setFocusWithReason(widgetToFocus, QFocusEvent::Tab);
00557                         kexipluginsdbg << "focusing " << widgetToFocus->name() << endl;
00558                     }
00559                     else {//backtab
00560                         KexiUtils::unsetFocusWithReason(widgetToUnfocus, QFocusEvent::Backtab);
00561                         //set focus, see above note
00562                         KexiUtils::setFocusWithReason(d->orderedFocusWidgetsIterator.current(), QFocusEvent::Backtab);
00563                         kexipluginsdbg << "focusing " << d->orderedFocusWidgetsIterator.current()->name() << endl;
00564                     }
00565                 }
00566                 return true;
00567             }
00568         }
00569     }
00570     else if (e->type()==QEvent::FocusIn) {
00571         bool focusDataWidget = preview();
00572         if (static_cast<QFocusEvent*>(e)->reason()==QFocusEvent::Popup) {
00573             kdDebug() << "->>> focus IN, popup" <<endl;
00574             focusDataWidget = !d->popupFocused;
00575             d->popupFocused = false;
00576 //          if (d->widgetFocusedBeforePopup) {
00577 //              watched = d->widgetFocusedBeforePopup;
00578 //              d->widgetFocusedBeforePopup = 0;
00579 //          }
00580         }
00581 
00582         if (focusDataWidget) {
00583             kexipluginsdbg << "KexiDBForm: FocusIn: " << watched->className() << " " << watched->name() << endl;
00584             if (d->dataAwareObject) {
00585                 QWidget *dataItem = dynamic_cast<QWidget*>(watched);
00586                 while (dataItem) {
00587                     while (dataItem && !dynamic_cast<KexiDataItemInterface*>(dataItem))
00588                         dataItem = dataItem->parentWidget();
00589                     if (!dataItem)
00590                         break;
00591                     kexipluginsdbg << "KexiDBForm: FocusIn: FOUND " << dataItem->className() << " " << dataItem->name() << endl;
00592 
00593                     const int index = d->indexOfDataAwareWidget(dataItem);
00594                     if (index>=0) {
00595                         kexipluginsdbg << "KexiDBForm: moving cursor to column #" << index << endl;
00596                         editedItem = 0;
00597                         if ((int)index!=d->dataAwareObject->currentColumn()) {
00598                             d->dataAwareObject->setCursorPosition( d->dataAwareObject->currentRow(), index /*column*/ );
00599                         }
00600                         break;
00601                     }
00602                     else
00603                         dataItem = dataItem->parentWidget();
00604 
00605                     dataItem->update();
00606                 }
00607             }
00608         }
00609     }
00610     else if (e->type()==QEvent::FocusOut) {
00611         if (static_cast<QFocusEvent*>(e)->reason()==QFocusEvent::Popup) {
00612             //d->widgetFocusedBeforePopup = (QWidget*)watched;
00613             d->popupFocused = true;
00614         }
00615         else
00616             d->popupFocused = false;
00617 //          d->widgetFocusedBeforePopup = 0;
00618 //      kdDebug() << "e->type()==QEvent::FocusOut " << watched->className() << " " <<watched->name() << endl;
00619 //      UNSET_FOCUS_USING_REASON(watched, static_cast<QFocusEvent*>(e)->reason());
00620     }
00621     return KexiDBFormBase::eventFilter(watched, e);
00622 }
00623 
00624 bool KexiDBForm::valueIsNull()
00625 {
00626     return true;
00627 }
00628 
00629 bool KexiDBForm::valueIsEmpty()
00630 {
00631     return true;
00632 }
00633 
00634 bool KexiDBForm::isReadOnly() const
00635 {
00636     if (d->dataAwareObject)
00637         return d->dataAwareObject->isReadOnly();
00639     return false;
00640 }
00641 
00642 void KexiDBForm::setReadOnly( bool readOnly )
00643 {
00644     if (d->dataAwareObject)
00645         d->dataAwareObject->setReadOnly( readOnly ); //???
00646 }
00647 
00648 QWidget* KexiDBForm::widget()
00649 {
00650     return this;
00651 }
00652 
00653 bool KexiDBForm::cursorAtStart()
00654 {
00655     return false;
00656 }
00657 
00658 bool KexiDBForm::cursorAtEnd()
00659 {
00660     return false;
00661 }
00662 
00663 void KexiDBForm::clear()
00664 {
00666 }
00667 
00668 bool KexiDBForm::preview() const {
00669     return dynamic_cast<KexiScrollView*>(d->dataAwareObject)
00670         ? dynamic_cast<KexiScrollView*>(d->dataAwareObject)->preview() : false;
00671 }
00672 
00673 void KexiDBForm::dragMoveEvent( QDragMoveEvent *e )
00674 {
00675     KexiDBFormBase::dragMoveEvent( e );
00676     emit handleDragMoveEvent(e);
00677 }
00678 
00679 void KexiDBForm::dropEvent( QDropEvent *e ) 
00680 {
00681     KexiDBFormBase::dropEvent( e );
00682     emit handleDropEvent(e);
00683 }
00684 
00685 void KexiDBForm::setCursor( const QCursor & cursor )
00686 {
00687     //js: empty, to avoid fscking problems with random cursors!
00689 
00690     if (KFormDesigner::FormManager::self()->isInserting()) //exception
00691         KexiDBFormBase::setCursor(cursor);
00692 }
00693 
00695 /*
00696 void KexiDBForm::paintEvent( QPaintEvent *e )
00697 {
00698     QPainter p;
00699     p.begin(this, true);
00700     bool unclipped = testWFlags( WPaintUnclipped );
00701     setWFlags( WPaintUnclipped );
00702 
00703     p.setPen(white);
00704     p.setRasterOp(XorROP);
00705     p.drawLine(e->rect().topLeft(), e->rect().bottomRight());
00706 
00707     if (!unclipped)
00708         clearWFlags( WPaintUnclipped );
00709     p.end();
00710     KexiDBFormBase::paintEvent(e);
00711 }
00712 */
00713 
00714 #include "kexidbform.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys