19 #include "qgseditorwidgetfactory.h"
20 #include "qgseditorwidgetregistry.h"
21 #include "qgseditorwidgetwrapper.h"
40 #include <QScrollArea>
41 #include <QPushButton>
44 #include <QFileDialog>
46 #include <QListWidget>
50 #include <QHBoxLayout>
51 #include <QPlainTextEdit>
53 #include <QCalendarWidget>
54 #include <QDialogButtonBox>
61 #include <QDesktopServices>
65 QPushButton *pb = qobject_cast<QPushButton *>( sender() );
69 QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
73 QLineEdit *le = hbox->findChild<QLineEdit *>();
77 QString fileName = QFileDialog::getOpenFileName( 0 ,
tr(
"Select a file" ), QFileInfo( le->text() ).absolutePath() );
78 if ( fileName.isNull() )
81 le->setText( QDir::toNativeSeparators( fileName ) );
86 QPushButton *pb = qobject_cast<QPushButton *>( sender() );
90 QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
94 QLineEdit *le = hbox->findChild<QLineEdit *>();
98 QDialog *dlg =
new QDialog();
99 dlg->setWindowTitle(
tr(
"Select a date" ) );
100 QVBoxLayout *vl =
new QVBoxLayout( dlg );
103 QString dateFormat = v ? v->
dateFormat() :
"yyyy-MM-dd";
105 QCalendarWidget *cw =
new QCalendarWidget( dlg );
106 QString prevValue = le->text();
107 cw->setSelectedDate( QDate::fromString( prevValue, dateFormat ) );
110 QDialogButtonBox *buttonBox =
new QDialogButtonBox( dlg );
111 buttonBox->addButton( QDialogButtonBox::Ok );
112 buttonBox->addButton( QDialogButtonBox::Cancel );
113 vl->addWidget( buttonBox );
115 connect( buttonBox, SIGNAL( accepted() ), dlg, SLOT( accept() ) );
116 connect( buttonBox, SIGNAL( rejected() ), dlg, SLOT( reject() ) );
118 if ( dlg->exec() == QDialog::Accepted )
120 QString newValue = cw->selectedDate().toString( dateFormat );
121 le->setText( newValue );
122 le->setModified( newValue != prevValue );
128 QLineEdit *le = qobject_cast<QLineEdit *>( sender() );
132 QWidget *hbox = qobject_cast<QWidget *>( le->parent() );
136 QWebView *ww = hbox->findChild<QWebView *>();
145 QLineEdit *le = qobject_cast<QLineEdit *>( sender() );
149 QWidget *hbox = qobject_cast<QWidget *>( le->parent() );
153 QLabel *lw = hbox->findChild<QLabel *>();
162 if (
size.width() == 0 &&
size.height() > 0 )
164 size.setWidth(
size.height() * pm.size().width() / pm.size().height() );
166 else if (
size.width() > 0 &&
size.height() == 0 )
168 size.setHeight(
size.width() * pm.size().height() / pm.size().width() );
171 pm = pm.scaled(
size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
174 lw->setMinimumSize(
size );
179 QPushButton *pb = qobject_cast<QPushButton *>( sender() );
183 QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
187 QWebView *ww = hbox->findChild<QWebView *>();
191 QLineEdit *le = hbox->findChild<QLineEdit *>();
195 le->blockSignals(
true );
196 le->setText( ww->url().toString() );
197 le->blockSignals(
false );
202 QPushButton *pb = qobject_cast<QPushButton *>( sender() );
206 QWidget *hbox = qobject_cast<QWidget *>( pb->parent() );
210 QWebView *ww = hbox->findChild<QWebView *>();
221 QLineEdit *sle = qobject_cast<QLineEdit *>( sender() );
226 QWidget *hbox = qobject_cast<QWidget *>( sender()->parent() );
234 QLineEdit *le = hbox->findChild<QLineEdit *>();
240 le->blockSignals(
true );
241 le->setText( scb->
color().name() );
242 le->blockSignals(
false );
247 cb->blockSignals(
true );
248 cb->
setColor( QColor( sle->text() ) );
249 cb->blockSignals(
false );
257 cb = qobject_cast<QComboBox *>( editor );
259 cb =
new QComboBox( parent );
268 lw = qobject_cast<QListWidget *>( editor );
270 lw =
new QListWidget( parent );
296 QWidget *myWidget = 0;
299 QVariant::Type myFieldType = field.
type();
301 bool synchronized =
false;
307 QList<QVariant> values;
310 QComboBox *cb =
comboBox( editor, parent );
313 cb->setEditable(
false );
315 for ( QList<QVariant>::iterator it = values.begin(); it != values.end(); ++it )
316 cb->addItem( it->toString(), it->toString() );
326 QStringList enumValues;
329 QComboBox *cb =
comboBox( editor, parent );
332 QStringList::const_iterator s_it = enumValues.constBegin();
333 for ( ; s_it != enumValues.constEnd(); ++s_it )
335 cb->addItem( *s_it, *s_it );
345 const QMap<QString, QVariant> &map = vl->
valueMap( idx );
347 QComboBox *cb =
comboBox( editor, parent );
350 for ( QMap<QString, QVariant>::const_iterator it = map.begin(); it != map.end(); ++it )
352 cb->addItem( it.key(), it.value() );
365 QMap< QString, QString > map;
380 if ( ki >= 0 && vi >= 0 )
382 QSet<int> attributes;
383 attributes << ki << vi;
405 if ( e && !e->
evaluate( &f ).toBool() )
415 QComboBox *cb =
comboBox( editor, parent );
421 cb->addItem(
tr(
"(no selection)" ), settings.value(
"qgis/nullValue",
"NULL" ).toString() );
424 for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); ++it )
427 cb->addItem( it.key(), it.value() );
429 cb->addItem( it.value(), it.key() );
437 QListWidget *lw =
listWidget( editor, parent );
440 QStringList checkList = value.toString().remove( QChar(
'{' ) ).remove( QChar(
'}' ) ).split(
"," );
442 for ( QMap< QString, QString >::const_iterator it = map.begin(); it != map.end(); ++it )
444 QListWidgetItem *item;
447 item =
new QListWidgetItem( it.key() );
448 item->setData( Qt::UserRole, it.value() );
449 item->setCheckState( checkList.contains( it.value() ) ? Qt::Checked : Qt::Unchecked );
453 item =
new QListWidgetItem( it.value() );
454 item->setData( Qt::UserRole, it.key() );
455 item->setCheckState( checkList.contains( it.key() ) ? Qt::Checked : Qt::Unchecked );
471 QgsEditorWidgetWrapper* eww = QgsEditorWidgetRegistry::instance()->create( widgetType, vl, idx, widgetConfig, editor, parent );
474 myWidget = eww->widget();
480 QMap<QString, QString> classes;
486 for (
int i = 0; i < categories.size(); i++ )
488 QString label = categories[i].label();
489 QString value = categories[i].value().toString();
490 if ( label.isEmpty() )
492 classes.insert( value, label );
496 QComboBox *cb =
comboBox( editor, parent );
499 for ( QMap<QString, QString>::const_iterator it = classes.begin(); it != classes.end(); ++it )
501 cb->addItem( it.value(), it.key() );
513 if ( myFieldType == QVariant::Int || myFieldType == QVariant::LongLong )
524 sb = qobject_cast<QSpinBox *>( editor );
526 sb =
new QSpinBox( parent );
530 sb->setRange( min, max );
531 sb->setSingleStep( step );
538 QAbstractSlider *sl = 0;
542 sl = qobject_cast<QAbstractSlider*>( editor );
546 sl =
new QDial( parent );
550 sl =
new QSlider( Qt::Horizontal, parent );
555 sl->setRange( min, max );
556 sl->setSingleStep( step );
563 else if ( myFieldType == QVariant::Double )
565 QDoubleSpinBox *dsb = 0;
567 dsb = qobject_cast<QDoubleSpinBox*>( editor );
569 dsb =
new QDoubleSpinBox( parent );
575 double step = vl->
range( idx ).
mStep.toDouble();
577 dsb->setRange( min, max );
578 dsb->setSingleStep( step );
592 gb = qobject_cast<QGroupBox *>( editor );
593 cb = qobject_cast<QCheckBox*>( editor );
596 cb =
new QCheckBox( parent );
620 QPlainTextEdit *pte = 0;
625 le = qobject_cast<QLineEdit *>( editor );
626 te = qobject_cast<QTextEdit *>( editor );
627 pte = qobject_cast<QPlainTextEdit *>( editor );
628 cb = qobject_cast<QComboBox *>( editor );
632 pte =
new QPlainTextEdit( parent );
643 QList<QVariant> values;
647 for ( QList<QVariant>::const_iterator it = values.begin(); it != values.end(); ++it )
648 svalues << it->toString();
650 QCompleter *c =
new QCompleter( svalues );
651 c->setCompletionMode( QCompleter::PopupCompletion );
652 le->setCompleter( c );
657 le->setReadOnly(
true );
667 te->setAcceptRichText(
true );
678 if ( cb->isEditable() )
687 myWidget->setDisabled(
true );
695 relay = pwdg->property(
"QgisAttrEditProxy" ).value<
QgsStringRelay*>();
702 const char* rSlot = SLOT( changeText( QString ) );
703 const char* rSig = SIGNAL( textChanged( QString ) );
704 const char* wSlot = SLOT( setText( QString ) );
705 const char* wSig = SIGNAL( textChanged( QString ) );
708 rSlot = SLOT( changeText() );
709 wSig = SIGNAL( textChanged() );
713 wSlot = SLOT( setPlainText( QString ) );
715 if ( cb && cb->isEditable() )
717 wSlot = SLOT( setEditText( QString ) );
718 wSig = SIGNAL( editTextChanged( QString ) );
721 synchronized = connect( relay, rSig, myWidget, wSlot );
722 synchronized &= connect( myWidget, wSig, relay, rSlot );
727 if ( !cb || cb->isEditable() )
729 myWidget->setProperty(
"QgisAttrEditSlot", QVariant( QByteArray( wSlot ) ) );
730 myWidget->setProperty(
"QgisAttrEditProxy", QVariant::fromValue<QgsStringRelay*>( relay ) );
746 QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( editor );
753 QWebView *ww = qobject_cast<QWebView *>( editor );
758 ww->settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls,
true );
759 ww->settings()->setAttribute( QWebSettings::JavascriptCanOpenWindows,
true );
761 ww->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled,
true );
765 if (
size.width() > 0 ||
size.height() > 0 )
767 if (
size.width() == 0 )
769 if (
size.height() == 0 )
771 ww->setMinimumSize(
size );
778 QLabel *lw = qobject_cast<QLabel *>( editor );
792 QPushButton *pb0 = 0;
793 QPushButton *pb1 = 0;
794 QLineEdit *le = qobject_cast<QLineEdit *>( editor );
800 if ( editor->parent() )
802 pb0 = editor->parent()->findChild<QPushButton *>();
807 myWidget =
new QWidget( parent );
808 myWidget->setBackgroundRole( QPalette::Window );
809 myWidget->setAutoFillBackground(
true );
817 pb0 =
new QPushButton(
tr(
"..." ), myWidget );
821 pb0 =
new QPushButton(
tr(
"<" ), myWidget );
822 pb0->setObjectName(
"saveUrl" );
823 pb1 =
new QPushButton(
tr(
"..." ), myWidget );
824 pb1->setObjectName(
"openUrl" );
837 QGridLayout *layout =
new QGridLayout( myWidget );
840 lw =
new QLabel( myWidget );
841 layout->addWidget( lw, 0, 0, 1, 2 );
846 ww =
new QWebView( myWidget );
847 ww->setObjectName(
"webview" );
850 ww->settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls,
true );
851 ww->settings()->setAttribute( QWebSettings::JavascriptCanOpenWindows,
true );
853 ww->settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled,
true );
857 if (
size.width() > 0 ||
size.height() > 0 )
859 if (
size.width() == 0 )
861 if (
size.height() == 0 )
863 ww->setMinimumSize(
size );
866 layout->addWidget( ww, 0, 0, 1, 2 );
870 layout->addWidget( le, row, 0 );
871 layout->addWidget( pb0, row, 1 );
873 layout->addWidget( pb1, row, 2 );
875 myWidget->setLayout( layout );
883 connect( le, SIGNAL( textChanged(
const QString & ) ),
new QgsAttributeEditor( le, vl, idx ), SLOT(
loadUrl(
const QString & ) ) );
895 pb0->setToolTip(
tr(
"Select filename..." ) );
900 pb0->setToolTip(
tr(
"Save current page url in attribute" ) );
905 pb0->setToolTip(
tr(
"Select date in calendar" ) );
910 pb0->setToolTip(
tr(
"Select color in browser" ) );
919 pb1->setToolTip(
tr(
"Open current page in default browser" ) );
930 myWidget->setEnabled(
false );
938 setValue( myWidget, vl, idx, value );
948 QgsEditorWidgetWrapper* wrapper = QgsEditorWidgetWrapper::fromWidget( widget );
952 value = wrapper->value();
958 bool modified =
false;
962 QString nullValue = settings.value(
"qgis/nullValue",
"NULL" ).toString();
964 QLineEdit *le = qobject_cast<QLineEdit *>( widget );
968 modified = le->isModified();
969 if ( text == nullValue )
971 text = QString::null;
975 QTextEdit *te = qobject_cast<QTextEdit *>( widget );
979 modified = te->document()->isModified();
980 if ( text == nullValue )
982 text = QString::null;
986 QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( widget );
989 text = pte->toPlainText();
990 modified = pte->document()->isModified();
991 if ( text == nullValue )
993 text = QString::null;
997 QComboBox *cb = qobject_cast<QComboBox *>( widget );
1005 text = cb->itemData( cb->currentIndex() ).toString();
1006 if ( text == nullValue )
1008 text = QString::null;
1013 text = cb->currentText();
1018 QListWidget *lw = qobject_cast<QListWidget *>( widget );
1024 for (
int i = 0, n = 0; i < lw->count(); i++ )
1026 if ( lw->item( i )->checkState() == Qt::Checked )
1032 text.append( lw->item( i )->data( Qt::UserRole ).toString() );
1040 text = QString::null;
1045 QSpinBox *sb = qobject_cast<QSpinBox *>( widget );
1048 text = QString::number( sb->value() );
1051 QAbstractSlider *slider = qobject_cast<QAbstractSlider *>( widget );
1054 text = QString::number( slider->value() );
1057 QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( widget );
1060 text = QString::number( dsb->value() );
1063 QCheckBox *ckb = qobject_cast<QCheckBox *>( widget );
1066 QPair<QString, QString> states = vl->
checkedState( idx );
1067 text = ckb->isChecked() ? states.first : states.second;
1070 QGroupBox *gb = qobject_cast<QGroupBox *>( widget );
1073 QPair<QString, QString> states = vl->
checkedState( idx );
1074 text = gb->isChecked() ? states.first : states.second;
1077 QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( widget );
1080 text = cw->selectedDate().toString( vl->
dateFormat( idx ) );
1083 le = widget->findChild<QLineEdit *>();
1086 if ( !cw && !gb && le )
1089 modified = le->isModified();
1090 if ( text == nullValue )
1092 text = QString::null;
1096 switch ( theField.
type() )
1101 int myIntValue = text.toInt( &ok );
1102 if ( ok && !text.isEmpty() )
1104 value = QVariant( myIntValue );
1107 else if ( modified )
1113 case QVariant::LongLong:
1116 qlonglong myLongValue = text.toLong( &ok );
1117 if ( ok && !text.isEmpty() )
1119 value = QVariant( myLongValue );
1122 else if ( modified )
1127 case QVariant::Double:
1130 double myDblValue = text.toDouble( &ok );
1131 if ( ok && !text.isEmpty() )
1133 value = QVariant( myDblValue );
1136 else if ( modified )
1142 case QVariant::Date:
1144 QDate myDateValue = QDate::fromString( text, vl->
dateFormat( idx ) );
1145 if ( myDateValue.isValid() && !text.isEmpty() )
1147 value = myDateValue;
1150 else if ( modified )
1158 if ( text.isNull() )
1159 value = QVariant( theField.
type() );
1161 value = QVariant( text );
1175 QVariant::Type myFieldType = field.
type();
1178 QString nullValue = settings.value(
"qgis/nullValue",
"NULL" ).toString();
1189 QComboBox *cb = qobject_cast<QComboBox *>( editor );
1198 int idx = cb->findData( v );
1202 cb->setCurrentIndex( idx );
1210 if ( myFieldType == QVariant::Int )
1214 QSpinBox *sb = qobject_cast<QSpinBox *>( editor );
1217 sb->setValue( value.toInt() );
1221 QAbstractSlider *sl = qobject_cast<QAbstractSlider *>( editor );
1224 sl->setValue( value.toInt() );
1228 else if ( myFieldType == QVariant::Double )
1230 QDoubleSpinBox *dsb = qobject_cast<QDoubleSpinBox *>( editor );
1233 dsb->setValue( value.toDouble() );
1239 QGroupBox *gb = qobject_cast<QGroupBox *>( editor );
1242 QPair<QString, QString> states = vl->
checkedState( idx );
1243 gb->setChecked( value == states.first );
1247 QCheckBox *cb = qobject_cast<QCheckBox *>( editor );
1250 QPair<QString, QString> states = vl->
checkedState( idx );
1251 cb->setChecked( value == states.first );
1265 QLineEdit *le = qobject_cast<QLineEdit *>( editor );
1266 QComboBox *cb = qobject_cast<QComboBox *>( editor );
1267 QTextEdit *te = qobject_cast<QTextEdit *>( editor );
1268 QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( editor );
1269 if ( !le && ! cb && !te && !pte )
1272 if ( fle && !( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date ) )
1278 if ( value.isNull() )
1280 if ( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date )
1283 text = QUuid::createUuid().toString();
1293 le->setText( text );
1294 if ( cb && cb->isEditable() )
1295 cb->setEditText( text );
1297 te->setHtml( text );
1299 pte->setPlainText( text );
1309 QCalendarWidget *cw = qobject_cast<QCalendarWidget *>( editor );
1312 cw->setSelectedDate( value.toDate() );
1316 QWebView *ww = qobject_cast<QWebView *>( editor );
1319 ww->load( value.toString() );
1323 QLabel *lw = qobject_cast<QLabel *>( editor );
1330 cb->
setColor( QColor( value.toString() ) );
1335 QLineEdit *le = qobject_cast<QLineEdit*>( editor );
1338 le = editor->findChild<QLineEdit *>();
1344 if ( fle && !( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date ) )
1350 if ( value.isNull() )
1352 if ( myFieldType == QVariant::Int || myFieldType == QVariant::Double || myFieldType == QVariant::LongLong || myFieldType == QVariant::Date )
1359 text = value.toDate().toString( vl->
dateFormat( idx ) );
1363 text = value.toString();
1366 le->setText( text );
1374 QgsEditorWidgetWrapper* wrapper = QgsEditorWidgetWrapper::fromWidget( editor );
1377 wrapper->setValue( value );
1387 QWidget *newWidget = 0;
1389 switch ( widgetDef->
type() )
1394 int fldIdx = fieldDef->
idx();
1395 if ( fldIdx < vl->pendingFields().count() && fldIdx >= 0 )
1405 newWidget->setEnabled(
true );
1409 foreach ( QWidget *w, newWidget->findChildren<QWidget *>() )
1411 w->setEnabled( qobject_cast<QLabel *>( w ) ?
true :
false );
1416 foreach ( QWidget *w, newWidget->findChildren<QWidget *>() )
1418 if ( qobject_cast<QWebView *>( w ) )
1419 w->setEnabled(
true );
1420 else if ( qobject_cast<QPushButton *>( w ) && w->objectName() ==
"openUrl" )
1421 w->setEnabled(
true );
1423 w->setEnabled(
false );
1428 newWidget->setEnabled(
false );
1435 newWidget =
new QLabel(
tr(
"<i>Error: Field does not exist in datasource</i>" ), parent );
1447 labelText = QString::null;
1455 QWidget* myContainer;
1459 QGroupBox* groupBox =
new QGroupBox( parent );
1460 groupBox->setTitle( container->
name() );
1461 myContainer = groupBox;
1462 newWidget = myContainer;
1466 QScrollArea *scrollArea =
new QScrollArea( parent );
1468 myContainer =
new QWidget( scrollArea );
1470 scrollArea->setWidget( myContainer );
1471 scrollArea->setWidgetResizable(
true );
1472 scrollArea->setFrameShape( QFrame::NoFrame );
1474 newWidget = scrollArea;
1477 QGridLayout* gbLayout =
new QGridLayout( myContainer );
1478 myContainer->setLayout( gbLayout );
1482 QList<QgsAttributeEditorElement*> children = container->
children();
1488 QWidget* editor =
createWidgetFromDef( childDef, myContainer, vl, feat, context, labelText, labelOnTop );
1490 if ( labelText == QString::null )
1492 gbLayout->addWidget( editor, index, 0, 1, 2 );
1496 QLabel* mypLabel =
new QLabel( labelText );
1499 gbLayout->addWidget( mypLabel, index, 0, 1, 2 );
1501 gbLayout->addWidget( editor, index, 0, 1 , 2 );
1505 gbLayout->addWidget( mypLabel, index, 0 );
1506 gbLayout->addWidget( editor, index, 1 );
1512 gbLayout->addItem(
new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding ), index , 0 );
1514 labelText = QString::null;
1520 QgsDebugMsg(
"Unknown attribute editor widget type encountered..." );
1529 QObject* sObj = QObject::sender();
1530 QTextEdit *te = qobject_cast<QTextEdit *>( sObj );
1531 QPlainTextEdit *pte = qobject_cast<QPlainTextEdit *>( sObj );
1541 QObject* sObj = QObject::sender();
1542 const char* sSlot = sObj->property(
"QgisAttrEditSlot" ).toByteArray().constData();
1545 disconnect(
this, SIGNAL(
textChanged( QString ) ), sObj, sSlot );
1548 QList<bool> oldBlockSigs;
1549 for (
int i = 0; i <
mProxyList.size(); ++i )
1551 oldBlockSigs << (
mProxyList[i] )->blockSignals(
true );
1558 connect(
this, SIGNAL(
textChanged( QString ) ), sObj, sSlot );
1559 for (
int i = 0; i <
mProxyList.size(); ++i )
1561 mProxyList[i]->blockSignals( oldBlockSigs[i] );