QGIS API Documentation  master-59fd5e0
src/gui/qgsattributeeditor.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                          qgsattributeeditor.cpp  -  description
00003                              -------------------
00004     begin                : July 2009
00005     copyright            : (C) 2009 by Jürgen E. Fischer
00006     email                : jef@norbit.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "qgsattributeeditor.h"
00019 #include <qgsvectorlayer.h>
00020 #include <qgsvectordataprovider.h>
00021 #include <qgscategorizedsymbolrendererv2.h>
00022 #include <qgslonglongvalidator.h>
00023 #include <qgsfieldvalidator.h>
00024 #include <qgsmaplayerregistry.h>
00025 #include <qgslogger.h>
00026 #include <qgsexpression.h>
00027 #include <qgsfilterlineedit.h>
00028 #include <qgscolorbutton.h>
00029 #include <qgsnetworkaccessmanager.h>
00030 
00031 #include <QScrollArea>
00032 #include <QPushButton>
00033 #include <QLineEdit>
00034 #include <QTextEdit>
00035 #include <QFileDialog>
00036 #include <QComboBox>
00037 #include <QListWidget>
00038 #include <QCheckBox>
00039 #include <QSpinBox>
00040 #include <QCompleter>
00041 #include <QHBoxLayout>
00042 #include <QPlainTextEdit>
00043 #include <QDial>
00044 #include <QCalendarWidget>
00045 #include <QDialogButtonBox>
00046 #include <QSettings>
00047 #include <QDir>
00048 #include <QUuid>
00049 #include <QGroupBox>
00050 #include <QLabel>
00051 #include <QWebView>
00052 #include <QDesktopServices>
00053 
00054 void QgsAttributeEditor::selectFileName()
00055 {
00056   QPushButton *pb = qobject_cast<QPushButton *>( sender() );
00057   if ( !pb )
00058     return;
00059 
00060   QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
00061   if ( !hbox )
00062     return;
00063 
00064   QLineEdit *le = hbox->findChild<QLineEdit *>();
00065   if ( !le )
00066     return;
00067 
00068   QString fileName = QFileDialog::getOpenFileName( 0 , tr( "Select a file" ), QFileInfo( le->text() ).absolutePath() );
00069   if ( fileName.isNull() )
00070     return;
00071 
00072   le->setText( QDir::toNativeSeparators( fileName ) );
00073 }
00074 
00075 void QgsAttributeEditor::selectDate()
00076 {
00077   QPushButton *pb = qobject_cast<QPushButton *>( sender() );
00078   if ( !pb )
00079     return;
00080 
00081   QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
00082   if ( !hbox )
00083     return;
00084 
00085   QLineEdit *le = hbox->findChild<QLineEdit *>();
00086   if ( !le )
00087     return;
00088 
00089   QDialog *dlg = new QDialog();
00090   dlg->setWindowTitle( tr( "Select a date" ) );
00091   QVBoxLayout *vl = new QVBoxLayout( dlg );
00092 
00093   const QgsFieldValidator *v = dynamic_cast<const QgsFieldValidator *>( le->validator() );
00094   QString dateFormat = v ? v->dateFormat() : "yyyy-MM-dd";
00095 
00096   QCalendarWidget *cw = new QCalendarWidget( dlg );
00097   QString prevValue = le->text();
00098   cw->setSelectedDate( QDate::fromString( prevValue, dateFormat ) );
00099   vl->addWidget( cw );
00100 
00101   QDialogButtonBox *buttonBox = new QDialogButtonBox( dlg );
00102   buttonBox->addButton( QDialogButtonBox::Ok );
00103   buttonBox->addButton( QDialogButtonBox::Cancel );
00104   vl->addWidget( buttonBox );
00105 
00106   connect( buttonBox, SIGNAL( accepted() ), dlg, SLOT( accept() ) );
00107   connect( buttonBox, SIGNAL( rejected() ), dlg, SLOT( reject() ) );
00108 
00109   if ( dlg->exec() == QDialog::Accepted )
00110   {
00111     QString newValue = cw->selectedDate().toString( dateFormat );
00112     le->setText( newValue );
00113     le->setModified( newValue != prevValue );
00114   }
00115 }
00116 
00117 void QgsAttributeEditor::loadUrl( const QString &url )
00118 {
00119   QLineEdit *le = qobject_cast<QLineEdit *>( sender() );
00120   if ( !le )
00121     return;
00122 
00123   QWidget *hbox = qobject_cast<QWidget *>( le->parent() );
00124   if ( !hbox )
00125     return;
00126 
00127   QWebView *ww = hbox->findChild<QWebView *>();
00128   if ( !ww )
00129     return;
00130 
00131   ww->load( url );
00132 }
00133 
00134 void QgsAttributeEditor::loadPixmap( const QString &name )
00135 {
00136   QLineEdit *le = qobject_cast<QLineEdit *>( sender() );
00137   if ( !le )
00138     return;
00139 
00140   QWidget *hbox = qobject_cast<QWidget *>( le->parent() );
00141   if ( !hbox )
00142     return;
00143 
00144   QLabel *lw = hbox->findChild<QLabel *>();
00145   if ( !lw )
00146     return;
00147 
00148   QPixmap pm( name );
00149   if ( pm.isNull() )
00150     return;
00151 
00152   QSize size( mLayer->widgetSize( mIdx ) );
00153   if ( size.width() == 0 && size.height() > 0 )
00154   {
00155     size.setWidth( size.height() * pm.size().width() / pm.size().height() );
00156   }
00157   else if ( size.width() > 0 && size.height() == 0 )
00158   {
00159     size.setHeight( size.width() * pm.size().height() / pm.size().width() );
00160   }
00161 
00162   pm = pm.scaled( size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
00163 
00164   lw->setPixmap( pm );
00165   lw->setMinimumSize( size );
00166 }
00167 
00168 void QgsAttributeEditor::updateUrl()
00169 {
00170   QPushButton *pb = qobject_cast<QPushButton *>( sender() );
00171   if ( !pb )
00172     return;
00173 
00174   QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
00175   if ( !hbox )
00176     return;
00177 
00178   QWebView *ww = hbox->findChild<QWebView *>();
00179   if ( !ww )
00180     return;
00181 
00182   QLineEdit *le = hbox->findChild<QLineEdit *>();
00183   if ( !le )
00184     return;
00185 
00186   le->blockSignals( true );
00187   le->setText( ww->url().toString() );
00188   le->blockSignals( false );
00189 }
00190 
00191 void QgsAttributeEditor::openUrl()
00192 {
00193   QPushButton *pb = qobject_cast<QPushButton *>( sender() );
00194   if ( !pb )
00195     return;
00196 
00197   QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
00198   if ( !hbox )
00199     return;
00200 
00201   QWebView *ww = hbox->findChild<QWebView *>();
00202   if ( !ww )
00203     return;
00204 
00205   QDesktopServices::openUrl( ww->url().toString() );
00206 }
00207 
00208 void QgsAttributeEditor::updateColor()
00209 {
00210   QString color;
00211   QgsColorButton *scb = qobject_cast<QgsColorButton *>( sender() );
00212   QLineEdit *sle = qobject_cast<QLineEdit *>( sender() );
00213 
00214   if ( !scb && !sle )
00215     return;
00216 
00217   QWidget *hbox = qobject_cast<QWidget *>( sender()->parent() );
00218   if ( !hbox )
00219     return;
00220 
00221   QgsColorButton *cb = hbox->findChild<QgsColorButton *>();
00222   if ( !cb )
00223     return;
00224 
00225   QLineEdit *le = hbox->findChild<QLineEdit *>();
00226   if ( !le )
00227     return;
00228 
00229   if ( scb )
00230   {
00231     le->blockSignals( true );
00232     le->setText( scb->color().name() );
00233     le->blockSignals( false );
00234   }
00235 
00236   if ( sle )
00237   {
00238     cb->blockSignals( true );
00239     cb->setColor( QColor( sle->text() ) );
00240     cb->blockSignals( false );
00241   }
00242 }
00243 
00244 QComboBox *QgsAttributeEditor::comboBox( QWidget *editor, QWidget *parent )
00245 {
00246   QComboBox *cb = 0;
00247   if ( editor )
00248     cb = qobject_cast<QComboBox *>( editor );
00249   else
00250     cb = new QComboBox( parent );
00251 
00252   return cb;
00253 }
00254 
00255 QListWidget *QgsAttributeEditor::listWidget( QWidget *editor, QWidget *parent )
00256 {
00257   QListWidget *lw = 0;
00258   if ( editor )
00259     lw = qobject_cast<QListWidget *>( editor );
00260   else
00261     lw = new QListWidget( parent );
00262 
00263   return lw;
00264 }
00265 
00266 QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
00267 {
00268   QMap<int, QWidget*> dummyProxyWidgets;
00269   return createAttributeEditor( parent, editor, vl, idx, value, dummyProxyWidgets );
00270 }
00271 
00272 QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value, QMap<int, QWidget*> &proxyWidgets )
00273 {
00274   if ( !vl )
00275     return 0;
00276 
00277   QWidget *myWidget = 0;
00278   QgsVectorLayer::EditType editType = vl->editType( idx );
00279   const QgsField &field = vl->pendingFields()[idx];
00280   QVariant::Type myFieldType = field.type();
00281 
00282   bool synchronized = false;
00283 
00284   switch ( editType )
00285   {
00286     case QgsVectorLayer::UniqueValues:
00287     {
00288       QList<QVariant> values;
00289       vl->dataProvider()->uniqueValues( idx, values );
00290 
00291       QComboBox *cb = comboBox( editor, parent );
00292       if ( cb )
00293       {
00294         cb->setEditable( false );
00295 
00296         for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); it++ )
00297           cb->addItem( it->toString(), it->toString() );
00298 
00299         myWidget = cb;
00300       }
00301 
00302     }
00303     break;
00304 
00305     case QgsVectorLayer::Enumeration:
00306     {
00307       QStringList enumValues;
00308       vl->dataProvider()->enumValues( idx, enumValues );
00309 
00310       QComboBox *cb = comboBox( editor, parent );
00311       if ( cb )
00312       {
00313         QStringList::const_iterator s_it = enumValues.constBegin();
00314         for ( ; s_it != enumValues.constEnd(); ++s_it )
00315         {
00316           cb->addItem( *s_it, *s_it );
00317         }
00318 
00319         myWidget = cb;
00320       }
00321     }
00322     break;
00323 
00324     case QgsVectorLayer::ValueMap:
00325     {
00326       const QMap<QString, QVariant> &map = vl->valueMap( idx );
00327 
00328       QComboBox *cb = comboBox( editor, parent );
00329       if ( cb )
00330       {
00331         for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); it++ )
00332         {
00333           cb->addItem( it.key(), it.value() );
00334         }
00335 
00336         myWidget = cb;
00337       }
00338     }
00339     break;
00340 
00341     case QgsVectorLayer::ValueRelation:
00342     {
00343       const QgsVectorLayer::ValueRelationData &data = vl->valueRelation( idx );
00344 
00345       QgsVectorLayer *layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( data.mLayer ) );
00346       QMap< QString, QString > map;
00347 
00348       if ( layer )
00349       {
00350         int ki = layer->fieldNameIndex( data.mOrderByValue ? data.mValue : data.mKey );
00351         int vi = layer->fieldNameIndex( data.mOrderByValue ? data.mKey : data.mValue );
00352 
00353         QgsExpression *e = 0;
00354         if ( !data.mFilterExpression.isEmpty() )
00355         {
00356           e = new QgsExpression( data.mFilterExpression );
00357           if ( e->hasParserError() || !e->prepare( layer->pendingFields() ) )
00358             ki = -1;
00359         }
00360 
00361         if ( ki >= 0 && vi >= 0 )
00362         {
00363           QSet<int> attributes;
00364           attributes << ki << vi;
00365 
00366           QgsFeatureRequest::Flag flags = QgsFeatureRequest::NoGeometry;
00367 
00368           if ( e )
00369           {
00370             if ( e->needsGeometry() )
00371               flags = QgsFeatureRequest::NoFlags;
00372 
00373             foreach ( const QString &field, e->referencedColumns() )
00374             {
00375               int idx = layer->fieldNameIndex( field );
00376               if ( idx < 0 )
00377                 continue;
00378               attributes << idx;
00379             }
00380           }
00381 
00382           QgsFeatureIterator fit = layer->getFeatures( QgsFeatureRequest().setFlags( flags ).setSubsetOfAttributes( attributes.toList() ) );
00383           QgsFeature f;
00384           while ( fit.nextFeature( f ) )
00385           {
00386             if ( e && !e->evaluate( &f ).toBool() )
00387               continue;
00388 
00389             map.insert( f.attribute( ki ).toString(), f.attribute( vi ).toString() );
00390           }
00391         }
00392       }
00393 
00394       if ( !data.mAllowMulti )
00395       {
00396         QComboBox *cb = comboBox( editor, parent );
00397         if ( cb )
00398         {
00399           if ( data.mAllowNull )
00400           {
00401             QSettings settings;
00402             cb->addItem( tr( "(no selection)" ), settings.value( "qgis/nullValue", "NULL" ).toString() );
00403           }
00404 
00405           for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); it++ )
00406           {
00407             if ( data.mOrderByValue )
00408               cb->addItem( it.key(), it.value() );
00409             else
00410               cb->addItem( it.value(), it.key() );
00411           }
00412 
00413           myWidget = cb;
00414         }
00415       }
00416       else
00417       {
00418         QListWidget *lw = listWidget( editor, parent );
00419         if ( lw )
00420         {
00421           QStringList checkList = value.toString().remove( QChar( '{' ) ).remove( QChar( '}' ) ).split( "," );
00422 
00423           for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); it++ )
00424           {
00425             QListWidgetItem *item;
00426             if ( data.mOrderByValue )
00427             {
00428               item = new QListWidgetItem( it.key() );
00429               item->setData( Qt::UserRole, it.value() );
00430               item->setCheckState( checkList.contains( it.value() ) ? Qt::Checked : Qt::Unchecked );
00431             }
00432             else
00433             {
00434               item = new QListWidgetItem( it.value() );
00435               item->setData( Qt::UserRole, it.key() );
00436               item->setCheckState( checkList.contains( it.key() ) ? Qt::Checked : Qt::Unchecked );
00437             }
00438             lw->addItem( item );
00439           }
00440 
00441           myWidget = lw;
00442         }
00443       }
00444     }
00445     break;
00446 
00447     case QgsVectorLayer::Classification:
00448     {
00449       QMap<QString, QString> classes;
00450 
00451       const QgsCategorizedSymbolRendererV2 *csr = dynamic_cast<const QgsCategorizedSymbolRendererV2 *>( vl->rendererV2() );
00452       if ( csr )
00453       {
00454         const QgsCategoryList &categories = (( QgsCategorizedSymbolRendererV2 * )csr )->categories(); // FIXME: QgsCategorizedSymbolRendererV2::categories() should be const
00455         for ( int i = 0; i < categories.size(); i++ )
00456         {
00457           QString label = categories[i].label();
00458           QString value = categories[i].value().toString();
00459           if ( label.isEmpty() )
00460             label = value;
00461           classes.insert( value, label );
00462         }
00463       }
00464 
00465       QComboBox *cb = comboBox( editor, parent );
00466       if ( cb )
00467       {
00468         for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); it++ )
00469         {
00470           cb->addItem( it.value(), it.key() );
00471         }
00472 
00473         myWidget = cb;
00474       }
00475     }
00476     break;
00477 
00478     case QgsVectorLayer::DialRange:
00479     case QgsVectorLayer::SliderRange:
00480     case QgsVectorLayer::EditRange:
00481     {
00482       if ( myFieldType == QVariant::Int )
00483       {
00484         int min = vl->range( idx ).mMin.toInt();
00485         int max = vl->range( idx ).mMax.toInt();
00486         int step = vl->range( idx ).mStep.toInt();
00487 
00488         if ( editType == QgsVectorLayer::EditRange )
00489         {
00490           QSpinBox *sb = 0;
00491 
00492           if ( editor )
00493             sb = qobject_cast<QSpinBox *>( editor );
00494           else
00495             sb = new QSpinBox( parent );
00496 
00497           if ( sb )
00498           {
00499             sb->setRange( min, max );
00500             sb->setSingleStep( step );
00501 
00502             myWidget = sb;
00503           }
00504         }
00505         else
00506         {
00507           QAbstractSlider *sl = 0;
00508 
00509           if ( editor )
00510           {
00511             sl = qobject_cast<QAbstractSlider*>( editor );
00512           }
00513           else if ( editType == QgsVectorLayer::DialRange )
00514           {
00515             sl = new QDial( parent );
00516           }
00517           else
00518           {
00519             sl = new QSlider( Qt::Horizontal, parent );
00520           }
00521 
00522           if ( sl )
00523           {
00524             sl->setRange( min, max );
00525             sl->setSingleStep( step );
00526 
00527             myWidget = sl;
00528           }
00529         }
00530         break;
00531       }
00532       else if ( myFieldType == QVariant::Double )
00533       {
00534         QDoubleSpinBox *dsb = 0;
00535         if ( editor )
00536           dsb = qobject_cast<QDoubleSpinBox*>( editor );
00537         else
00538           dsb = new QDoubleSpinBox( parent );
00539 
00540         if ( dsb )
00541         {
00542           double min = vl->range( idx ).mMin.toDouble();
00543           double max = vl->range( idx ).mMax.toDouble();
00544           double step = vl->range( idx ).mStep.toDouble();
00545 
00546           dsb->setRange( min, max );
00547           dsb->setSingleStep( step );
00548 
00549           myWidget = dsb;
00550         }
00551         break;
00552       }
00553     }
00554 
00555     case QgsVectorLayer::CheckBox:
00556     {
00557       QCheckBox *cb = 0;
00558       QGroupBox *gb = 0;
00559       if ( editor )
00560       {
00561         gb = qobject_cast<QGroupBox *>( editor );
00562         cb = qobject_cast<QCheckBox*>( editor );
00563       }
00564       else
00565         cb = new QCheckBox( parent );
00566 
00567       if ( cb )
00568       {
00569         myWidget = cb;
00570         break;
00571       }
00572       else if ( gb )
00573       {
00574         myWidget = gb;
00575         break;
00576       }
00577     }
00578 
00579     // fall-through
00580 
00581     case QgsVectorLayer::LineEdit:
00582     case QgsVectorLayer::TextEdit:
00583     case QgsVectorLayer::UuidGenerator:
00584     case QgsVectorLayer::UniqueValuesEditable:
00585     case QgsVectorLayer::Immutable:
00586     {
00587       QLineEdit *le = 0;
00588       QTextEdit *te = 0;
00589       QPlainTextEdit *pte = 0;
00590       QComboBox * cb = 0;
00591 
00592       if ( editor )
00593       {
00594         le = qobject_cast<QLineEdit *>( editor );
00595         te = qobject_cast<QTextEdit *>( editor );
00596         pte = qobject_cast<QPlainTextEdit *>( editor );
00597         cb = qobject_cast<QComboBox *>( editor );
00598       }
00599       else if ( editType == QgsVectorLayer::TextEdit )
00600       {
00601         pte = new QPlainTextEdit( parent );
00602       }
00603       else
00604       {
00605         le = new QgsFilterLineEdit( parent );
00606       }
00607 
00608       if ( le )
00609       {
00610         if ( editType == QgsVectorLayer::UniqueValuesEditable )
00611         {
00612           QList<QVariant> values;
00613           vl->dataProvider()->uniqueValues( idx, values );
00614 
00615           QStringList svalues;
00616           for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); it++ )
00617             svalues << it->toString();
00618 
00619           QCompleter *c = new QCompleter( svalues );
00620           c->setCompletionMode( QCompleter::PopupCompletion );
00621           le->setCompleter( c );
00622         }
00623 
00624         if ( editType == QgsVectorLayer::UuidGenerator )
00625         {
00626           le->setReadOnly( true );
00627         }
00628 
00629         le->setValidator( new QgsFieldValidator( le, field, vl->dateFormat( idx ) ) );
00630 
00631         myWidget = le;
00632       }
00633 
00634       if ( te )
00635       {
00636         te->setAcceptRichText( true );
00637         myWidget = te;
00638       }
00639 
00640       if ( pte )
00641       {
00642         myWidget = pte;
00643       }
00644 
00645       if ( cb )
00646       {
00647         if ( cb->isEditable() )
00648           cb->setValidator( new QgsFieldValidator( cb, field, vl->dateFormat( idx ) ) );
00649         myWidget = cb;
00650       }
00651 
00652       if ( myWidget )
00653       {
00654         if ( editType == QgsVectorLayer::Immutable )
00655         {
00656           myWidget->setDisabled( true );
00657         }
00658 
00659         QgsStringRelay* relay = NULL;
00660 
00661         QMap<int, QWidget*>::const_iterator it = proxyWidgets.find( idx );
00662         if ( it != proxyWidgets.end() )
00663         {
00664           QObject* obj = qvariant_cast<QObject*>(( *it )->property( "QgisAttrEditProxy" ) );
00665           relay = qobject_cast<QgsStringRelay*>( obj );
00666         }
00667         else
00668         {
00669           relay = new QgsStringRelay( myWidget );
00670         }
00671 
00672         const char* rSlot = SLOT( changeText( QString ) );
00673         const char* rSig = SIGNAL( textChanged( QString ) );
00674         const char* wSlot = SLOT( setText( QString ) );
00675         const char* wSig = SIGNAL( textChanged( QString ) );
00676         if ( te || pte )
00677         {
00678           rSlot = SLOT( changeText() );
00679           wSig = SIGNAL( textChanged() );
00680         }
00681         if ( pte )
00682         {
00683           wSlot = SLOT( setPlainText( QString ) );
00684         }
00685         if ( cb && cb->isEditable() )
00686         {
00687           wSlot = SLOT( setEditText( QString ) );
00688           wSig = SIGNAL( editTextChanged( QString ) );
00689         }
00690 
00691         synchronized =  connect( relay, rSig, myWidget, wSlot );
00692         synchronized &= connect( myWidget, wSig, relay, rSlot );
00693 
00694         // store list of proxies in relay
00695         relay->appendProxy( myWidget );
00696 
00697         if ( !cb || cb->isEditable() )
00698         {
00699           myWidget->setProperty( "QgisAttrEditSlot", QVariant( QByteArray( wSlot ) ) );
00700           myWidget->setProperty( "QgisAttrEditProxy", QVariant( QMetaType::QObjectStar, &relay ) );
00701         }
00702       }
00703     }
00704     break;
00705 
00706     case QgsVectorLayer::Hidden:
00707       myWidget = 0;
00708       break;
00709 
00710     case QgsVectorLayer::FileName:
00711     case QgsVectorLayer::Calendar:
00712     case QgsVectorLayer::Photo:
00713     case QgsVectorLayer::WebView:
00714     case QgsVectorLayer::Color:
00715     {
00716       QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( editor );
00717       if ( cw )
00718       {
00719         myWidget = cw;
00720         break;
00721       }
00722 
00723       QWebView *ww = qobject_cast<QWebView *>( editor );
00724       if ( ww )
00725       {
00726         ww->page()->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
00727         // ww->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
00728         ww->settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
00729         ww->settings()->setAttribute( QWebSettings::JavascriptCanOpenWindows, true );
00730 #ifdef QGISDEBUG
00731         ww->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
00732 #endif
00733 
00734         QSize size( vl->widgetSize( idx ) );
00735         if ( size.width() > 0 || size.height() > 0 )
00736         {
00737           if ( size.width() == 0 )
00738             size.setWidth( 1 );
00739           if ( size.height() == 0 )
00740             size.setHeight( 1 );
00741           ww->setMinimumSize( size );
00742         }
00743 
00744         myWidget = ww;
00745         break;
00746       }
00747 
00748       QLabel *lw = qobject_cast<QLabel *>( editor );
00749       if ( lw )
00750       {
00751         myWidget = lw;
00752         break;
00753       }
00754 
00755       QgsColorButton *cb = qobject_cast<QgsColorButton *>( editor );
00756       if ( cb )
00757       {
00758         myWidget = cb;
00759         break;
00760       }
00761 
00762       QPushButton *pb0 = 0;
00763       QPushButton *pb1 = 0;
00764       QLineEdit *le = qobject_cast<QLineEdit *>( editor );
00765       if ( le )
00766       {
00767         if ( le )
00768           myWidget = le;
00769 
00770         if ( editor->parent() )
00771         {
00772           pb0 = editor->parent()->findChild<QPushButton *>();
00773         }
00774       }
00775       else
00776       {
00777         myWidget = new QWidget( parent );
00778         myWidget->setBackgroundRole( QPalette::Window );
00779         myWidget->setAutoFillBackground( true );
00780 
00781         le = new QgsFilterLineEdit( myWidget );
00782         switch ( editType )
00783         {
00784           case QgsVectorLayer::FileName:
00785           case QgsVectorLayer::Photo:
00786           case QgsVectorLayer::Calendar:
00787             pb0 = new QPushButton( tr( "..." ), myWidget );
00788             break;
00789 
00790           case QgsVectorLayer::WebView:
00791             pb0 = new QPushButton( tr( "<" ), myWidget );
00792             pb0->setObjectName( "saveUrl" );
00793             pb1 = new QPushButton( tr( "..." ), myWidget );
00794             pb1->setObjectName( "openUrl" );
00795             break;
00796 
00797           case QgsVectorLayer::Color:
00798             pb0 = new QgsColorButton( myWidget );
00799             break;
00800 
00801           default:
00802             break;
00803         }
00804 
00805 
00806         int row = 0;
00807         QGridLayout *layout = new QGridLayout( myWidget );
00808         if ( editType == QgsVectorLayer::Photo )
00809         {
00810           lw = new QLabel( myWidget );
00811           layout->addWidget( lw, 0, 0, 1, 2 );
00812           row++;
00813         }
00814         else if ( editType == QgsVectorLayer::WebView )
00815         {
00816           ww = new QWebView( myWidget );
00817           ww->setObjectName( "webview" );
00818           ww->page()->setNetworkAccessManager( QgsNetworkAccessManager::instance() );
00819           // ww->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
00820           ww->settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
00821           ww->settings()->setAttribute( QWebSettings::JavascriptCanOpenWindows, true );
00822 #ifdef QGISDEBUG
00823           ww->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
00824 #endif
00825 
00826           QSize size( vl->widgetSize( idx ) );
00827           if ( size.width() > 0 || size.height() > 0 )
00828           {
00829             if ( size.width() == 0 )
00830               size.setWidth( 1 );
00831             if ( size.height() == 0 )
00832               size.setHeight( 1 );
00833             ww->setMinimumSize( size );
00834           }
00835 
00836           layout->addWidget( ww, 0, 0, 1, 2 );
00837           row++;
00838         }
00839 
00840         layout->addWidget( le, row, 0 );
00841         layout->addWidget( pb0, row, 1 );
00842         if ( pb1 )
00843           layout->addWidget( pb1, row, 2 );
00844 
00845         myWidget->setLayout( layout );
00846       }
00847 
00848       if ( le )
00849       {
00850         le->setValidator( new QgsFieldValidator( le, field, vl->dateFormat( idx ) ) );
00851 
00852         if ( ww )
00853           connect( le, SIGNAL( textChanged( const QString & ) ), new QgsAttributeEditor( le, vl, idx ), SLOT( loadUrl( const QString & ) ) );
00854         if ( lw )
00855           connect( le, SIGNAL( textChanged( const QString & ) ), new QgsAttributeEditor( le, vl, idx ), SLOT( loadPixmap( const QString & ) ) );
00856         if ( editType == QgsVectorLayer::Color )
00857           connect( le, SIGNAL( textChanged( const QString & ) ), new QgsAttributeEditor( le ), SLOT( updateColor() ) );
00858       }
00859 
00860       if ( pb0 )
00861       {
00862         if ( editType == QgsVectorLayer::FileName || editType == QgsVectorLayer::Photo )
00863         {
00864           connect( pb0, SIGNAL( clicked() ), new QgsAttributeEditor( pb0 ), SLOT( selectFileName() ) );
00865           pb0->setToolTip( tr( "Select filename..." ) );
00866         }
00867         if ( editType == QgsVectorLayer::WebView )
00868         {
00869           connect( pb0, SIGNAL( clicked() ), new QgsAttributeEditor( pb0 ), SLOT( updateUrl() ) );
00870           pb0->setToolTip( tr( "Save current page url in attribute" ) );
00871         }
00872         if ( editType == QgsVectorLayer::Calendar )
00873         {
00874           connect( pb0, SIGNAL( clicked() ), new QgsAttributeEditor( pb0 ), SLOT( selectDate() ) );
00875           pb0->setToolTip( tr( "Select date in calendar" ) );
00876         }
00877         if ( editType == QgsVectorLayer::Color )
00878         {
00879           connect( pb0, SIGNAL( colorChanged( const QColor & ) ), new QgsAttributeEditor( pb0 ), SLOT( updateColor() ) );
00880           pb0->setToolTip( tr( "Select color in browser" ) );
00881         }
00882       }
00883 
00884       if ( pb1 )
00885       {
00886         if ( editType == QgsVectorLayer::WebView )
00887         {
00888           connect( pb1, SIGNAL( clicked() ), new QgsAttributeEditor( pb1 ), SLOT( openUrl() ) );
00889           pb1->setToolTip( tr( "Open current page in default browser" ) );
00890         }
00891       }
00892     }
00893     break;
00894   }
00895 
00896   QMap<int, QWidget*>::const_iterator it = proxyWidgets.find( idx );
00897   if ( it != proxyWidgets.end() )
00898   {
00899     if ( !synchronized )
00900     {
00901       myWidget->setEnabled( false );
00902     }
00903   }
00904   else
00905   {
00906     proxyWidgets.insert( idx, myWidget );
00907   }
00908 
00909   setValue( myWidget, vl, idx, value );
00910 
00911   return myWidget;
00912 }
00913 
00914 bool QgsAttributeEditor::retrieveValue( QWidget *widget, QgsVectorLayer *vl, int idx, QVariant &value )
00915 {
00916   if ( !widget )
00917     return false;
00918 
00919   const QgsField &theField = vl->pendingFields()[idx];
00920   QgsVectorLayer::EditType editType = vl->editType( idx );
00921   bool modified = false;
00922   QString text;
00923 
00924   QSettings settings;
00925   QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString();
00926 
00927   QLineEdit *le = qobject_cast<QLineEdit *>( widget );
00928   if ( le )
00929   {
00930     text = le->text();
00931     modified = le->isModified();
00932     if ( text == nullValue )
00933     {
00934       text = QString::null;
00935     }
00936   }
00937 
00938   QTextEdit *te = qobject_cast<QTextEdit *>( widget );
00939   if ( te )
00940   {
00941     text = te->toHtml();
00942     modified = te->document()->isModified();
00943     if ( text == nullValue )
00944     {
00945       text = QString::null;
00946     }
00947   }
00948 
00949   QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( widget );
00950   if ( pte )
00951   {
00952     text = pte->toPlainText();
00953     modified = pte->document()->isModified();
00954     if ( text == nullValue )
00955     {
00956       text = QString::null;
00957     }
00958   }
00959 
00960   QComboBox *cb = qobject_cast<QComboBox *>( widget );
00961   if ( cb )
00962   {
00963     if ( editType == QgsVectorLayer::UniqueValues ||
00964          editType == QgsVectorLayer::ValueMap ||
00965          editType == QgsVectorLayer::Classification ||
00966          editType == QgsVectorLayer::ValueRelation )
00967     {
00968       text = cb->itemData( cb->currentIndex() ).toString();
00969       if ( text == nullValue )
00970       {
00971         text = QString::null;
00972       }
00973     }
00974     else
00975     {
00976       text = cb->currentText();
00977     }
00978     modified = true;
00979   }
00980 
00981   QListWidget *lw = qobject_cast<QListWidget *>( widget );
00982   if ( lw )
00983   {
00984     if ( editType == QgsVectorLayer::ValueRelation )
00985     {
00986       text = '{';
00987       for ( int i = 0, n = 0; i < lw->count(); i++ )
00988       {
00989         if ( lw->item( i )->checkState() == Qt::Checked )
00990         {
00991           if ( n > 0 )
00992           {
00993             text.append( ',' );
00994           }
00995           text.append( lw->item( i )->data( Qt::UserRole ).toString() );
00996           n++;
00997         }
00998       }
00999       text.append( '}' );
01000     }
01001     else
01002     {
01003       text = QString::null;
01004     }
01005     modified = true;
01006   }
01007 
01008   QSpinBox *sb = qobject_cast<QSpinBox *>( widget );
01009   if ( sb )
01010   {
01011     text = QString::number( sb->value() );
01012   }
01013 
01014   QAbstractSlider *slider = qobject_cast<QAbstractSlider *>( widget );
01015   if ( slider )
01016   {
01017     text = QString::number( slider->value() );
01018   }
01019 
01020   QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( widget );
01021   if ( dsb )
01022   {
01023     text = QString::number( dsb->value() );
01024   }
01025 
01026   QCheckBox *ckb = qobject_cast<QCheckBox *>( widget );
01027   if ( ckb )
01028   {
01029     QPair<QString, QString> states = vl->checkedState( idx );
01030     text = ckb->isChecked() ? states.first : states.second;
01031   }
01032 
01033   QGroupBox *gb = qobject_cast<QGroupBox *>( widget );
01034   if ( gb )
01035   {
01036     QPair<QString, QString> states = vl->checkedState( idx );
01037     text = gb->isChecked() ? states.first : states.second;
01038   }
01039 
01040   QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( widget );
01041   if ( cw )
01042   {
01043     text = cw->selectedDate().toString( vl->dateFormat( idx ) );
01044   }
01045 
01046   le = widget->findChild<QLineEdit *>();
01047   // QCalendarWidget and QGroupBox have an internal QLineEdit which returns the year
01048   // part of the date so we need to skip this if we have a QCalendarWidget
01049   if ( !cw && !gb && le )
01050   {
01051     text = le->text();
01052     modified = le->isModified();
01053     if ( text == nullValue )
01054     {
01055       text = QString::null;
01056     }
01057   }
01058 
01059   switch ( theField.type() )
01060   {
01061     case QVariant::Int:
01062     {
01063       bool ok;
01064       int myIntValue = text.toInt( &ok );
01065       if ( ok && !text.isEmpty() )
01066       {
01067         value = QVariant( myIntValue );
01068         modified = true;
01069       }
01070       else if ( modified )
01071       {
01072         value = QVariant();
01073       }
01074     }
01075     break;
01076     case QVariant::LongLong:
01077     {
01078       bool ok;
01079       qlonglong myLongValue = text.toLong( &ok );
01080       if ( ok && !text.isEmpty() )
01081       {
01082         value = QVariant( myLongValue );
01083         modified = true;
01084       }
01085       else if ( modified )
01086       {
01087         value = QVariant();
01088       }
01089     }
01090     case QVariant::Double:
01091     {
01092       bool ok;
01093       double myDblValue = text.toDouble( &ok );
01094       if ( ok && !text.isEmpty() )
01095       {
01096         value = QVariant( myDblValue );
01097         modified = true;
01098       }
01099       else if ( modified )
01100       {
01101         value = QVariant();
01102       }
01103     }
01104     break;
01105     case QVariant::Date:
01106     {
01107       QDate myDateValue = QDate::fromString( text, vl->dateFormat( idx ) );
01108       if ( myDateValue.isValid() && !text.isEmpty() )
01109       {
01110         value = myDateValue;
01111         modified = true;
01112       }
01113       else if ( modified )
01114       {
01115         value = QVariant();
01116       }
01117     }
01118     break;
01119     default: //string
01120       modified = true;
01121       if ( text.isNull() )
01122         value = QVariant( theField.type() );
01123       else
01124         value = QVariant( text );
01125       break;
01126   }
01127 
01128   return modified;
01129 }
01130 
01131 bool QgsAttributeEditor::setValue( QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
01132 {
01133   if ( !editor )
01134     return false;
01135 
01136   QgsVectorLayer::EditType editType = vl->editType( idx );
01137   const QgsField &field = vl->pendingFields()[idx];
01138   QVariant::Type myFieldType = field.type();
01139 
01140   QSettings settings;
01141   QString nullValue = settings.value( "qgis/nullValue", "NULL" ).toString();
01142 
01143   switch ( editType )
01144   {
01145     case QgsVectorLayer::Classification:
01146     case QgsVectorLayer::UniqueValues:
01147     case QgsVectorLayer::Enumeration:
01148     case QgsVectorLayer::ValueMap:
01149     case QgsVectorLayer::ValueRelation:
01150     {
01151       QVariant v = value;
01152       QComboBox *cb = qobject_cast<QComboBox *>( editor );
01153       if ( !cb )
01154         return false;
01155 
01156       if ( v.isNull() )
01157       {
01158         v = nullValue;
01159       }
01160 
01161       int idx = cb->findData( v );
01162       if ( idx < 0 )
01163         return false;
01164 
01165       cb->setCurrentIndex( idx );
01166     }
01167     break;
01168 
01169     case QgsVectorLayer::DialRange:
01170     case QgsVectorLayer::SliderRange:
01171     case QgsVectorLayer::EditRange:
01172     {
01173       if ( myFieldType == QVariant::Int )
01174       {
01175         if ( editType == QgsVectorLayer::EditRange )
01176         {
01177           QSpinBox *sb = qobject_cast<QSpinBox *>( editor );
01178           if ( !sb )
01179             return false;
01180           sb->setValue( value.toInt() );
01181         }
01182         else
01183         {
01184           QAbstractSlider *sl = qobject_cast<QAbstractSlider *>( editor );
01185           if ( !sl )
01186             return false;
01187           sl->setValue( value.toInt() );
01188         }
01189         break;
01190       }
01191       else if ( myFieldType == QVariant::Double )
01192       {
01193         QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( editor );
01194         if ( !dsb )
01195           return false;
01196         dsb->setValue( value.toDouble() );
01197       }
01198     }
01199 
01200     case QgsVectorLayer::CheckBox:
01201     {
01202       QGroupBox *gb = qobject_cast<QGroupBox *>( editor );
01203       if ( gb )
01204       {
01205         QPair<QString, QString> states = vl->checkedState( idx );
01206         gb->setChecked( value == states.first );
01207         break;
01208       }
01209 
01210       QCheckBox *cb = qobject_cast<QCheckBox *>( editor );
01211       if ( cb )
01212       {
01213         QPair<QString, QString> states = vl->checkedState( idx );
01214         cb->setChecked( value == states.first );
01215         break;
01216       }
01217     }
01218 
01219     // fall-through
01220 
01221     case QgsVectorLayer::LineEdit:
01222     case QgsVectorLayer::UniqueValuesEditable:
01223     case QgsVectorLayer::Immutable:
01224     case QgsVectorLayer::UuidGenerator:
01225     case QgsVectorLayer::TextEdit:
01226     {
01227       QgsFilterLineEdit *fle = qobject_cast<QgsFilterLineEdit *>( editor );
01228       QLineEdit *le = qobject_cast<QLineEdit *>( editor );
01229       QComboBox *cb = qobject_cast<QComboBox *>( editor );
01230       QTextEdit *te = qobject_cast<QTextEdit *>( editor );
01231       QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( editor );
01232       if ( !le && ! cb && !te && !pte )
01233         return false;
01234 
01235       if ( fle && !( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date ) )
01236       {
01237         fle->setNullValue( nullValue );
01238       }
01239 
01240       QString text;
01241       if ( value.isNull() )
01242       {
01243         if ( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date )
01244           text = "";
01245         else if ( editType == QgsVectorLayer::UuidGenerator )
01246           text = QUuid::createUuid().toString();
01247         else
01248           text = nullValue;
01249       }
01250       else
01251       {
01252         text = field.displayString( value );
01253       }
01254 
01255       if ( le )
01256         le->setText( text );
01257       if ( cb && cb->isEditable() )
01258         cb->setEditText( text );
01259       if ( te )
01260         te->setHtml( text );
01261       if ( pte )
01262         pte->setPlainText( text );
01263     }
01264     break;
01265 
01266     case QgsVectorLayer::FileName:
01267     case QgsVectorLayer::Calendar:
01268     case QgsVectorLayer::Photo:
01269     case QgsVectorLayer::WebView:
01270     case QgsVectorLayer::Color:
01271     {
01272       QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( editor );
01273       if ( cw )
01274       {
01275         cw->setSelectedDate( value.toDate() );
01276         break;
01277       }
01278 
01279       QWebView *ww = qobject_cast<QWebView *>( editor );
01280       if ( ww )
01281       {
01282         ww->load( value.toString() );
01283         break;
01284       }
01285 
01286       QLabel *lw = qobject_cast<QLabel *>( editor );
01287       if ( lw )
01288         break;
01289 
01290       QgsColorButton *cb = qobject_cast<QgsColorButton *>( editor );
01291       if ( cb )
01292       {
01293         cb->setColor( QColor( value.toString() ) );
01294         break;
01295       }
01296 
01297       QgsFilterLineEdit *fle = qobject_cast<QgsFilterLineEdit*>( editor );
01298       QLineEdit *le = qobject_cast<QLineEdit*>( editor );
01299       if ( !le )
01300       {
01301         le = editor->findChild<QLineEdit *>();
01302         fle = qobject_cast<QgsFilterLineEdit *>( le );
01303       }
01304       if ( !le )
01305         return false;
01306 
01307       if ( fle && !( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date ) )
01308       {
01309         fle->setNullValue( nullValue );
01310       }
01311 
01312       QString text;
01313       if ( value.isNull() )
01314       {
01315         if ( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date )
01316           text = "";
01317         else
01318           text = nullValue;
01319       }
01320       else if ( editType == QgsVectorLayer::Calendar && value.canConvert( QVariant::Date ) )
01321       {
01322         text = value.toDate().toString( vl->dateFormat( idx ) );
01323       }
01324       else
01325       {
01326         text = value.toString();
01327       }
01328 
01329       le->setText( text );
01330     }
01331     break;
01332 
01333     case QgsVectorLayer::Hidden:
01334       break;
01335   }
01336 
01337   return true;
01338 }
01339 
01340 QWidget* QgsAttributeEditor::createWidgetFromDef( const QgsAttributeEditorElement* widgetDef, QWidget* parent, QgsVectorLayer* vl, QgsAttributes &attrs, QMap<int, QWidget*> &proxyWidgets, bool createGroupBox )
01341 {
01342   QWidget *newWidget = 0;
01343 
01344   switch ( widgetDef->type() )
01345   {
01346     case QgsAttributeEditorElement::AeTypeField:
01347     {
01348       const QgsAttributeEditorField* fieldDef = dynamic_cast<const QgsAttributeEditorField*>( widgetDef );
01349       int fldIdx = fieldDef->idx();
01350       newWidget = createAttributeEditor( parent, 0, vl, fldIdx, attrs.value( fldIdx, QVariant() ), proxyWidgets );
01351 
01352       if ( vl->editType( fldIdx ) != QgsVectorLayer::Immutable )
01353       {
01354         if ( newWidget->isEnabled() && vl->isEditable() && vl->fieldEditable( fldIdx ) )
01355         {
01356           newWidget->setEnabled( true );
01357         }
01358         else if ( vl->editType( fldIdx ) == QgsVectorLayer::Photo )
01359         {
01360           foreach ( QWidget *w, newWidget->findChildren<QWidget *>() )
01361           {
01362             w->setEnabled( qobject_cast<QLabel *>( w ) ? true : false );
01363           }
01364         }
01365         else if ( vl->editType( fldIdx ) == QgsVectorLayer::WebView )
01366         {
01367           foreach ( QWidget *w, newWidget->findChildren<QWidget *>() )
01368           {
01369             if ( qobject_cast<QWebView *>( w ) )
01370               w->setEnabled( true );
01371             else if ( qobject_cast<QPushButton *>( w ) && w->objectName() == "openUrl" )
01372               w->setEnabled( true );
01373             else
01374               w->setEnabled( false );
01375           }
01376         }
01377         else
01378         {
01379           newWidget->setEnabled( false );
01380         }
01381       }
01382 
01383       break;
01384     }
01385 
01386     case QgsAttributeEditorElement::AeTypeContainer:
01387     {
01388       const QgsAttributeEditorContainer* container = dynamic_cast<const QgsAttributeEditorContainer*>( widgetDef );
01389       QWidget* myContainer;
01390 
01391       if ( createGroupBox )
01392       {
01393         QGroupBox* groupBox = new QGroupBox( parent );
01394         groupBox->setTitle( container->name() );
01395         myContainer = groupBox;
01396         newWidget = myContainer;
01397       }
01398       else
01399       {
01400         QScrollArea *scrollArea = new QScrollArea( parent );
01401 
01402         myContainer = new QWidget( scrollArea );
01403 
01404         scrollArea->setWidget( myContainer );
01405         scrollArea->setWidgetResizable( true );
01406         scrollArea->setFrameShape( QFrame::NoFrame );
01407 
01408         newWidget = scrollArea;
01409       }
01410 
01411       QGridLayout* gbLayout = new QGridLayout( myContainer );
01412       myContainer->setLayout( gbLayout );
01413 
01414       int index = 0;
01415 
01416       QList<QgsAttributeEditorElement*> children = container->children();
01417 
01418       for ( QList<QgsAttributeEditorElement*>::const_iterator it = children.begin(); it != children.end(); ++it )
01419       {
01420         QgsAttributeEditorElement* childDef = *it;
01421         QWidget* editor = createWidgetFromDef( childDef, myContainer, vl, attrs, proxyWidgets, true );
01422 
01423         if ( childDef->type() == QgsAttributeEditorElement::AeTypeContainer )
01424         {
01425           gbLayout->addWidget( editor, index, 0, 1, 2 );
01426         }
01427         else
01428         {
01429           const QgsAttributeEditorField* fieldDef = dynamic_cast<const QgsAttributeEditorField*>( childDef );
01430 
01431           //show attribute alias if available
01432           QString myFieldName = vl->attributeDisplayName( fieldDef->idx() );
01433           QLabel *mypLabel = new QLabel( myFieldName, myContainer );
01434 
01435           if ( vl->labelOnTop( fieldDef->idx() ) )
01436           {
01437             gbLayout->addWidget( mypLabel, index++, 0, 1, 2 );
01438             gbLayout->addWidget( editor, index, 0, 1 , 2 );
01439           }
01440           else
01441           {
01442             gbLayout->addWidget( mypLabel, index, 0 );
01443             gbLayout->addWidget( editor, index, 1 );
01444           }
01445         }
01446 
01447         ++index;
01448       }
01449       gbLayout->addItem( new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );
01450 
01451       break;
01452     }
01453 
01454     default:
01455       QgsDebugMsg( "Unknown attribute editor widget type encountered..." );
01456       break;
01457   }
01458 
01459   return newWidget;
01460 }
01461 
01462 void QgsStringRelay::changeText()
01463 {
01464   QObject* sObj = QObject::sender();
01465   QTextEdit *te = qobject_cast<QTextEdit *>( sObj );
01466   QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( sObj );
01467 
01468   if ( te )
01469     changeText( te->toPlainText() );
01470   if ( pte )
01471     changeText( pte->toPlainText() );
01472 }
01473 
01474 void QgsStringRelay::changeText( QString str )
01475 {
01476   QObject* sObj = QObject::sender();
01477   const char* sSlot = sObj->property( "QgisAttrEditSlot" ).toByteArray().constData();
01478 
01479   // disconnect widget being edited from relay's signal
01480   disconnect( this, SIGNAL( textChanged( QString ) ), sObj, sSlot );
01481 
01482   // block all proxies' signals
01483   QList<bool> oldBlockSigs;
01484   for ( int i = 0; i < mProxyList.size(); ++i )
01485   {
01486     oldBlockSigs << ( mProxyList[i] )->blockSignals( true );
01487   }
01488 
01489   // update all proxies not being edited without creating cyclical signals/slots
01490   emit textChanged( str );
01491 
01492   // reconnect widget being edited and reset blockSignals state
01493   connect( this, SIGNAL( textChanged( QString ) ), sObj, sSlot );
01494   for ( int i = 0; i < mProxyList.size(); ++i )
01495   {
01496     mProxyList[i]->blockSignals( oldBlockSigs[i] );
01497   }
01498 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines