AbanQ: Ampliando la funcionalidad de los optionslist
Una de las ayudas que tiene AbanQ a la hora de construir formularios que presentan registros asociados, es sin duda la posibilidad de definir OptionsList. Para una columna de base de datos, podemos definir un conjunto de posibles valores que se almacenarán en la misma, utilizando el tag optionslist dentro de la definición del campo, en el .mtd de la tabla correspondiente. AbanQ, automáticamente, creará un combobox en la vista (el formulario) para que el usuario sólo pueda escoger uno de esos valores.
Pero esta solución, aunque muy buena, no es óptima. Si la columna es un campo de tipo varchar (o string, como se le llama en AbanQ), el optionslist, guarda siempre en esa columna la cadena entera. Supongamos, por ejemplo, una columna “tipo_articulo” y un options list
<optionslist>Articulo prefabricado, Materia prima, Producto intermedio, Producto terminado</optionslist>
El detalle, es que esas cadenas se almacenan constantemente en la columna de la base de datos. Eso no es mayor problema si queremos indexar sobre esa columna, por ejemplo… Quizás es más interesante, el poder guardar en lugar de esos valores, otros, según la siguiente relación
<optionslist>Articulo prefabricado, Materia prima, Producto intermedio, Producto terminado</optionslist> <optionsvalues>1,2,3,4</optionsvalues>
De esta forma, cuando el usuario escoga en el combo box “Artículo prefabricado” en la columna de la base de datos, se guardará un 1.
¿Cómo se puede implementar esto en AbanQ? Es relativamente sencillo. Os pongo a continuación las diferencias entre archivos.
Index: abanq/src/flbase/FLDataTable.cpp
===================================================================
--- abanq/src/flbase/FLDataTable.cpp (revisión: 114)
+++ abanq/src/flbase/FLDataTable.cpp (copia de trabajo)
@@ -233,18 +233,37 @@
break;
case QVariant::String: {
- text = field->value().toString();
+ QString textView;
+ text = field->value().toString();
if ( fieldTMD->hasOptionsList() ) {
- QStringList ol( fieldTMD->optionsList() );
- if ( !ol.contains( text ) ) {
- QVariant defVal( fieldTMD->defaultValue() );
- if ( defVal.isValid() )
- text = defVal.toString();
- else
- text = ol.first();
- }
- text = FLUtil::translate( "MetaData", text );
- }
+ // dpinelo: El valor del campo lo buscamos en la lista de valores si está definida
+ if ( fieldTMD->optionsValues().isEmpty() ) {
+ QStringList ol( fieldTMD->optionsList() );
+ if ( !ol.contains( text ) ) {
+ QVariant defVal( fieldTMD->defaultValue() );
+ if ( defVal.isValid() )
+ text = defVal.toString();
+ else
+ text = ol.first();
+ }
+ text = FLUtil::translate( "MetaData", text );
+ } else {
+ QStringList ol( fieldTMD->optionsValues() );
+ QStringList olList ( fieldTMD->optionsList() );
+ // ¿Contiene el valor?
+ if ( !ol.contains( text ) ) {
+ QVariant defVal( fieldTMD->defaultValue() );
+ if ( defVal.isValid() )
+ textView = defVal.toString();
+ else {
+ textView = olList.first();
+ }
+ } else {
+ textView = olList[ol.findIndex(text)];
+ }
+ }
+ text = FLUtil::translate( "MetaData", textView );
+ }
p->drawText( 2, 2, cr.width() - 4, cr.height() - 4, fieldAlignment( field ), text );
}
break;
Index: abanq/src/flbase/FLFieldDB.cpp
===================================================================
--- abanq/src/flbase/FLFieldDB.cpp (revisión: 114)
+++ abanq/src/flbase/FLFieldDB.cpp (copia de trabajo)
@@ -294,7 +294,12 @@
QString tAux( t );
if ( ol && editor_ )
- tAux = field->optionsList()[ ::qt_cast( editor_ )->currentItem()];
+ // dpinelo
+ if ( field->optionsValues().isEmpty() ) {
+ tAux = field->optionsList()[ ::qt_cast( editor_ )->currentItem()];
+ } else {
+ tAux = field->optionsValues()[ ::qt_cast( editor_ )->currentItem()];
+ }
if ( !cursor_->bufferIsNull( fieldName_ ) ) {
if ( tAux == cursor_->valueBuffer( fieldName_ ).toString() ) {
@@ -403,12 +408,25 @@
if ( field->hasOptionsList() ) {
int idxItem = -1;
- if ( v.type() == QVariant::String )
- idxItem = field->optionsList().findIndex( v.toString() );
- if ( idxItem == -1 )
+ if ( v.type() == QVariant::String ) {
+ // dpinelo
+ if ( field->optionsValues().isEmpty() ) {
+ idxItem = field->optionsList().findIndex( v.toString() );
+ } else {
+ idxItem = field->optionsValues().findIndex( v.toString() );
+ }
+ }
+ if ( idxItem == -1 )
idxItem = v.toInt();
::qt_cast( editor_ )->setCurrentItem( idxItem );
- updateValue( ::qt_cast( editor_ )->currentText() );
+ if ( field->optionsValues().isEmpty() ) {
+ updateValue( ::qt_cast( editor_ )->currentText() );
+ } else {
+ int idxValue = field->optionsList().findIndex( ::qt_cast( editor_ )->currentText() );
+ if ( idxValue != -1 ) {
+ updateValue( field->optionsValues()[idxValue] );
+ }
+ }
#ifdef FL_TEST
::qt_cast( qApp )->continueTesting( FLTester::FIELD_READY, this->name() );
#endif
@@ -1317,19 +1335,39 @@
break;
case QVariant::String: {
- bool doHome = false;
- if ( ol ) {
- if ( v.toString() == ::qt_cast( editor_ )->currentText() )
- return ;
- } else {
- if ( v.toString() == ::qt_cast( editor_ )->text() )
- return ;
- doHome = ( ::qt_cast( editor_ )->text().isEmpty() );
- }
+ bool doHome = false;
+ if ( ol ) {
+ // dpinelo
+ if ( field->optionsValues().isEmpty() ) {
+ if ( v.toString() == ::qt_cast( editor_ )->currentText() ) {
+ return ;
+ } else {
+ if ( v.toString() == ::qt_cast( editor_ )->text() )
+ return ;
+ doHome = ( ::qt_cast( editor_ )->text().isEmpty() );
+ }
+ } else {
+ int index = field->optionsValues().findIndex( v.toString() );
+ if ( index != -1 ) {
+ QString comp = field->optionsList()[index];
+ if ( comp == ::qt_cast( editor_ )->currentText() ) {
+ return ;
+ } else {
+ if ( comp == ::qt_cast( editor_ )->text() )
+ return ;
+ doHome = ( ::qt_cast( editor_ )->text().isEmpty() );
+ }
+ }
+ }
+ }
disconnect( editor_, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateValue( const QString & ) ) );
if ( v.isValid() && !v.isNull() ) {
- if ( ol )
- ::qt_cast( editor_ )->setCurrentItem( field->optionsList().findIndex( v.toString() ) );
+ if ( ol ) {
+ // dpinelo
+ int index = field->optionsValues().findIndex( v.toString() );
+ ::qt_cast( editor_ )->setCurrentItem( index );
+ // ::qt_cast( editor_ )->setCurrentItem( field->optionsList().findIndex( v.toString() ) );
+ }
else
::qt_cast( editor_ )->setText( v.toString() );
} else {
@@ -1534,8 +1572,11 @@
doHome = ( ::qt_cast( editor_ )->text().isEmpty() );
disconnect( editor_, SIGNAL( textChanged( const QString & ) ), this, SLOT( updateValue( const QString & ) ) );
if ( !null ) {
- if ( ol )
- ::qt_cast( editor_ )->setCurrentItem( field->optionsList().findIndex( v.toString() ) );
+ if ( ol ) {
+ // dpinelo
+ int index = field->optionsValues().findIndex( v.toString() );
+ ::qt_cast( editor_ )->setCurrentItem( index );
+ }
else
::qt_cast( editor_ )->setText( v.toString() );
} else {
Index: abanq/src/flbase/FLFieldMetaData.cpp
===================================================================
--- abanq/src/flbase/FLFieldMetaData.cpp (revisión: 114)
+++ abanq/src/flbase/FLFieldMetaData.cpp (copia de trabajo)
@@ -59,6 +59,8 @@
delete relationM1_;
optionsList_.clear();
+ // dpinelo
+ optionsValues_.clear();
}
FLFieldMetaData::FLFieldMetaData( const QString & n, const QString & a, bool aN, bool iPK,
@@ -196,3 +198,24 @@
}
return type;
}
+
+// dpinelo
+void FLFieldMetaData::setOptionsValues(const QString & ol)
+{
+ d->optionsValues_.clear();
+ QString olTranslated = ol;
+ if ( ol.contains( "QT_TRANSLATE_NOOP" ) ) {
+ QStringList components = QStringList::split( ';', olTranslated );
+ QString component;
+
+ olTranslated = "";
+ for ( int i = 0; i < components.count(); i++ ) {
+ component = components[ i ];
+ component = component.mid( 30, component.length() - 32 );
+ if ( i > 0 )
+ olTranslated += ",";
+ olTranslated += component;
+ }
+ }
+ d->optionsValues_ = QStringList::split( ',', olTranslated );
+}
Index: abanq/src/flbase/FLFieldMetaData.h
===================================================================
--- abanq/src/flbase/FLFieldMetaData.h (revisión: 114)
+++ abanq/src/flbase/FLFieldMetaData.h (copia de trabajo)
@@ -384,6 +384,14 @@
QStringList optionsList();
/**
+ dpinelo: La lista de opciones para el campo se compone del valor que se guarda
+ y del valor que se muestra
+
+ @return Lista de valores del campo
+ */
+ QStringList optionsValues();
+
+ /**
Establece la lista de opciones para el campo
@param ol Cadena de texto con la opciones para el campo
@@ -392,6 +400,14 @@
void setOptionsList( const QString & ol );
/**
+ dpinelo: Establece la lista de valores para el campo
+
+ @param ol Cadena de texto con la opciones para el campo
+ separada por comas, p.e. "opcion1,opcion2,opcion3"
+ */
+ void setOptionsValues( const QString & ol );
+
+ /**
Obtiene si el campo es de tipo Check
*/
bool isCheck() const;
@@ -572,6 +588,11 @@
Lista de opciones para el campo
*/
QStringList optionsList_;
+
+ /**
+ dpinelo: Lista de valores para el campo
+ */
+ QStringList optionsValues_;
/**
Indica si las modificaciones del campo se hacen fuera de cualquier transaccion.
@@ -746,6 +767,11 @@
return d->optionsList_;
}
+// dpinelo
+inline QStringList FLFieldMetaData::optionsValues() {
+ return d->optionsValues_;
+}
+
inline bool FLFieldMetaData::isCompoundKey() const {
return d->isCompoundKey_;
}
Index: abanq/src/flbase/FLManager.cpp
===================================================================
--- abanq/src/flbase/FLManager.cpp (revisión: 114)
+++ abanq/src/flbase/FLManager.cpp (copia de trabajo)
@@ -302,6 +302,8 @@
bool aN = true, iPK = true, c = false, iNX = false, uNI = false, coun = false, oT = false, vG = true;
int t = QVariant::Int, l = 0, pI = 4, pD = 0;
QVariant dV = QVariant();
+ // dpinelo
+ QString olValues;
QDomNode no = field->firstChild();
@@ -446,7 +448,13 @@
no = no.nextSibling();
continue;
}
- }
+ // dpinelo
+ if ( e.tagName() == "optionsvalues" ) {
+ olValues = e.text();
+ no = no.nextSibling();
+ continue;
+ }
+ }
no = no.nextSibling();
}
@@ -455,6 +463,10 @@
if ( !ol.isEmpty() )
f->setOptionsList( ol );
+
+ // dpinelo
+ if ( !olValues.isEmpty() )
+ f->setOptionsValues ( olValues );
no = field->firstChild();
Detalles: Los números de líneas quizás no sean los correctos. Mi código está algo modificado, pero al menos sí aparecen el código que he modificado. En cualquier caso, voy a extraer todos las diferencias entre mi versión de AbanQ y la publicada por InfoSial indicando qué he añadido, para que así podáis sincronizar vuestro código con el mío sin problemas… pero necesito algo de tiempo para hacerlo.