00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgsattributeeditor.h"
00020 #include <qgsvectorlayer.h>
00021 #include <qgsvectordataprovider.h>
00022 #include <qgsuniquevaluerenderer.h>
00023 #include <qgscategorizedsymbolrendererv2.h>
00024 #include <qgssymbol.h>
00025 #include <qgslonglongvalidator.h>
00026
00027 #include <QPushButton>
00028 #include <QLineEdit>
00029 #include <QTextEdit>
00030 #include <QFileDialog>
00031 #include <QComboBox>
00032 #include <QCheckBox>
00033 #include <QSpinBox>
00034 #include <QCompleter>
00035 #include <QHBoxLayout>
00036 #include <QPlainTextEdit>
00037 #include <QDial>
00038 #include <QCalendarWidget>
00039 #include <QDialogButtonBox>
00040
00041 void QgsAttributeEditor::selectFileName( void )
00042 {
00043 QPushButton *pb = qobject_cast<QPushButton *>( sender() );
00044 if ( !pb )
00045 return;
00046
00047 QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
00048 if ( !hbox )
00049 return;
00050
00051 QLineEdit *le = hbox->findChild<QLineEdit *>();
00052 if ( !le )
00053 return;
00054
00055 QString fileName = QFileDialog::getOpenFileName( 0 , tr( "Select a file" ) );
00056 if ( fileName.isNull() )
00057 return;
00058
00059 le->setText( fileName );
00060 }
00061
00062 void QgsAttributeEditor::selectDate( void )
00063 {
00064 QPushButton *pb = qobject_cast<QPushButton *>( sender() );
00065 if ( !pb )
00066 return;
00067
00068 QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
00069 if ( !hbox )
00070 return;
00071
00072 QLineEdit *le = hbox->findChild<QLineEdit *>();
00073 if ( !le )
00074 return;
00075
00076 QDialog *dlg = new QDialog();
00077 dlg->setWindowTitle( tr( "Select a date" ) );
00078 QVBoxLayout *vl = new QVBoxLayout( dlg );
00079
00080 QCalendarWidget *cw = new QCalendarWidget( dlg );
00081 cw->setSelectedDate( QDate::fromString( le->text(), Qt::ISODate ) );
00082 vl->addWidget( cw );
00083
00084 QDialogButtonBox *buttonBox = new QDialogButtonBox( dlg );
00085 buttonBox->addButton( QDialogButtonBox::Ok );
00086 buttonBox->addButton( QDialogButtonBox::Cancel );
00087 vl->addWidget( buttonBox );
00088
00089 connect( buttonBox, SIGNAL( accepted() ), dlg, SLOT( accept() ) );
00090 connect( buttonBox, SIGNAL( rejected() ), dlg, SLOT( reject() ) );
00091
00092 if ( dlg->exec() == QDialog::Accepted )
00093 {
00094 le->setText( cw->selectedDate().toString( Qt::ISODate ) );
00095 }
00096 }
00097
00098 QComboBox *QgsAttributeEditor::comboBox( QWidget *editor, QWidget *parent )
00099 {
00100 QComboBox *cb = NULL;
00101 if ( editor )
00102 cb = qobject_cast<QComboBox *>( editor );
00103 else
00104 cb = new QComboBox( parent );
00105
00106 return cb;
00107 }
00108
00109 QWidget *QgsAttributeEditor::createAttributeEditor( QWidget *parent, QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
00110 {
00111 if ( !vl )
00112 return NULL;
00113
00114 QWidget *myWidget = NULL;
00115 QgsVectorLayer::EditType editType = vl->editType( idx );
00116 const QgsField &field = vl->pendingFields()[idx];
00117 QVariant::Type myFieldType = field.type();
00118
00119 switch ( editType )
00120 {
00121 case QgsVectorLayer::UniqueValues:
00122 {
00123 QList<QVariant> values;
00124 vl->dataProvider()->uniqueValues( idx, values );
00125
00126 QComboBox *cb = comboBox( editor, parent );
00127 if ( cb )
00128 {
00129 cb->setEditable( false );
00130
00131 for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); it++ )
00132 cb->addItem( it->toString(), it->toString() );
00133
00134 myWidget = cb;
00135 }
00136 }
00137 break;
00138
00139 case QgsVectorLayer::Enumeration:
00140 {
00141 QStringList enumValues;
00142 vl->dataProvider()->enumValues( idx, enumValues );
00143
00144 QComboBox *cb = comboBox( editor, parent );
00145 if ( cb )
00146 {
00147 QStringList::const_iterator s_it = enumValues.constBegin();
00148 for ( ; s_it != enumValues.constEnd(); ++s_it )
00149 {
00150 cb->addItem( *s_it, *s_it );
00151 }
00152
00153 myWidget = cb;
00154 }
00155 }
00156 break;
00157
00158 case QgsVectorLayer::ValueMap:
00159 {
00160 const QMap<QString, QVariant> &map = vl->valueMap( idx );
00161
00162 QComboBox *cb = comboBox( editor, parent );
00163 if ( cb )
00164 {
00165 for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); it++ )
00166 {
00167 cb->addItem( it.key(), it.value() );
00168 }
00169
00170 myWidget = cb;
00171 }
00172 }
00173 break;
00174
00175 case QgsVectorLayer::Classification:
00176 {
00177 QMap<QString, QString> classes;
00178
00179 const QgsUniqueValueRenderer *uvr = dynamic_cast<const QgsUniqueValueRenderer *>( vl->renderer() );
00180 if ( uvr )
00181 {
00182 const QList<QgsSymbol *> symbols = uvr->symbols();
00183
00184 for ( int i = 0; i < symbols.size(); i++ )
00185 {
00186 QString label = symbols[i]->label();
00187 QString name = symbols[i]->lowerValue();
00188
00189 if ( label == "" )
00190 label = name;
00191
00192 classes.insert( name, label );
00193 }
00194 }
00195
00196 const QgsCategorizedSymbolRendererV2 *csr = dynamic_cast<const QgsCategorizedSymbolRendererV2 *>( vl->rendererV2() );
00197 if ( csr )
00198 {
00199 const QgsCategoryList &categories = (( QgsCategorizedSymbolRendererV2 * )csr )->categories();
00200 for ( int i = 0; i < categories.size(); i++ )
00201 {
00202 QString label = categories[i].label();
00203 QString value = categories[i].value().toString();
00204 if ( label.isEmpty() )
00205 label = value;
00206 classes.insert( value, label );
00207 }
00208 }
00209
00210 QComboBox *cb = comboBox( editor, parent );
00211 if ( cb )
00212 {
00213 for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); it++ )
00214 {
00215 cb->addItem( it.value(), it.key() );
00216 }
00217
00218 myWidget = cb;
00219 }
00220 }
00221 break;
00222
00223
00224 case QgsVectorLayer::DialRange:
00225 case QgsVectorLayer::SliderRange:
00226 case QgsVectorLayer::EditRange:
00227 {
00228 if ( myFieldType == QVariant::Int )
00229 {
00230 int min = vl->range( idx ).mMin.toInt();
00231 int max = vl->range( idx ).mMax.toInt();
00232 int step = vl->range( idx ).mStep.toInt();
00233
00234 if ( editType == QgsVectorLayer::EditRange )
00235 {
00236 QSpinBox *sb = NULL;
00237
00238 if ( editor )
00239 sb = qobject_cast<QSpinBox *>( editor );
00240 else
00241 sb = new QSpinBox( parent );
00242
00243 if ( sb )
00244 {
00245 sb->setRange( min, max );
00246 sb->setSingleStep( step );
00247
00248 myWidget = sb;
00249 }
00250 }
00251 else
00252 {
00253 QAbstractSlider *sl = NULL;
00254
00255 if ( editor )
00256 {
00257 sl = qobject_cast<QAbstractSlider*>( editor );
00258 }
00259 else if ( editType == QgsVectorLayer::DialRange )
00260 {
00261 sl = new QDial( parent );
00262 }
00263 else
00264 {
00265 sl = new QSlider( Qt::Horizontal, parent );
00266 }
00267
00268 if ( sl )
00269 {
00270 sl->setRange( min, max );
00271 sl->setSingleStep( step );
00272
00273 myWidget = sl;
00274 }
00275 }
00276 break;
00277 }
00278 else if ( myFieldType == QVariant::Double )
00279 {
00280 QDoubleSpinBox *dsb = NULL;
00281 if ( editor )
00282 dsb = qobject_cast<QDoubleSpinBox*>( editor );
00283 else
00284 dsb = new QDoubleSpinBox( parent );
00285
00286 if ( dsb )
00287 {
00288 double min = vl->range( idx ).mMin.toDouble();
00289 double max = vl->range( idx ).mMax.toDouble();
00290 double step = vl->range( idx ).mStep.toDouble();
00291
00292 dsb->setRange( min, max );
00293 dsb->setSingleStep( step );
00294
00295 myWidget = dsb;
00296 }
00297 break;
00298 }
00299 }
00300
00301 case QgsVectorLayer::CheckBox:
00302 {
00303 QCheckBox *cb = NULL;
00304 if ( editor )
00305 cb = qobject_cast<QCheckBox*>( editor );
00306 else
00307 cb = new QCheckBox( parent );
00308
00309 if ( cb )
00310 {
00311 myWidget = cb;
00312 break;
00313 }
00314 }
00315
00316
00317
00318 case QgsVectorLayer::LineEdit:
00319 case QgsVectorLayer::TextEdit:
00320 case QgsVectorLayer::UniqueValuesEditable:
00321 case QgsVectorLayer::Immutable:
00322 {
00323 QLineEdit *le = NULL;
00324 QTextEdit *te = NULL;
00325 QPlainTextEdit *pte = NULL;
00326
00327 if ( editor )
00328 {
00329 le = qobject_cast<QLineEdit *>( editor );
00330 te = qobject_cast<QTextEdit *>( editor );
00331 pte = qobject_cast<QPlainTextEdit *>( editor );
00332 }
00333 else if ( editType == QgsVectorLayer::TextEdit )
00334 {
00335 pte = new QPlainTextEdit( parent );
00336 }
00337 else
00338 {
00339 le = new QLineEdit( parent );
00340 }
00341
00342 if ( le )
00343 {
00344
00345 if ( editType == QgsVectorLayer::UniqueValuesEditable )
00346 {
00347 QList<QVariant> values;
00348 vl->dataProvider()->uniqueValues( idx, values );
00349
00350 QStringList svalues;
00351 for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); it++ )
00352 svalues << it->toString();
00353
00354 QCompleter *c = new QCompleter( svalues );
00355 c->setCompletionMode( QCompleter::PopupCompletion );
00356 le->setCompleter( c );
00357 }
00358
00359 if ( myFieldType == QVariant::Int )
00360 {
00361 le->setValidator( new QIntValidator( le ) );
00362 }
00363 else if ( myFieldType == QVariant::LongLong )
00364 {
00365 le->setValidator( new QgsLongLongValidator( le ) );
00366 }
00367 else if ( myFieldType == QVariant::Double )
00368 {
00369 le->setValidator( new QDoubleValidator( le ) );
00370 }
00371
00372 myWidget = le;
00373 }
00374
00375 if ( te )
00376 {
00377 te->setAcceptRichText( true );
00378 myWidget = te;
00379 }
00380
00381 if ( pte )
00382 {
00383 myWidget = pte;
00384 }
00385
00386 if ( myWidget )
00387 {
00388 myWidget->setDisabled( editType == QgsVectorLayer::Immutable );
00389 }
00390 }
00391 break;
00392
00393 case QgsVectorLayer::Hidden:
00394 myWidget = NULL;
00395 break;
00396
00397 case QgsVectorLayer::FileName:
00398 case QgsVectorLayer::Calendar:
00399 {
00400 QPushButton *pb = NULL;
00401 QLineEdit *le = qobject_cast<QLineEdit *>( editor );
00402 if ( le )
00403 {
00404 if ( le )
00405 myWidget = le;
00406
00407 if ( editor->parent() )
00408 {
00409 pb = editor->parent()->findChild<QPushButton *>();
00410 }
00411 }
00412 else
00413 {
00414 le = new QLineEdit();
00415
00416 pb = new QPushButton( tr( "..." ) );
00417
00418 QHBoxLayout *hbl = new QHBoxLayout();
00419 hbl->addWidget( le );
00420 hbl->addWidget( pb );
00421
00422 myWidget = new QWidget( parent );
00423 myWidget->setBackgroundRole( QPalette::Window );
00424 myWidget->setAutoFillBackground( true );
00425 myWidget->setLayout( hbl );
00426 }
00427
00428 if ( pb )
00429 {
00430 if ( editType == QgsVectorLayer::FileName )
00431 connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectFileName() ) );
00432 if ( editType == QgsVectorLayer::Calendar )
00433 connect( pb, SIGNAL( clicked() ), new QgsAttributeEditor( pb ), SLOT( selectDate() ) );
00434 }
00435 }
00436 break;
00437 }
00438
00439 setValue( myWidget, vl, idx, value );
00440
00441 return myWidget;
00442 }
00443
00444 bool QgsAttributeEditor::retrieveValue( QWidget *widget, QgsVectorLayer *vl, int idx, QVariant &value )
00445 {
00446 if ( !widget )
00447 return false;
00448
00449 const QgsField &theField = vl->pendingFields()[idx];
00450 QgsVectorLayer::EditType editType = vl->editType( idx );
00451 bool modified = false;
00452 QString text;
00453
00454 QLineEdit *le = qobject_cast<QLineEdit *>( widget );
00455 if ( le )
00456 {
00457 text = le->text();
00458 modified = le->isModified();
00459 if ( text == "NULL" )
00460 {
00461 text = QString::null;
00462 }
00463 }
00464
00465 QTextEdit *te = qobject_cast<QTextEdit *>( widget );
00466 if ( te )
00467 {
00468 text = te->toHtml();
00469 modified = te->document()->isModified();
00470 if ( text == "NULL" )
00471 {
00472 text = QString::null;
00473 }
00474 }
00475
00476 QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( widget );
00477 if ( pte )
00478 {
00479 text = pte->toPlainText();
00480 modified = pte->document()->isModified();
00481 if ( text == "NULL" )
00482 {
00483 text = QString::null;
00484 }
00485 }
00486
00487 QComboBox *cb = qobject_cast<QComboBox *>( widget );
00488 if ( cb )
00489 {
00490 if ( editType == QgsVectorLayer::UniqueValues ||
00491 editType == QgsVectorLayer::ValueMap ||
00492 editType == QgsVectorLayer::Classification )
00493 {
00494 text = cb->itemData( cb->currentIndex() ).toString();
00495 }
00496 else
00497 {
00498 text = cb->currentText();
00499 }
00500 }
00501
00502 QSpinBox *sb = qobject_cast<QSpinBox *>( widget );
00503 if ( sb )
00504 {
00505 text = QString::number( sb->value() );
00506 }
00507
00508 QAbstractSlider *slider = qobject_cast<QAbstractSlider *>( widget );
00509 if ( slider )
00510 {
00511 text = QString::number( slider->value() );
00512 }
00513
00514 QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( widget );
00515 if ( dsb )
00516 {
00517 text = QString::number( dsb->value() );
00518 }
00519
00520 QCheckBox *ckb = qobject_cast<QCheckBox *>( widget );
00521 if ( ckb )
00522 {
00523 QPair<QString, QString> states = vl->checkedState( idx );
00524 text = ckb->isChecked() ? states.first : states.second;
00525 }
00526
00527 QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( widget );
00528 if ( cw )
00529 {
00530 text = cw->selectedDate().toString();
00531 }
00532
00533 le = widget->findChild<QLineEdit *>();
00534 if ( le )
00535 {
00536 text = le->text();
00537 }
00538
00539 switch ( theField.type() )
00540 {
00541 case QVariant::Int:
00542 {
00543 bool ok;
00544 int myIntValue = text.toInt( &ok );
00545 if ( ok && !text.isEmpty() )
00546 {
00547 value = QVariant( myIntValue );
00548 modified = true;
00549 }
00550 else if ( modified )
00551 {
00552 value = QVariant( theField.type() );
00553 }
00554 }
00555 break;
00556 case QVariant::LongLong:
00557 {
00558 bool ok;
00559 qlonglong myLongValue = text.toLong( &ok );
00560 if ( ok && !text.isEmpty() )
00561 {
00562 value = QVariant( myLongValue );
00563 modified = true;
00564 }
00565 else if ( modified )
00566 {
00567 value = QVariant( theField.type() );
00568 }
00569 }
00570 case QVariant::Double:
00571 {
00572 bool ok;
00573 double myDblValue = text.toDouble( &ok );
00574 if ( ok && !text.isEmpty() )
00575 {
00576 value = QVariant( myDblValue );
00577 modified = true;
00578 }
00579 else if ( modified )
00580 {
00581 value = QVariant( theField.type() );
00582 }
00583 }
00584 break;
00585 case QVariant::Date:
00586 {
00587 QDate myDateValue = QDate::fromString( text, Qt::ISODate );
00588 if ( myDateValue.isValid() && !text.isEmpty() )
00589 {
00590 value = myDateValue;
00591 modified = true;
00592 }
00593 else if ( modified )
00594 {
00595 value = QVariant( theField.type() );
00596 }
00597 }
00598 break;
00599 default:
00600 modified = true;
00601 value = QVariant( text );
00602 break;
00603 }
00604
00605 return modified;
00606 }
00607
00608 bool QgsAttributeEditor::setValue( QWidget *editor, QgsVectorLayer *vl, int idx, const QVariant &value )
00609 {
00610 if ( !editor )
00611 return false;
00612
00613 QgsVectorLayer::EditType editType = vl->editType( idx );
00614 const QgsField &field = vl->pendingFields()[idx];
00615 QVariant::Type myFieldType = field.type();
00616
00617 switch ( editType )
00618 {
00619 case QgsVectorLayer::Classification:
00620 case QgsVectorLayer::UniqueValues:
00621 case QgsVectorLayer::Enumeration:
00622 case QgsVectorLayer::ValueMap:
00623 {
00624 QComboBox *cb = qobject_cast<QComboBox *>( editor );
00625 if ( cb == NULL )
00626 return false;
00627
00628 int idx = cb->findData( value );
00629 if ( idx < 0 )
00630 return false;
00631
00632 cb->setCurrentIndex( idx );
00633 }
00634 break;
00635
00636 case QgsVectorLayer::DialRange:
00637 case QgsVectorLayer::SliderRange:
00638 case QgsVectorLayer::EditRange:
00639 {
00640 if ( myFieldType == QVariant::Int )
00641 {
00642 if ( editType == QgsVectorLayer::EditRange )
00643 {
00644 QSpinBox *sb = qobject_cast<QSpinBox *>( editor );
00645 if ( sb == NULL )
00646 return false;
00647 sb->setValue( value.toInt() );
00648 }
00649 else
00650 {
00651 QAbstractSlider *sl = qobject_cast<QAbstractSlider *>( editor );
00652 if ( sl == NULL )
00653 return false;
00654 sl->setValue( value.toInt() );
00655 }
00656 break;
00657 }
00658 else if ( myFieldType == QVariant::Double )
00659 {
00660 QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( editor );
00661 if ( dsb == NULL )
00662 return false;
00663 dsb->setValue( value.toDouble() );
00664 }
00665 }
00666
00667 case QgsVectorLayer::CheckBox:
00668 {
00669 QCheckBox *cb = qobject_cast<QCheckBox *>( editor );
00670 if ( cb )
00671 {
00672 QPair<QString, QString> states = vl->checkedState( idx );
00673 cb->setChecked( value == states.first );
00674 break;
00675 }
00676 }
00677
00678
00679
00680 case QgsVectorLayer::LineEdit:
00681 case QgsVectorLayer::UniqueValuesEditable:
00682 case QgsVectorLayer::Immutable:
00683 default:
00684 {
00685 QLineEdit *le = qobject_cast<QLineEdit *>( editor );
00686 QTextEdit *te = qobject_cast<QTextEdit *>( editor );
00687 QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( editor );
00688 if ( !le && !te && !pte )
00689 return false;
00690
00691 QString text;
00692 if ( value.isNull() )
00693 if ( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong )
00694 text = "";
00695 else
00696 text = "NULL";
00697 else
00698 text = value.toString();
00699
00700 if ( le )
00701 le->setText( text );
00702 if ( te )
00703 te->setHtml( text );
00704 if ( pte )
00705 pte->setPlainText( text );
00706 }
00707 break;
00708
00709 case QgsVectorLayer::FileName:
00710 case QgsVectorLayer::Calendar:
00711 {
00712 QLineEdit *le = editor->findChild<QLineEdit *>();
00713 if ( le == NULL )
00714 return false;
00715 le->setText( value.toString() );
00716 }
00717 break;
00718 }
00719
00720 return true;
00721 }