kexi

kexiformview.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
00003    Copyright (C) 2004-2007 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kexiformview.h"
00022 
00023 #include <qobjectlist.h>
00024 #include <qfileinfo.h>
00025 
00026 #include <formeditor/form.h>
00027 #include <formeditor/formIO.h>
00028 #include <formeditor/formmanager.h>
00029 #include <formeditor/objecttree.h>
00030 #include <formeditor/container.h>
00031 #include <formeditor/widgetpropertyset.h>
00032 #include <formeditor/commands.h>
00033 #include <formeditor/widgetwithsubpropertiesinterface.h>
00034 #include <formeditor/objecttree.h>
00035 
00036 #include <kexi.h>
00037 #include <kexidialogbase.h>
00038 #include <kexidragobjects.h>
00039 #include <kexidb/field.h>
00040 #include <kexidb/fieldlist.h>
00041 #include <kexidb/connection.h>
00042 #include <kexidb/cursor.h>
00043 #include <kexidb/utils.h>
00044 #include <kexidb/preparedstatement.h>
00045 #include <tableview/kexitableitem.h>
00046 #include <tableview/kexitableviewdata.h>
00047 #include <widget/kexipropertyeditorview.h>
00048 #include <widget/kexiqueryparameters.h>
00049 #include <kexiutils/utils.h>
00050 
00051 #include <koproperty/set.h>
00052 #include <koproperty/property.h>
00053 
00054 #include "widgets/kexidbform.h"
00055 #include "kexiformscrollview.h"
00056 #include "kexidatasourcepage.h"
00057 #include "widgets/kexidbautofield.h"
00058 
00059 #define NO_DSWIZARD
00060 
00062 
00063 KexiFormView::KexiFormView(KexiMainWindow *mainWin, QWidget *parent,
00064     const char *name, bool /*dbAware*/)
00065  : KexiDataAwareView( mainWin, parent, name )
00066  , m_propertySet(0)
00067  , m_resizeMode(KexiFormView::ResizeDefault)
00068  , m_query(0)
00069  , m_queryIsOwned(false)
00070  , m_cursor(0)
00071 // , m_firstFocusWidget(0)
00072 {
00073     m_delayedFormContentsResizeOnShow = 0;
00074 
00075     QHBoxLayout *l = new QHBoxLayout(this);
00076     l->setAutoAdd(true);
00077 
00078     m_scrollView = new KexiFormScrollView(this, viewMode()==Kexi::DataViewMode);
00079 
00080 //moved setViewWidget(m_scrollView);
00081 //  m_scrollView->show();
00082 
00083     m_dbform = new KexiDBForm(m_scrollView->viewport(), m_scrollView, name/*, conn*/);
00084 //  m_dbform->resize( m_scrollView->viewport()->size() - QSize(20, 20) );
00085 //  m_dbform->resize(QSize(400, 300));
00086     m_scrollView->setWidget(m_dbform);
00087     m_scrollView->setResizingEnabled(viewMode()!=Kexi::DataViewMode);
00088 
00089 //  initForm();
00090 
00091     if (viewMode()==Kexi::DataViewMode) {
00092         m_scrollView->recordNavigator()->setRecordHandler( m_scrollView );
00093         m_scrollView->viewport()->setPaletteBackgroundColor(m_dbform->palette().active().background());
00094 //moved to formmanager      connect(formPart()->manager(), SIGNAL(noFormSelected()), SLOT(slotNoFormSelected()));
00095     }
00096     else
00097     {
00098         connect(KFormDesigner::FormManager::self(), SIGNAL(propertySetSwitched(KoProperty::Set*, bool, const QCString&)),
00099             this, SLOT(slotPropertySetSwitched(KoProperty::Set*, bool, const QCString&)));
00100         connect(KFormDesigner::FormManager::self(), SIGNAL(dirty(KFormDesigner::Form *, bool)),
00101             this, SLOT(slotDirty(KFormDesigner::Form *, bool)));
00102 
00103         connect(m_dbform, SIGNAL(handleDragMoveEvent(QDragMoveEvent*)), 
00104             this, SLOT(slotHandleDragMoveEvent(QDragMoveEvent*)));
00105         connect(m_dbform, SIGNAL(handleDropEvent(QDropEvent*)), 
00106             this, SLOT(slotHandleDropEvent(QDropEvent*)));
00107 
00108         // action stuff
00109         plugSharedAction("formpart_taborder", KFormDesigner::FormManager::self(), SLOT(editTabOrder()));
00110         plugSharedAction("formpart_adjust_size", KFormDesigner::FormManager::self(), SLOT(adjustWidgetSize()));
00111 //TODO      plugSharedAction("formpart_pixmap_collection", formPart()->manager(), SLOT(editFormPixmapCollection()));
00112 //TODO      plugSharedAction("formpart_connections", formPart()->manager(), SLOT(editConnections()));
00113 
00114         plugSharedAction("edit_copy", KFormDesigner::FormManager::self(), SLOT(copyWidget()));
00115         plugSharedAction("edit_cut", KFormDesigner::FormManager::self(), SLOT(cutWidget()));
00116         plugSharedAction("edit_paste", KFormDesigner::FormManager::self(), SLOT(pasteWidget()));
00117         plugSharedAction("edit_delete", KFormDesigner::FormManager::self(), SLOT(deleteWidget()));
00118         plugSharedAction("edit_select_all", KFormDesigner::FormManager::self(), SLOT(selectAll()));
00119         plugSharedAction("formpart_clear_contents", KFormDesigner::FormManager::self(), SLOT(clearWidgetContent()));
00120         plugSharedAction("edit_undo", KFormDesigner::FormManager::self(), SLOT(undo()));
00121         plugSharedAction("edit_redo", KFormDesigner::FormManager::self(), SLOT(redo()));
00122 
00123         plugSharedAction("formpart_layout_menu", KFormDesigner::FormManager::self(), 0 );
00124         plugSharedAction("formpart_layout_hbox", KFormDesigner::FormManager::self(), SLOT(layoutHBox()) );
00125         plugSharedAction("formpart_layout_vbox", KFormDesigner::FormManager::self(), SLOT(layoutVBox()) );
00126         plugSharedAction("formpart_layout_grid", KFormDesigner::FormManager::self(), SLOT(layoutGrid()) );
00127 #ifdef KEXI_SHOW_SPLITTER_WIDGET
00128         plugSharedAction("formpart_layout_hsplitter", KFormDesigner::FormManager::self(), SLOT(layoutHSplitter()) );
00129         plugSharedAction("formpart_layout_vsplitter", KFormDesigner::FormManager::self(), SLOT(layoutVSplitter()) );
00130 #endif
00131         plugSharedAction("formpart_break_layout", KFormDesigner::FormManager::self(), SLOT(breakLayout()) );
00132 
00133         plugSharedAction("formpart_format_raise", KFormDesigner::FormManager::self(), SLOT(bringWidgetToFront()) );
00134         plugSharedAction("formpart_format_lower", KFormDesigner::FormManager::self(), SLOT(sendWidgetToBack()) );
00135 
00136         plugSharedAction("other_widgets_menu", KFormDesigner::FormManager::self(), 0 );
00137         setAvailable("other_widgets_menu", true);
00138 
00139         plugSharedAction("formpart_align_menu", KFormDesigner::FormManager::self(), 0 );
00140         plugSharedAction("formpart_align_to_left", KFormDesigner::FormManager::self(),SLOT(alignWidgetsToLeft()) );
00141         plugSharedAction("formpart_align_to_right", KFormDesigner::FormManager::self(), SLOT(alignWidgetsToRight()) );
00142         plugSharedAction("formpart_align_to_top", KFormDesigner::FormManager::self(), SLOT(alignWidgetsToTop()) );
00143         plugSharedAction("formpart_align_to_bottom", KFormDesigner::FormManager::self(), SLOT(alignWidgetsToBottom()) );
00144         plugSharedAction("formpart_align_to_grid", KFormDesigner::FormManager::self(), SLOT(alignWidgetsToGrid()) );
00145 
00146         plugSharedAction("formpart_adjust_size_menu", KFormDesigner::FormManager::self(), 0 );
00147         plugSharedAction("formpart_adjust_to_fit", KFormDesigner::FormManager::self(), SLOT(adjustWidgetSize()) );
00148         plugSharedAction("formpart_adjust_size_grid", KFormDesigner::FormManager::self(), SLOT(adjustSizeToGrid()) );
00149         plugSharedAction("formpart_adjust_height_small", KFormDesigner::FormManager::self(),  SLOT(adjustHeightToSmall()) );
00150         plugSharedAction("formpart_adjust_height_big", KFormDesigner::FormManager::self(), SLOT(adjustHeightToBig()) );
00151         plugSharedAction("formpart_adjust_width_small", KFormDesigner::FormManager::self(), SLOT(adjustWidthToSmall()) );
00152         plugSharedAction("formpart_adjust_width_big", KFormDesigner::FormManager::self(), SLOT(adjustWidthToBig()) );
00153 
00154         plugSharedAction("format_font", KFormDesigner::FormManager::self(), SLOT(changeFont()) );
00155     }
00156 
00157     initForm();
00158 
00159     KexiDataAwareView::init( m_scrollView, m_scrollView, m_scrollView,
00160         /* skip data-awarness if design mode */ viewMode()==Kexi::DesignViewMode );
00161 
00162     connect(this, SIGNAL(focus(bool)), this, SLOT(slotFocus(bool)));
00164 //  m_dbform->resize( m_dbform->size()+QSize(m_scrollView->verticalScrollBar()->width(), m_scrollView->horizontalScrollBar()->height()) );
00165 }
00166 
00167 KexiFormView::~KexiFormView()
00168 {
00169     if (m_cursor) {
00170         KexiDB::Connection *conn = parentDialog()->mainWin()->project()->dbConnection();
00171         conn->deleteCursor(m_cursor);
00172         m_cursor = 0;
00173     }
00174     deleteQuery();
00175 
00176     // Important: form window is closed.
00177     // Set property set to 0 because there is *only one* instance of a property set class
00178     // in Kexi, so the main window wouldn't know the set in fact has been changed.
00179     m_propertySet = 0;
00180     propertySetSwitched();
00181 }
00182 
00183 void
00184 KexiFormView::deleteQuery()
00185 {
00186     if (m_cursor) {
00187         KexiDB::Connection *conn = parentDialog()->mainWin()->project()->dbConnection();
00188         conn->deleteCursor(m_cursor);
00189         m_cursor = 0;
00190     }
00191 
00192     if (m_queryIsOwned) {
00193         delete m_query;
00194     } else {
00196     }
00197     m_query = 0;
00198 }
00199 
00200 KFormDesigner::Form*
00201 KexiFormView::form() const
00202 {
00203     if(viewMode()==Kexi::DataViewMode)
00204         return tempData()->previewForm;
00205     else
00206         return tempData()->form;
00207 }
00208 
00209 void
00210 KexiFormView::setForm(KFormDesigner::Form *f)
00211 {
00212     if(viewMode()==Kexi::DataViewMode)
00213         tempData()->previewForm = f;
00214     else
00215         tempData()->form = f;
00216 }
00217 
00218 void
00219 KexiFormView::initForm()
00220 {
00221     setForm( new KFormDesigner::Form(KexiFormPart::library(), 0, viewMode()==Kexi::DesignViewMode) );
00222 //  if (viewMode()==Kexi::DataViewMode)
00223         //form()->setDesignMode(false);
00224     form()->createToplevel(m_dbform, m_dbform);
00225 
00226     if (viewMode()==Kexi::DesignViewMode) {
00227         //we want to be informed about executed commands
00228         connect(form()->commandHistory(), SIGNAL(commandExecuted()),
00229             KFormDesigner::FormManager::self(), SLOT(slotHistoryCommandExecuted()));
00230     }
00231 
00232     const bool newForm = parentDialog()->id() < 0;
00233 
00234     KexiDB::FieldList *fields = 0;
00235     if (newForm) {
00236         // Show the form wizard if this is a new Form
00237 #ifndef NO_DSWIZARD
00238         KexiDataSourceWizard *w = new KexiDataSourceWizard(mainWin(), (QWidget*)mainWin(), "datasource_wizard");
00239         if(!w->exec())
00240             fields = 0;
00241         else
00242             fields = w->fields();
00243         delete w;
00244 #endif
00245     }
00246 
00247     if(fields)
00248     {
00249         QDomDocument dom;
00250         formPart()->generateForm(fields, dom);
00251         KFormDesigner::FormIO::loadFormFromDom(form(), m_dbform, dom);
00253     }
00254     else
00255         loadForm();
00256 
00257     if(form()->autoTabStops())
00258         form()->autoAssignTabStops();
00259 
00260     //collect tab order information
00261     m_dbform->updateTabStopsOrder(form());
00262 
00263 //  if (m_dbform->orderedFocusWidgets()->first())
00264     //  m_scrollView->setFocusProxy( m_dbform->orderedFocusWidgets()->first() );
00265 
00266     KFormDesigner::FormManager::self()->importForm(form(), viewMode()==Kexi::DataViewMode);
00267     m_scrollView->setForm(form());
00268 
00269 //  m_dbform->updateTabStopsOrder(form());
00270 //  QSize s = m_dbform->size();
00271 //  QApplication::sendPostedEvents();
00272 //  m_scrollView->resize( s );
00273 //  m_dbform->resize(s);
00274     m_scrollView->refreshContentsSize();
00275 //  m_scrollView->refreshContentsSizeLater(true,true);
00276 
00277     if (newForm && !fields) {
00278         /* Our form's area will be resized more than once.
00279         Let's resize form widget itself later. */
00280         m_delayedFormContentsResizeOnShow = 3;
00281     }
00282 
00283     updateDataSourcePage();
00284 
00285     if (!newForm && viewMode()==Kexi::DesignViewMode) {
00286         form()->clearCommandHistory();
00287     }
00288 }
00289 
00290 void KexiFormView::updateAutoFieldsDataSource()
00291 {
00293     //update autofields: 
00294     //-inherit captions
00295     //-inherit data types
00296     //(this data has not been stored in the form)
00297     QString dataSourceString( m_dbform->dataSource() );
00298     QCString dataSourceMimeTypeString( m_dbform->dataSourceMimeType() );
00299     KexiDB::Connection *conn = parentDialog()->mainWin()->project()->dbConnection();
00300     KexiDB::TableOrQuerySchema tableOrQuery(
00301         conn, dataSourceString.latin1(), dataSourceMimeTypeString=="kexi/table");
00302     if (!tableOrQuery.table() && !tableOrQuery.query())
00303         return;
00304     for (KFormDesigner::ObjectTreeDictIterator it(*form()->objectTree()->dict());
00305         it.current(); ++it)
00306     {
00307         KexiDBAutoField *afWidget = dynamic_cast<KexiDBAutoField*>( it.current()->widget() );
00308         if (afWidget) {
00309             KexiDB::QueryColumnInfo *colInfo = tableOrQuery.columnInfo( afWidget->dataSource() );
00310             if (colInfo) {
00311                 afWidget->setColumnInfo(colInfo);
00312                     //setFieldTypeInternal((int)colInfo->field->type());
00313                     //afWidget->setFieldCaptionInternal(colInfo->captionOrAliasOrName());
00314             }
00315         }
00316     }
00317 }
00318 
00319 void KexiFormView::updateValuesForSubproperties()
00320 {
00322     //update autofields: 
00323     //-inherit captions
00324     //-inherit data types
00325     //(this data has not been stored in the form)
00326     QString dataSourceString( m_dbform->dataSource() );
00327     QCString dataSourceMimeTypeString( m_dbform->dataSourceMimeType() );
00328     KexiDB::Connection *conn = parentDialog()->mainWin()->project()->dbConnection();
00329     KexiDB::TableOrQuerySchema tableOrQuery(
00330         conn, dataSourceString.latin1(), dataSourceMimeTypeString=="kexi/table");
00331     if (!tableOrQuery.table() && !tableOrQuery.query())
00332         return;
00333 
00334     for (KFormDesigner::ObjectTreeDictIterator it(*form()->objectTree()->dict());
00335         it.current(); ++it)
00336     {
00337         // (delayed) set values for subproperties
00339         KFormDesigner::WidgetWithSubpropertiesInterface* subpropIface 
00340             = dynamic_cast<KFormDesigner::WidgetWithSubpropertiesInterface*>( it.current()->widget() );
00341         if (subpropIface && subpropIface->subwidget() && it.current()->subproperties() ) {
00342             QWidget *subwidget = subpropIface->subwidget();
00343             QMap<QString, QVariant>* subprops = it.current()->subproperties();
00344             for (QMapConstIterator<QString, QVariant> subpropIt = subprops->constBegin(); subpropIt!=subprops->constEnd(); ++subpropIt) {
00345                 kexipluginsdbg << "KexiFormView::loadForm(): delayed setting of the subproperty: widget="
00346                     << it.current()->widget()->name() << " prop=" << subpropIt.key() << " val=" << subpropIt.data() << endl;
00347 
00348                 const int count = subwidget->metaObject()->findProperty(subpropIt.key().latin1(), true);
00349                 const QMetaProperty *meta = count!=-1 ? subwidget->metaObject()->property(count, true) : 0;
00350                 if (meta) {
00351                     // Special case: the property value of type enum (set) but is saved as a string list,
00352                     // not as int, so we need to translate it to int. It's been created as such
00353                     // by FormIO::readPropertyValue(). Example: "alignment" property.
00354                     if (meta->isSetType() && subpropIt.data().type()==QVariant::StringList) {
00355                         QStrList keys;
00356                         const QStringList list( subpropIt.data().toStringList() );
00357                         for (QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it)
00358                             keys.append((*it).latin1());
00359                         subwidget->setProperty( subpropIt.key().latin1(), meta->keysToValue(keys) );
00360                     }
00361                     else {
00362                         subwidget->setProperty( subpropIt.key().latin1(), subpropIt.data() );
00363                     }
00364                 }
00365             }//for
00366         }
00367     }
00368 }
00369 
00371 static void setUnsavedBLOBIdsForDataViewMode( 
00372     QWidget* widget, const QMap<QCString, KexiBLOBBuffer::Id_t>& unsavedLocalBLOBsByName)
00373 {
00374     if (-1 != widget->metaObject()->findProperty("pixmapId")) {
00375         const KexiBLOBBuffer::Id_t blobID = unsavedLocalBLOBsByName[ widget->name() ];
00376         if (blobID > 0)
00377             widget->setProperty("pixmapId", (uint /* KexiBLOBBuffer::Id_t is unsafe and unsupported by QVariant - will be fixed in Qt4*/)blobID);
00378     }
00379     const QObjectList *list = widget->children();
00380     if (!list)
00381         return;
00382     for (QObjectListIterator it(*list); it.current(); ++it) {
00383         if (dynamic_cast<QWidget*>(it.current()))
00384             setUnsavedBLOBIdsForDataViewMode(dynamic_cast<QWidget*>(it.current()), unsavedLocalBLOBsByName);
00385     }
00386 }
00387 
00388 void
00389 KexiFormView::loadForm()
00390 {
00391 //@todo also load m_resizeMode !
00392 
00393     kexipluginsdbg << "KexiFormView::loadForm() Loading the form with id : " << parentDialog()->id() << endl;
00394     // If we are previewing the Form, use the tempData instead of the form stored in the db
00395     if(viewMode()==Kexi::DataViewMode && !tempData()->tempForm.isNull() )
00396     {
00397         KFormDesigner::FormIO::loadFormFromString(form(), m_dbform, tempData()->tempForm);
00398         setUnsavedBLOBIdsForDataViewMode( m_dbform, tempData()->unsavedLocalBLOBsByName );
00399         updateAutoFieldsDataSource();
00400         updateValuesForSubproperties();
00401         return;
00402     }
00403 
00404     // normal load
00405     QString data;
00406     loadDataBlock(data);
00407     KFormDesigner::FormIO::loadFormFromString(form(), m_dbform, data);
00408 
00409     //"autoTabStops" property is loaded -set it within the form tree as well
00410     form()->setAutoTabStops( m_dbform->autoTabStops() );
00411 
00412     updateAutoFieldsDataSource();
00413     updateValuesForSubproperties();
00414 }
00415 
00416 void
00417 KexiFormView::slotPropertySetSwitched(KoProperty::Set *set, bool forceReload, const QCString& propertyToSelect)
00418 {
00419 //  if (set && parentDialog()!=parentDialog()->mainWin()->currentDialog())
00420     if (form() != KFormDesigner::FormManager::self()->activeForm())
00421         return; //this is not the current form view
00422     m_propertySet = set;
00423     if (forceReload)
00424         propertySetReloaded(true/*preservePrevSelection*/, propertyToSelect);
00425     else
00426         propertySetSwitched();
00427 
00428     formPart()->dataSourcePage()->assignPropertySet(m_propertySet);
00429 }
00430 
00431 tristate
00432 KexiFormView::beforeSwitchTo(int mode, bool &dontStore)
00433 {
00434     if (mode!=viewMode()) {
00435         if (viewMode()==Kexi::DataViewMode) {
00436             if (!m_scrollView->acceptRowEdit())
00437                 return cancelled;
00438 
00439             m_scrollView->beforeSwitchView();
00440         }
00441         else {
00442             //remember our pos
00443             tempData()->scrollViewContentsPos
00444                 = QPoint(m_scrollView->contentsX(), m_scrollView->contentsY());
00445         }
00446     }
00447 
00448     // we don't store on db, but in our TempData
00449     dontStore = true;
00450     if(dirty() && (mode == Kexi::DataViewMode) && form()->objectTree()) {
00451         KexiFormPart::TempData* temp = tempData();
00452         if (!KFormDesigner::FormIO::saveFormToString(form(), temp->tempForm))
00453             return false;
00454 
00455         //collect blobs from design mode by name for use in data view mode
00456         temp->unsavedLocalBLOBsByName.clear();
00457         for (QMapConstIterator<QWidget*, KexiBLOBBuffer::Id_t> it = temp->unsavedLocalBLOBs.constBegin(); 
00458             it!=temp->unsavedLocalBLOBs.constEnd(); ++it)
00459         {
00460             if (!it.key())
00461                 continue;
00462             temp->unsavedLocalBLOBsByName.insert( it.key()->name(), it.data() );
00463         }
00464     }
00465 
00466     return true;
00467 }
00468 
00469 tristate
00470 KexiFormView::afterSwitchFrom(int mode)
00471 {
00472     if (mode == 0 || mode == Kexi::DesignViewMode) {
00473         if (parentDialog()->neverSaved()) {
00474             m_dbform->resize(QSize(400, 300));
00475             m_scrollView->refreshContentsSizeLater(true,true);
00476             //m_delayedFormContentsResizeOnShow = false;
00477         }
00478     }
00479 
00480     if (mode != 0 && mode != Kexi::DesignViewMode) {
00481         //preserve contents pos after switching to other view
00482         m_scrollView->setContentsPos(tempData()->scrollViewContentsPos.x(),
00483             tempData()->scrollViewContentsPos.y());
00484     }
00485 //  if (mode == Kexi::DesignViewMode) {
00486         //m_scrollView->move(0,0);
00487         //m_scrollView->setContentsPos(0,0);
00488         //m_scrollView->moveChild(m_dbform, 0, 0);
00489 //  }
00490 
00491     if((mode == Kexi::DesignViewMode) && viewMode()==Kexi::DataViewMode) {
00492         // The form may have been modified, so we must recreate the preview
00493         delete m_dbform; // also deletes form()
00494         m_dbform = new KexiDBForm(m_scrollView->viewport(), m_scrollView, "KexiDBForm");
00495         m_scrollView->setWidget(m_dbform);
00496 
00497         initForm();
00498 //moved to formmanager      slotNoFormSelected();
00499 
00500         //reset position
00501         m_scrollView->setContentsPos(0,0);
00502         m_dbform->move(0,0);
00503 
00504     }
00505 
00506     //update tab stops if needed
00507     if (viewMode()==Kexi::DataViewMode) {
00508 //      //propagate current "autoTabStops" property value to the form tree
00509 //      form()->setAutoTabStops( m_dbform->autoTabStops() );
00510 
00511 //      if(form()->autoTabStops())
00512 //          form()->autoAssignTabStops();
00513     }
00514     else {
00515         //set "autoTabStops" property
00516         m_dbform->setAutoTabStops( form()->autoTabStops() );
00517     }
00518 
00519     if (viewMode() == Kexi::DataViewMode) {
00520 //TMP!!
00521         initDataSource();
00522 
00523         //handle events for this form
00524         m_scrollView->setMainWidgetForEventHandling(parentDialog()->mainWin(), m_dbform);
00525 
00526         //set focus on 1st focusable widget which has valid dataSource property set
00527         if (!m_dbform->orderedFocusWidgets()->isEmpty()) {
00528 //          QWidget *www = focusWidget();
00529             //if (Kexi::hasParent(this, qApp->focusWidget())) {
00530                 KexiUtils::unsetFocusWithReason(qApp->focusWidget(), QFocusEvent::Tab);
00531             //}
00532 
00533             QPtrListIterator<QWidget> it(*m_dbform->orderedFocusWidgets());
00534             for (;it.current(); ++it) {
00535                 KexiFormDataItemInterface *iface = dynamic_cast<KexiFormDataItemInterface*>(it.current());
00536                 if (iface)
00537                     kexipluginsdbg << iface->dataSource() << endl;
00538                 if (iface && iface->columnInfo() && !iface->isReadOnly()
00540                     /* also skip autoincremented fields:*/
00541                     && !iface->columnInfo()->field->isAutoIncrement()) 
00542                     break;
00543             }
00544             if (!it.current()) //eventually, focus first available widget if nothing other is available
00545                 it.toFirst();
00546 
00547             it.current()->setFocus();
00548             KexiUtils::setFocusWithReason(it.current(), QFocusEvent::Tab);
00549             m_setFocusInternalOnce = it.current();
00550         }
00551 
00552         if (m_query)
00553             m_scrollView->selectFirstRow();
00554     }
00555 
00556     //dirty only if it's a new object
00557     if (mode == 0)
00558         setDirty( parentDialog()->partItem()->neverSaved() );
00559 
00560     if (mode==Kexi::DataViewMode && viewMode()==Kexi::DesignViewMode) {
00561 //      slotPropertySetSwitched
00562 //      emit KFormDesigner::FormManager::self()->propertySetSwitched( KFormDesigner::FormManager::self()->propertySet()->set(), true );
00563     }
00564 
00565     return true;
00566 }
00567 
00568 void KexiFormView::initDataSource()
00569 {
00570     deleteQuery();
00571     QString dataSourceString( m_dbform->dataSource() );
00572     QCString dataSourceMimeTypeString( m_dbform->dataSourceMimeType() );
00574     bool ok = !dataSourceString.isEmpty();
00575 
00576 /*          if (m_previousDataSourceString.lower()==dataSourceString.lower() && !m_cursor) {
00577             //data source changed: delete previous cursor
00578             m_conn->deleteCursor(m_cursor);
00579             m_cursor = 0;
00580         }*/
00581 
00582     KexiDB::TableSchema *tableSchema = 0;
00583     KexiDB::Connection *conn = 0;
00584     QStringList sources;
00585     bool forceReadOnlyDataSource = false;
00586 
00587     if (ok) {
00588 //      m_previousDataSourceString = dataSourceString;
00589 
00590         //collect all data-aware widgets and create query schema
00591         m_scrollView->setMainDataSourceWidget(m_dbform);
00592         sources = m_scrollView->usedDataSources();
00593         conn = parentDialog()->mainWin()->project()->dbConnection();
00594         if (dataSourceMimeTypeString.isEmpty() /*table type is the default*/ 
00595             || dataSourceMimeTypeString=="kexi/table")
00596         {
00597             tableSchema = conn->tableSchema( dataSourceString );
00598             if (tableSchema) {
00599                 /* We will build a _minimum_ query schema from selected table fields. */
00600                 m_query = new KexiDB::QuerySchema();
00601                 m_queryIsOwned = true;
00602 
00603                 if (dataSourceMimeTypeString.isEmpty())
00604                     m_dbform->setDataSourceMimeType("kexi/table"); //update for compatibility
00605             }
00606         }
00607         
00608         if (!tableSchema) {
00609             if (dataSourceMimeTypeString.isEmpty() /*also try to find a query (for compatibility with Kexi<=0.9)*/ 
00610                 || dataSourceMimeTypeString=="kexi/query")
00611             {
00612                 //try to find predefined query schema.
00613                 //Note: In general, we could not skip unused fields within this query because
00614                 //      it can have GROUP BY clause.
00616                 m_query = conn->querySchema( dataSourceString );
00617                 m_queryIsOwned = false;
00618                 ok = m_query != 0;
00619                 if (ok && dataSourceMimeTypeString.isEmpty())
00620                     m_dbform->setDataSourceMimeType("kexi/query"); //update for compatibility
00621                 // query results are read-only
00623                 forceReadOnlyDataSource = true;
00624             }
00625             else //no other mime types supported
00626                 ok = false;
00627         }
00628     }
00629 
00630     QDict<char> invalidSources(997);
00631     if (ok) {
00632         KexiDB::IndexSchema *pkey = tableSchema ? tableSchema->primaryKey() : 0;
00633         if (pkey) {
00634             //always add all fields from table's primary key
00635             // (don't worry about duplicates, unique list will be computed later)
00636             sources += pkey->names();
00637             kexipluginsdbg << "KexiFormView::initDataSource(): pkey added to data sources: " << pkey->names() << endl;
00638         }
00639         kexipluginsdbg << "KexiFormView::initDataSource(): sources=" << sources << endl;
00640 
00641         uint index = 0;
00642         for (QStringList::ConstIterator it = sources.constBegin();
00643             it!=sources.constEnd(); ++it, index++) {
00645             QString fieldName( (*it).lower() );
00646             //remove "tablename." if it was prepended
00647             if (tableSchema && fieldName.startsWith( tableSchema->name().lower()+"." ))
00648                 fieldName = fieldName.mid(tableSchema->name().length()+1);
00649             //remove "queryname." if it was prepended
00650             if (!tableSchema && fieldName.startsWith( m_query->name().lower()+"." ))
00651                 fieldName = fieldName.mid(m_query->name().length()+1);
00652             KexiDB::Field *f = tableSchema ? tableSchema->field(fieldName) : m_query->field(fieldName);
00653             if (!f) {
00655                 //remove this widget from the set of data widgets in the provider
00657                 invalidSources.insert( fieldName, (const char*)1 ); // += index;
00658                 kexipluginsdbg << "KexiFormView::initDataSource(): invalidSources+=" << index << " (" 
00659                     << (*it) << ")" << endl;
00660                 continue;
00661             }
00662             if (tableSchema) {
00663                 if (!m_query->hasField( f )) {
00664                     //we're building a new query: add this field
00665                     m_query->addField( f );
00666                 }
00667             }
00668         }
00669         if (invalidSources.count()==sources.count()) {
00670             //all data sources are invalid! don't execute the query
00671             deleteQuery();
00672         }
00673         else {
00674             KexiDB::debug( m_query->parameters() );
00675             // like in KexiQueryView::executeQuery()
00676             QValueList<QVariant> params;
00677             {
00678                 KexiUtils::WaitCursorRemover remover;
00679                 params = KexiQueryParameters::getParameters(this, *conn->driver(), *m_query, ok);
00680             }
00681             if (ok) //input cancelled
00682                 m_cursor = conn->executeQuery( *m_query, params );
00683         }
00684         m_scrollView->invalidateDataSources( invalidSources, m_query );
00685         ok = m_cursor!=0;
00686     }
00687 
00688     if (!invalidSources.isEmpty())
00689         m_dbform->updateTabStopsOrder();
00690 
00691     if (ok) {
00694         KexiTableViewData* data = new KexiTableViewData(m_cursor);
00695         if (forceReadOnlyDataSource)
00696             data->setReadOnly(true);
00697         data->preloadAllRows();
00698 
00700 //          int resultCount = -1;
00701 //          if (ok) {
00702 //              resultCount = m_conn->resultCount(m_conn->selectStatement(*m_query));
00703 //              ok = m_cursor->reopen();
00704 //          }
00705 //          if (ok)
00706 //              ok = ! (!m_cursor->moveFirst() && m_cursor->error());
00707 
00708         m_scrollView->setData( data, true /*owner*/ );
00709     }
00710     else
00711         m_scrollView->setData( 0, false );
00712 }
00713 
00714 void
00715 KexiFormView::slotDirty(KFormDesigner::Form *dirtyForm, bool isDirty)
00716 {
00717     if(dirtyForm == form())
00718         KexiViewBase::setDirty(isDirty);
00719 }
00720 
00721 KexiDB::SchemaData*
00722 KexiFormView::storeNewData(const KexiDB::SchemaData& sdata, bool &cancel)
00723 {
00724     KexiDB::SchemaData *s = KexiViewBase::storeNewData(sdata, cancel);
00725     kexipluginsdbg << "KexiDBForm::storeNewData(): new id:" << s->id() << endl;
00726 
00727     if (!s || cancel) {
00728         delete s;
00729         return 0;
00730     }
00731     if (!storeData()) {
00732         //failure: remove object's schema data to avoid garbage
00733         KexiDB::Connection *conn = parentDialog()->mainWin()->project()->dbConnection();
00734         conn->removeObject( s->id() );
00735         delete s;
00736         return 0;
00737     }
00738     return s;
00739 }
00740 
00741 tristate
00742 KexiFormView::storeData(bool dontAsk)
00743 {
00744     Q_UNUSED(dontAsk);
00745     kexipluginsdbg << "KexiDBForm::storeData(): " << parentDialog()->partItem()->name() 
00746         << " [" << parentDialog()->id() << "]" << endl;
00747 
00748     //-- first, store local BLOBs, so identifiers can be updated
00750     KexiDB::Connection *conn = parentDialog()->mainWin()->project()->dbConnection();
00751     KexiDB::TableSchema *blobsTable = conn->tableSchema("kexi__blobs");
00752     if (!blobsTable) { //compatibility check for older Kexi project versions
00754         return false;
00755     }
00756     // Not all engines accept passing NULL to PKEY o_id, so we're omitting it.
00757     QStringList blobsFieldNamesWithoutID(blobsTable->names());
00758     blobsFieldNamesWithoutID.pop_front();
00759     KexiDB::FieldList *blobsFieldsWithoutID = blobsTable->subList(blobsFieldNamesWithoutID);
00760     
00761     KexiDB::PreparedStatement::Ptr st = conn->prepareStatement(
00762         KexiDB::PreparedStatement::InsertStatement, *blobsFieldsWithoutID);
00763     if (!st) {
00764         delete blobsFieldsWithoutID;
00766         return false;
00767     }
00768     KexiBLOBBuffer *blobBuf = KexiBLOBBuffer::self();
00769     KexiFormView *designFormView 
00770         = dynamic_cast<KexiFormView*>( parentDialog()->viewForMode(Kexi::DesignViewMode) );
00771     if (designFormView) {
00772         for (QMapConstIterator<QWidget*, KexiBLOBBuffer::Id_t> it = tempData()->unsavedLocalBLOBs.constBegin(); 
00773             it!=tempData()->unsavedLocalBLOBs.constEnd(); ++it)
00774         {
00775             if (!it.key()) {
00776                 kexipluginswarn << "KexiFormView::storeData(): it.key()==0 !" << endl;
00777                 continue;
00778             }
00779             kexipluginsdbg << "name=" << it.key()->name() << " dataID=" << it.data() << endl;
00780             KexiBLOBBuffer::Handle h( blobBuf->objectForId(it.data(), false) );
00781             if (!h)
00782                 continue; //no BLOB assigned
00783 
00784             QString originalFileName(h.originalFileName());
00785             QFileInfo fi(originalFileName);
00786             QString caption(fi.baseName().replace('_', " ").simplifyWhiteSpace());
00787 
00788             if (st) {
00789                 *st /* << NO, (pgsql doesn't support this):QVariant()*/ /*id*/ 
00790                     << h.data() << originalFileName << caption 
00791                     << h.mimeType() << (uint)h.folderId();
00792                 if (!st->execute()) {
00793                     delete blobsFieldsWithoutID;
00794                     kexipluginsdbg << " execute error" << endl;
00795                     return false;
00796                 }
00797             }
00798             delete blobsFieldsWithoutID;
00799             blobsFieldsWithoutID=0;
00800             const Q_ULLONG storedBLOBID = conn->lastInsertedAutoIncValue("o_id", "kexi__blobs");
00801             if ((Q_ULLONG)-1 == storedBLOBID) {
00803                 return false;
00804             }
00805             kexipluginsdbg << " storedDataID=" << storedBLOBID << endl;
00806             h.setStoredWidthID((KexiBLOBBuffer::Id_t /*unsafe - will be fixed in Qt4*/)storedBLOBID);
00807             //set widget's internal property so it can be saved...
00808             const QVariant oldStoredPixmapId( it.key()->property("storedPixmapId") );
00809             it.key()->setProperty("storedPixmapId", 
00810                 QVariant((uint /* KexiBLOBBuffer::Id_t is unsafe and unsupported by QVariant - will be fixed in Qt4*/)storedBLOBID));
00811             KFormDesigner::ObjectTreeItem *widgetItem = designFormView->form()->objectTree()->lookup(it.key()->name()); //form()->objectTree()->lookup(it.key()->name());
00812             if (widgetItem)
00813                 widgetItem->addModifiedProperty( "storedPixmapId", oldStoredPixmapId );
00814             else
00815                 kexipluginswarn << "KexiFormView::storeData(): no '" << widgetItem->name() << "' widget found within a form" << endl;
00816         }
00817     }
00818 
00819     //-- now, save form's XML
00820     QString data;
00821     if (!KFormDesigner::FormIO::saveFormToString(tempData()->form, data))
00822         return false;
00823     if (!storeDataBlock(data))
00824         return false;
00825 
00826     //all blobs are now saved
00827     tempData()->unsavedLocalBLOBs.clear();
00828 
00829     tempData()->tempForm = QString::null;
00830     return true;
00831 }
00832 
00833 #if 0
00835 void
00836 KexiFormView::slotWidgetSelected(KFormDesigner::Form *f, bool multiple)
00837 {
00838     if(f != form())
00839         return;
00840 
00841     enableFormActions();
00842     // Enable edit actions
00843     setAvailable("edit_copy", true);
00844     setAvailable("edit_cut", true);
00845     setAvailable("edit_clear", true);
00846 
00847     // 'Align Widgets' menu
00848     setAvailable("formpart_align_menu", multiple);
00849     setAvailable("formpart_align_to_left", multiple);
00850     setAvailable("formpart_align_to_right", multiple);
00851     setAvailable("formpart_align_to_top", multiple);
00852     setAvailable("formpart_align_to_bottom", multiple);
00853 
00854     setAvailable("formpart_adjust_size_menu", true);
00855     setAvailable("formpart_adjust_width_small", multiple);
00856     setAvailable("formpart_adjust_width_big", multiple);
00857     setAvailable("formpart_adjust_height_small", multiple);
00858     setAvailable("formpart_adjust_height_big", multiple);
00859 
00860     setAvailable("formpart_format_raise", true);
00861     setAvailable("formpart_format_lower", true);
00862 
00863     // If the widgets selected is a container, we enable layout actions
00864     if(!multiple)
00865     {
00866         KFormDesigner::ObjectTreeItem *item = f->objectTree()->lookup( f->selectedWidgets()->first()->name() );
00867         if(item && item->container())
00868             multiple = true;
00869     }
00870     // Layout actions
00871     setAvailable("formpart_layout_hbox", multiple);
00872     setAvailable("formpart_layout_vbox", multiple);
00873     setAvailable("formpart_layout_grid", multiple);
00874 
00875     KFormDesigner::Container *container = f->activeContainer();
00876     setAvailable("formpart_break_layout", container ?
00877         (container->layoutType() != KFormDesigner::Container::NoLayout) : false );
00878 }
00879 
00880 void
00881 KexiFormView::slotFormWidgetSelected(KFormDesigner::Form *f)
00882 {
00883     if(f != form())
00884         return;
00885 
00886     disableWidgetActions();
00887     enableFormActions();
00888 
00889     // Layout actions
00890     setAvailable("formpart_layout_hbox", true);
00891     setAvailable("formpart_layout_vbox", true);
00892     setAvailable("formpart_layout_grid", true);
00893     setAvailable("formpart_break_layout", (f->toplevelContainer()->layoutType() != KFormDesigner::Container::NoLayout));
00894 }
00895 
00896 void
00897 KexiFormView::slotNoFormSelected() // == form in preview mode
00898 {
00899     disableWidgetActions();
00900 
00901     // Disable paste action
00902     setAvailable("edit_paste", false);
00903     setAvailable("edit_undo", false);
00904     setAvailable("edit_redo", false);
00905 
00906     // Disable 'Tools' actions
00907     setAvailable("formpart_pixmap_collection", false);
00908     setAvailable("formpart_connections", false);
00909     setAvailable("formpart_taborder", false);
00910     setAvailable("formpart_change_style", false);
00911 }
00912 
00913 void
00914 KexiFormView::enableFormActions()
00915 {
00916     // Enable 'Tools' actions
00917     setAvailable("formpart_pixmap_collection", true);
00918     setAvailable("formpart_connections", true);
00919     setAvailable("formpart_taborder", true);
00920 
00921     setAvailable("edit_paste", KFormDesigner::FormManager::self()->isPasteEnabled());
00922 }
00923 
00924 void
00925 KexiFormView::disableWidgetActions()
00926 {
00927     // Disable edit actions
00928     setAvailable("edit_copy", false);
00929     setAvailable("edit_cut", false);
00930     setAvailable("edit_clear", false);
00931 
00932     // Disable format functions
00933     setAvailable("formpart_align_menu", false);
00934     setAvailable("formpart_align_to_left", false);
00935     setAvailable("formpart_align_to_right", false);
00936     setAvailable("formpart_align_to_top", false);
00937     setAvailable("formpart_align_to_bottom", false);
00938 
00939     setAvailable("formpart_adjust_size_menu", false);
00940     setAvailable("formpart_adjust_width_small", false);
00941     setAvailable("formpart_adjust_width_big", false);
00942     setAvailable("formpart_adjust_height_small", false);
00943     setAvailable("formpart_adjust_height_big", false);
00944 
00945     setAvailable("formpart_format_raise", false);
00946     setAvailable("formpart_format_lower", false);
00947 
00948     setAvailable("formpart_layout_hbox", false);
00949     setAvailable("formpart_layout_vbox", false);
00950     setAvailable("formpart_layout_grid", false);
00951     setAvailable("formpart_break_layout", false);
00952 }
00953 
00954 void
00955 KexiFormView::setUndoEnabled(bool enabled)
00956 {
00957     setAvailable("edit_undo", enabled);
00958 }
00959 
00960 void
00961 KexiFormView::setRedoEnabled(bool enabled)
00962 {
00963     setAvailable("edit_redo", enabled);
00964 }
00965 #endif //0
00966 
00967 QSize
00968 KexiFormView::preferredSizeHint(const QSize& otherSize)
00969 {
00970     if (parentDialog()->neverSaved()) {
00971         //ignore otherSize if possible
00972 //      return KexiViewBase::preferredSizeHint( (parentDialog() && parentDialog()->mdiParent()) ? QSize(10000,10000) : otherSize);
00973     }
00974 
00975     return (m_dbform->size()
00976             +QSize(m_scrollView->verticalScrollBar()->isVisible() ? m_scrollView->verticalScrollBar()->width()*3/2 : 10,
00977              m_scrollView->horizontalScrollBar()->isVisible() ? m_scrollView->horizontalScrollBar()->height()*3/2 : 10))
00978         .expandedTo( KexiViewBase::preferredSizeHint(otherSize) );
00979 }
00980 
00981 void
00982 KexiFormView::resizeEvent( QResizeEvent *e )
00983 {
00984     if (viewMode()==Kexi::DataViewMode) {
00985         m_scrollView->refreshContentsSizeLater(
00986             e->size().width()!=e->oldSize().width(),
00987             e->size().height()!=e->oldSize().height()
00988         );
00989     }
00990     KexiViewBase::resizeEvent(e);
00991     m_scrollView->updateNavPanelGeometry();
00992     if (m_delayedFormContentsResizeOnShow>0) { // && isVisible()) {
00993         m_delayedFormContentsResizeOnShow--;
00994         m_dbform->resize( e->size() - QSize(30, 30) );
00995     }
00996 }
00997 
00998 void
00999 KexiFormView::setFocusInternal()
01000 {
01001     if (viewMode() == Kexi::DataViewMode) {
01002         if (m_dbform->focusWidget()) {
01003             //better-looking focus
01004             if (m_setFocusInternalOnce) {
01005                 KexiUtils::setFocusWithReason(m_setFocusInternalOnce, QFocusEvent::Other);//Tab);
01006                 m_setFocusInternalOnce = 0;
01007             }
01008             else {
01009                 //ok? SET_FOCUS_USING_REASON(m_dbform->focusWidget(), QFocusEvent::Other);//Tab);
01010             }
01011             return;
01012         }
01013     }
01014     QWidget::setFocus();
01015 }
01016 
01017 void
01018 KexiFormView::show()
01019 {
01020     KexiDataAwareView::show();
01021 
01022 //moved from KexiFormScrollView::show():
01023 
01024     //now get resize mode settings for entire form
01025     //  if (resizeMode() == KexiFormView::ResizeAuto)
01026     if (viewMode()==Kexi::DataViewMode) {
01027         if (resizeMode() == KexiFormView::ResizeAuto)
01028             m_scrollView->setResizePolicy(QScrollView::AutoOneFit);
01029     }
01030 }
01031 
01032 void
01033 KexiFormView::slotFocus(bool in)
01034 {
01035     if(in && form() && KFormDesigner::FormManager::self() && KFormDesigner::FormManager::self()->activeForm() != form()) {
01036         KFormDesigner::FormManager::self()->windowChanged(m_dbform);
01037         updateDataSourcePage();
01038     }
01039 }
01040 
01041 void
01042 KexiFormView::updateDataSourcePage()
01043 {
01044     if (viewMode()==Kexi::DesignViewMode) {
01045         QCString dataSourceMimeType, dataSource;
01046         KFormDesigner::WidgetPropertySet *set = KFormDesigner::FormManager::self()->propertySet();
01047         if (set->contains("dataSourceMimeType"))
01048             dataSourceMimeType = (*set)["dataSourceMimeType"].value().toCString();
01049         if (set->contains("dataSource"))
01050             dataSource = (*set)["dataSource"].value().toCString();
01051 
01052         formPart()->dataSourcePage()->setDataSource(dataSourceMimeType, dataSource);
01053     }
01054 }
01055 
01056 void
01057 KexiFormView::slotHandleDragMoveEvent(QDragMoveEvent* e)
01058 {
01059     if (KexiFieldDrag::canDecodeMultiple( e )) {
01060         e->accept(true);
01061         //dirty:    drawRect(QRect( e->pos(), QSize(50, 20)), 2);
01062     }
01063 }
01064 
01065 void
01066 KexiFormView::slotHandleDropEvent(QDropEvent* e)
01067 {
01068     const QWidget *targetContainerWidget = dynamic_cast<const QWidget*>(sender());
01069     KFormDesigner::ObjectTreeItem *targetContainerWidgetItem = targetContainerWidget 
01070         ? form()->objectTree()->lookup( targetContainerWidget->name() ) : 0; 
01071     if (targetContainerWidgetItem && targetContainerWidgetItem->container() 
01072         && KexiFieldDrag::canDecodeMultiple( e ))
01073     {
01074         QString sourceMimeType, sourceName;
01075         QStringList fields;
01076         if (!KexiFieldDrag::decodeMultiple( e, sourceMimeType, sourceName, fields ))
01077             return;
01078         insertAutoFields(sourceMimeType, sourceName, fields, 
01079             targetContainerWidgetItem->container(), e->pos());
01080     }
01081 }
01082 
01083 void
01084 KexiFormView::insertAutoFields(const QString& sourceMimeType, const QString& sourceName,
01085     const QStringList& fields, KFormDesigner::Container* targetContainer, const QPoint& _pos)
01086 {
01087     if (fields.isEmpty())
01088         return;
01089 
01090     KexiDB::Connection *conn = parentDialog()->mainWin()->project()->dbConnection();
01091     KexiDB::TableOrQuerySchema tableOrQuery(conn, sourceName.latin1(), sourceMimeType=="kexi/table");
01092     if (!tableOrQuery.table() && !tableOrQuery.query()) {
01093         kexipluginswarn << "KexiFormView::insertAutoFields(): no such table/query \""
01094             << sourceName << "\"" << endl;
01095         return;
01096     }
01097 
01098     QPoint pos(_pos);
01099     //if pos is not specified, compute a new position:
01100     if (pos==QPoint(-1,-1)) {
01101         if (m_widgetGeometryForRecentInsertAutoFields.isValid()) {
01102             pos = m_widgetGeometryForRecentInsertAutoFields.bottomLeft() 
01103                 + QPoint(0,form()->gridSize());
01104         }
01105         else {
01106             pos = QPoint(40, 40); //start here
01107         }
01108     }
01109 
01110     // there will be many actions performed, do not update property pane until all that's finished
01111     KFormDesigner::FormManager::self()->blockPropertyEditorUpdating(this);
01112 
01114 
01115 //      KFormDesigner::WidgetList* prevSelection = form()->selectedWidgets();
01116     KFormDesigner::WidgetList widgetsToSelect;
01117     KFormDesigner::CommandGroup *group = new KFormDesigner::CommandGroup(
01118         fields.count()==1 ? i18n("Insert AutoField widget") : i18n("Insert %1 AutoField widgets").arg(fields.count()),
01119         KFormDesigner::FormManager::self()->propertySet()
01120     );
01121     
01122     foreach( QStringList::ConstIterator, it, fields ) {
01123         KexiDB::QueryColumnInfo* column = tableOrQuery.columnInfo(*it);
01124         if (!column) {
01125             kexipluginswarn << "KexiFormView::insertAutoFields(): no such field \""
01126                 << *it << "\" in table/query \"" << sourceName << "\"" << endl;
01127             continue;
01128         }
01130         //KFormDesigner::Container *targetContainer;
01131 /*      QWidget* targetContainerWidget = QApplication::widgetAt(pos, true);
01132         while (targetContainerWidget 
01133             && !dynamic_cast<KFormDesigner::Container*>(targetContainerWidget))
01134         {
01135             targetContainerWidget = targetContainerWidget->parentWidget();
01136         }
01137         if (dynamic_cast<KFormDesigner::Container*>(targetContainerWidget))
01138             targetContainer = dynamic_cast<KFormDesigner::Container*>(targetContainerWidget);
01139         else
01140             targetContainer = form()->toplevelContainer();*/
01141         KFormDesigner::InsertWidgetCommand *insertCmd
01142             = new KFormDesigner::InsertWidgetCommand(targetContainer,
01144                 "KexiDBAutoField",
01146             pos, column->aliasOrName()
01147         );
01148         insertCmd->execute();
01149         group->addCommand(insertCmd, false/*don't exec twice*/);
01150 
01151         KFormDesigner::ObjectTreeItem *newWidgetItem 
01152             = form()->objectTree()->dict()->find(insertCmd->widgetName());
01153         KexiDBAutoField* newWidget 
01154             = newWidgetItem ? dynamic_cast<KexiDBAutoField*>(newWidgetItem->widget()) : 0;
01155         widgetsToSelect.append(newWidget);
01156 //#if 0
01157         KFormDesigner::CommandGroup *subGroup 
01158             = new KFormDesigner::CommandGroup("", KFormDesigner::FormManager::self()->propertySet());
01159         QMap<QCString, QVariant> propValues;
01160         propValues.insert("dataSource", column->aliasOrName());
01161         propValues.insert("fieldTypeInternal", (int)column->field->type());
01162         propValues.insert("fieldCaptionInternal", column->captionOrAliasOrName());
01163         KFormDesigner::FormManager::self()->propertySet()->createPropertyCommandsInDesignMode(
01164             newWidget, propValues, subGroup, false, 
01165             true );
01166         subGroup->execute();
01167         group->addCommand( subGroup, false/*will not be executed on CommandGroup::execute()*/ );
01168 
01169 //#endif
01170         //set data source and caption
01171         //-we don't need to use PropertyCommand here beacause we don't need UNDO 
01172         // for these single commands
01173 //      newWidget->setDataSource(column->aliasOrName());
01174 //      newWidget->setFieldTypeInternal((int)column->field->type());
01175 //      newWidget->setFieldCaptionInternal(column->captionOrAliasOrName());
01176         //resize again because autofield's type changed what can lead to changed sizeHint() 
01177 //      newWidget->resize(newWidget->sizeHint());
01178         KFormDesigner::WidgetList list;
01179         list.append(newWidget);
01180         KFormDesigner::AdjustSizeCommand *adjustCommand 
01181             =   new KFormDesigner::AdjustSizeCommand(KFormDesigner::AdjustSizeCommand::SizeToFit,
01182                 list, form());
01183         adjustCommand->execute();
01184         group->addCommand( adjustCommand,
01185             false/*will not be executed on CommandGroup::execute()*/
01186         );
01187 
01188         if (newWidget) {//move position down for next widget
01189             pos.setY( pos.y() + newWidget->height() + form()->gridSize());
01190         }
01191     }
01192     if (widgetsToSelect.last()) {
01193         //resize form if needed
01194         QRect oldFormRect( m_dbform->geometry() );
01195         QRect newFormRect( oldFormRect );
01196         newFormRect.setWidth(QMAX(m_dbform->width(), widgetsToSelect.last()->geometry().right()+1));
01197         newFormRect.setHeight(QMAX(m_dbform->height(), widgetsToSelect.last()->geometry().bottom()+1));
01198         if (newFormRect != oldFormRect) {
01199             //1. resize by hand
01200             m_dbform->setGeometry( newFormRect );
01201             //2. store information about resize
01202             KFormDesigner::PropertyCommand *resizeFormCommand = new KFormDesigner::PropertyCommand(
01203                 KFormDesigner::FormManager::self()->propertySet(), m_dbform->name(),
01204                 oldFormRect, newFormRect, "geometry"); 
01205             group->addCommand(resizeFormCommand, true/*will be executed on CommandGroup::execute()*/);
01206         }
01207 
01208         //remember geometry of the last inserted widget
01209         m_widgetGeometryForRecentInsertAutoFields = widgetsToSelect.last()->geometry();
01210     }
01211 
01212     //eventually, add entire command group to active form
01213     form()->addCommand( group, true/*exec*/ );
01214 
01215 //  group->debug();
01216 
01217     //enable proper REDO usage
01218     group->resetAllowExecuteFlags();
01219 
01220     m_scrollView->repaint();
01221     m_scrollView->viewport()->repaint();
01222     m_scrollView->repaintContents();
01223     m_scrollView->updateContents();
01224     m_scrollView->clipper()->repaint();
01225     m_scrollView->refreshContentsSize();
01226 
01227     //select all inserted widgets, if multiple
01228     if (widgetsToSelect.count()>1) {
01229         form()->setSelectedWidget(0);
01230         foreach_list (KFormDesigner::WidgetListIterator, it, widgetsToSelect)
01231             form()->setSelectedWidget(it.current(), true/*add*/, true/*dontRaise*/);
01232     }
01233 
01234     // eventually, update property pane
01235     KFormDesigner::FormManager::self()->unblockPropertyEditorUpdating(this, KFormDesigner::FormManager::self()->propertySet());
01236 }
01237 
01238 void
01239 KexiFormView::setUnsavedLocalBLOB(QWidget *widget, KexiBLOBBuffer::Id_t id)
01240 {
01242     if (id==0) 
01243         tempData()->unsavedLocalBLOBs.remove(widget);
01244     else
01245         tempData()->unsavedLocalBLOBs.insert(widget, id);
01246 }
01247 
01248 /*
01249 todo
01250 void KexiFormView::updateActions(bool activated)
01251 {
01252     if (viewMode()==Kexi::DesignViewMode) {
01253         if (form()->selectedWidget()) {
01254             if (form()->widget() == form()->selectedWidget())
01255                 KFormDesigner::FormManager::self()->emitFormWidgetSelected( form() );
01256             else
01257                 KFormDesigner::FormManager::self()->emitWidgetSelected( form(), false );
01258         }
01259         else if (form()->selectedWidgets()) {
01260             KFormDesigner::FormManager::self()->emitWidgetSelected( form(), true );
01261         }
01262     }
01263     KexiDataAwareView::updateActions(activated);
01264 }*/
01265 
01266 /*
01267 void KexiFormView::parentDialogDetached()
01268 {
01269     m_dbform->updateTabStopsOrder(form());
01270 }
01271 
01272 void KexiFormView::parentDialogAttached(KMdiChildFrm *)
01273 {
01274     m_dbform->updateTabStopsOrder(form());
01275 }*/
01276 
01277 #include "kexiformview.moc"
01278 
KDE Home | KDE Accessibility Home | Description of Access Keys