|
QGIS API Documentation
master-59fd5e0
|
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 }