@@ -276,8 +276,13 @@ QString FilterController::buildFieldExpression( const FieldFilter &filter ) cons
276276
277277 if ( filter.filterType == QLatin1String ( " bool" ) )
278278 {
279- bool boolValue = filter.value .toBool ();
280- return QStringLiteral ( " %1 = %2" ).arg ( quotedField, boolValue ? QStringLiteral ( " TRUE" ) : QStringLiteral ( " FALSE" ) );
279+ // for custom checkboxes the values can also be string or integers
280+ if ( filter.value .typeId () == QMetaType::Bool )
281+ {
282+ bool boolValue = filter.value .toBool ();
283+ return QStringLiteral ( " %1 = %2" ).arg ( quotedField, boolValue ? QStringLiteral ( " TRUE" ) : QStringLiteral ( " FALSE" ) );
284+ }
285+ return QStringLiteral ( " %1 = %2" ).arg ( quotedField, QgsExpression::quotedValue ( filter.value ) );
281286 }
282287 else if ( filter.filterType == QLatin1String ( " text" ) )
283288 {
@@ -502,13 +507,47 @@ QVariantList FilterController::getFilterableFields( QgsVectorLayer *layer ) cons
502507 filterType = QStringLiteral ( " dropdown" );
503508 multiSelect = widgetSetup.config ().value ( QStringLiteral ( " AllowMulti" ) ).toBool ();
504509 }
510+ else if ( widgetType == QLatin1String ( " CheckBox" ) )
511+ {
512+ filterType = QStringLiteral ( " bool" );
513+ QVariantMap config = widgetSetup.config ();
514+ QString checkedStateStr = config.value ( QStringLiteral ( " CheckedState" ) ).toString ();
515+ QString uncheckedStateStr = config.value ( QStringLiteral ( " UncheckedState" ) ).toString ();
516+
517+ if ( !checkedStateStr.isEmpty () )
518+ fieldInfo[QStringLiteral ( " boolTrueLabel" )] = checkedStateStr;
519+ if ( !uncheckedStateStr.isEmpty () )
520+ fieldInfo[QStringLiteral ( " boolFalseLabel" )] = uncheckedStateStr;
521+
522+ // Emit typed checked/unchecked values matching the field's actual storage type
523+ QMetaType::Type fieldType = static_cast <QMetaType::Type>( field.type () );
524+ bool isIntField = ( fieldType == QMetaType::Int || fieldType == QMetaType::UInt ||
525+ fieldType == QMetaType::LongLong || fieldType == QMetaType::ULongLong );
526+
527+ if ( !checkedStateStr.isEmpty () )
528+ {
529+ bool ok = false ;
530+ int intVal = checkedStateStr.toInt ( &ok );
531+ fieldInfo[QStringLiteral ( " boolCheckedValue" )] = ( isIntField && ok ) ? QVariant ( intVal ) : QVariant ( checkedStateStr );
532+ }
533+ if ( !uncheckedStateStr.isEmpty () )
534+ {
535+ bool ok = false ;
536+ int intVal = uncheckedStateStr.toInt ( &ok );
537+ fieldInfo[QStringLiteral ( " boolUncheckedValue" )] = ( isIntField && ok ) ? QVariant ( intVal ) : QVariant ( uncheckedStateStr );
538+ }
539+ }
505540 else
506541 {
507542 // Determine filter type based on field data type
508543 QMetaType::Type fieldType = static_cast <QMetaType::Type>( field.type () );
509544
510545 switch ( fieldType )
511546 {
547+ case QMetaType::Bool:
548+ filterType = QStringLiteral ( " bool" );
549+ break ;
550+
512551 case QMetaType::Int:
513552 case QMetaType::UInt:
514553 case QMetaType::LongLong:
0 commit comments