/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
 
#include <queryfilter.hxx>
#include <com/sun/star/sdbc/ColumnSearch.hpp>
#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
#include <com/sun/star/sdb/SQLFilterOperator.hpp>
#include <com/sun/star/sdbc/XConnection.hpp>
#include <comphelper/string.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <osl/diagnose.h>
#include <connectivity/dbtools.hxx>
#include <strings.hxx>
#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
 
using namespace dbaui;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::sdb;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::sdbcx;
using namespace ::com::sun::star::beans;
 
static void Replace_OS_PlaceHolder(OUString& aString)
{
    aString = aString.replaceAll( "*", "%" );
    aString = aString.replaceAll( "?", "_" );
}
 
static void Replace_SQL_PlaceHolder(OUString& aString)
{
    aString = aString.replaceAll( "%", "*" );
    aString = aString.replaceAll( "_", "?" );
}
 
DlgFilterCrit::DlgFilterCrit(weld::Window * pParent,
                             const Reference< XComponentContext >& rxContext,
                             const Reference< XConnection>& _rxConnection,
                             const Reference< XSingleSelectQueryComposer >& _rxComposer,
                             const Reference< XNameAccess>& _rxCols)
    : GenericDialogController(pParent, u"dbaccess/ui/queryfilterdialog.ui"_ustr, u"QueryFilterDialog"_ustr)
    , m_xQueryComposer(_rxComposer)
    , m_xColumns( _rxCols )
    , m_xConnection( _rxConnection )
    , m_xMetaData( _rxConnection->getMetaData() )
    , m_aPredicateInput( rxContext, _rxConnection, getParseContext() )
    , m_xLB_WHEREFIELD1(m_xBuilder->weld_combo_box(u"field1"_ustr))
    , m_xLB_WHERECOMP1(m_xBuilder->weld_combo_box(u"cond1"_ustr))
    , m_xET_WHEREVALUE1(m_xBuilder->weld_entry(u"value1"_ustr))
    , m_xLB_WHERECOND2(m_xBuilder->weld_combo_box(u"op2"_ustr))
    , m_xLB_WHEREFIELD2(m_xBuilder->weld_combo_box(u"field2"_ustr))
    , m_xLB_WHERECOMP2(m_xBuilder->weld_combo_box(u"cond2"_ustr))
    , m_xET_WHEREVALUE2(m_xBuilder->weld_entry(u"value2"_ustr))
    , m_xLB_WHERECOND3(m_xBuilder->weld_combo_box(u"op3"_ustr))
    , m_xLB_WHEREFIELD3(m_xBuilder->weld_combo_box(u"field3"_ustr))
    , m_xLB_WHERECOMP3(m_xBuilder->weld_combo_box(u"cond3"_ustr))
    , m_xET_WHEREVALUE3(m_xBuilder->weld_entry(u"value3"_ustr))
{
    //set all condition preferred width to max width
    //if all entries exist
    Size aSize(m_xLB_WHERECOMP1->get_preferred_size());
    m_xLB_WHERECOMP1->set_size_request(aSize.Width(), -1);
    m_xLB_WHERECOMP2->set_size_request(aSize.Width(), -1);
    m_xLB_WHERECOMP3->set_size_request(aSize.Width(), -1);
    const sal_Int32 nEntryCount =  m_xLB_WHERECOMP1->get_count();
    m_aSTR_COMPARE_OPERATORS.resize(nEntryCount);
    for (sal_Int32 i = 0; i < nEntryCount; ++i)
    {
        m_aSTR_COMPARE_OPERATORS[i] = m_xLB_WHERECOMP1->get_text(i);
    }
    m_xLB_WHERECOMP1->clear();
 
    // ... also write it into the remaining fields
    Reference<XPropertySet> xColumn;
    for (auto& colName : m_xColumns->getElementNames())
    {
        try
        {
            xColumn.set(m_xColumns->getByName(colName), UNO_QUERY_THROW);
 
            sal_Int32 nDataType( 0 );
            OSL_VERIFY( xColumn->getPropertyValue( PROPERTY_TYPE ) >>= nDataType );
            sal_Int32 eColumnSearch = ::dbtools::getSearchColumnFlag( m_xConnection, nDataType );
            if ( eColumnSearch == ColumnSearch::NONE )
                continue;
 
            bool bIsSearchable( true );
            OSL_VERIFY( xColumn->getPropertyValue( PROPERTY_ISSEARCHABLE ) >>= bIsSearchable );
            if ( !bIsSearchable )
                continue;
        }
        catch( const Exception& )
        {
            DBG_UNHANDLED_EXCEPTION("dbaccess");
        }
        m_xLB_WHEREFIELD1->append_text(colName);
        m_xLB_WHEREFIELD2->append_text(colName);
        m_xLB_WHEREFIELD3->append_text(colName);
    }
 
    Reference<XNameAccess> xSelectColumns = Reference<XColumnsSupplier>(m_xQueryComposer,UNO_QUERY_THROW)->getColumns();
    for (auto& colName : xSelectColumns->getElementNames())
    {
        // don't insert a column name twice
        if (!m_xColumns->hasByName(colName))
        {
            xColumn.set(xSelectColumns->getByName(colName), UNO_QUERY);
            OSL_ENSURE(xColumn.is(),"DlgFilterCrit::DlgFilterCrit: Column is null!");
            sal_Int32 nDataType(0);
            xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
            sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType);
            // TODO
            // !pColumn->IsFunction()
            if(eColumnSearch != ColumnSearch::NONE)
            {
                m_xLB_WHEREFIELD1->append_text(colName);
                m_xLB_WHEREFIELD2->append_text(colName);
                m_xLB_WHEREFIELD3->append_text(colName);
            }
        }
    }
    // initialize the listboxes with noEntry
    m_xLB_WHEREFIELD1->set_active(0);
    m_xLB_WHEREFIELD2->set_active(0);
    m_xLB_WHEREFIELD3->set_active(0);
 
    // insert the criteria into the dialog
    Sequence<Sequence<PropertyValue > > aValues = m_xQueryComposer->getStructuredFilter();
    int i(0);
    fillLines(i, aValues);
    aValues = m_xQueryComposer->getStructuredHavingClause();
    fillLines(i, aValues);
 
    EnableLines();
 
    m_xLB_WHEREFIELD1->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl));
    m_xLB_WHEREFIELD2->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl));
    m_xLB_WHEREFIELD3->connect_changed(LINK(this,DlgFilterCrit,ListSelectHdl));
 
    m_xLB_WHERECOMP1->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl));
    m_xLB_WHERECOMP2->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl));
    m_xLB_WHERECOMP3->connect_changed(LINK(this,DlgFilterCrit,ListSelectCompHdl));
 
    m_xET_WHEREVALUE1->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) );
    m_xET_WHEREVALUE2->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) );
    m_xET_WHEREVALUE3->connect_focus_out( LINK( this, DlgFilterCrit, PredicateLoseFocus ) );
 
    if (m_xET_WHEREVALUE1->get_sensitive())
        m_xET_WHEREVALUE1->grab_focus();
}
 
DlgFilterCrit::~DlgFilterCrit()
{
}
 
sal_Int32 DlgFilterCrit::GetOSQLPredicateType( std::u16string_view _rSelectedPredicate ) const
{
    sal_Int32 nPredicateIndex = -1;
    for ( size_t i=0; i < m_aSTR_COMPARE_OPERATORS.size(); ++i)
        if ( m_aSTR_COMPARE_OPERATORS[i] == _rSelectedPredicate )
        {
            nPredicateIndex = i;
            break;
        }
 
    sal_Int32 nPredicateType = SQLFilterOperator::NOT_SQLNULL;
    switch ( nPredicateIndex )
    {
    case 0:
        nPredicateType = SQLFilterOperator::EQUAL;
        break;
    case 1:
        nPredicateType = SQLFilterOperator::NOT_EQUAL;
        break;
    case 2:
        nPredicateType = SQLFilterOperator::LESS;
        break;
    case 3:
        nPredicateType = SQLFilterOperator::LESS_EQUAL;
        break;
    case 4:
        nPredicateType = SQLFilterOperator::GREATER;
        break;
    case 5:
        nPredicateType = SQLFilterOperator::GREATER_EQUAL;
        break;
    case 6:
        nPredicateType = SQLFilterOperator::LIKE;
        break;
    case 7:
        nPredicateType = SQLFilterOperator::NOT_LIKE;
        break;
    case 8:
        nPredicateType = SQLFilterOperator::SQLNULL;
        break;
    case 9:
        nPredicateType = SQLFilterOperator::NOT_SQLNULL;
        break;
    default:
        OSL_FAIL( "DlgFilterCrit::GetOSQLPredicateType: unknown predicate string!" );
        break;
    }
 
    return nPredicateType;
}
 
sal_Int32 DlgFilterCrit::GetSelectionPos(sal_Int32 eType, const weld::ComboBox& rListBox)
{
    sal_Int32 nPos;
    switch(eType)
    {
        case SQLFilterOperator::EQUAL:
            nPos = 0;
            break;
        case SQLFilterOperator::NOT_EQUAL:
            nPos = 1;
            break;
        case SQLFilterOperator::LESS:
            nPos = 2;
            break;
        case SQLFilterOperator::LESS_EQUAL:
            nPos = 3;
            break;
        case SQLFilterOperator::GREATER:
            nPos = 4;
            break;
        case SQLFilterOperator::GREATER_EQUAL:
            nPos = 5;
            break;
        case SQLFilterOperator::NOT_LIKE:
            nPos = rListBox.get_count() > 2 ? rListBox.get_count()-3 : 0;
            break;
        case SQLFilterOperator::LIKE:
            nPos = rListBox.get_count() > 2 ? rListBox.get_count()-4 : 1;
            break;
        case SQLFilterOperator::SQLNULL:
            nPos = rListBox.get_count()-2;
            break;
        case SQLFilterOperator::NOT_SQLNULL:
            nPos = rListBox.get_count()-1;
            break;
        default:
            //  TODO  What value should this be?
            nPos = 0;
            break;
    }
    return nPos;
}
 
bool DlgFilterCrit::getCondition(const weld::ComboBox& _rField,const weld::ComboBox& _rComp,const weld::Entry& _rValue,PropertyValue& _rFilter) const
{
    bool bHaving = false;
    try
    {
        _rFilter.Name = _rField.get_active_text();
        Reference< XPropertySet > xColumn = getQueryColumn(_rFilter.Name);
        if ( xColumn.is() )
        {
            bool bFunction = false;
            OUString sTableName;
            Reference< XPropertySetInfo > xInfo = xColumn->getPropertySetInfo();
            if ( xInfo->hasPropertyByName(PROPERTY_REALNAME) )
            {
                if ( xInfo->hasPropertyByName(PROPERTY_TABLENAME) )
                {
                    xColumn->getPropertyValue(PROPERTY_TABLENAME)   >>= sTableName;
                    if ( !sTableName.isEmpty() )
                    {
                        // properly quote all parts of the table name, so
                        // e.g. <schema>.<table> becomes "<schema>"."<table>"
                        OUString aCatalog,aSchema,aTable;
                        ::dbtools::qualifiedNameComponents( m_xMetaData, sTableName, aCatalog, aSchema, aTable, ::dbtools::EComposeRule::InDataManipulation );
                        sTableName = ::dbtools::composeTableName( m_xMetaData, aCatalog, aSchema, aTable, true, ::dbtools::EComposeRule::InDataManipulation );
                    }
                }
                xColumn->getPropertyValue(PROPERTY_REALNAME)    >>= _rFilter.Name;
                static constexpr OUString sAgg = u"AggregateFunction"_ustr;
                if ( xInfo->hasPropertyByName(sAgg) )
                    xColumn->getPropertyValue(sAgg) >>= bHaving;
                static constexpr OUString sFunction = u"Function"_ustr;
                if ( xInfo->hasPropertyByName(sFunction) )
                    xColumn->getPropertyValue(sFunction) >>= bFunction;
            }
            if ( !bFunction )
            {
                const OUString aQuote    = m_xMetaData.is() ? m_xMetaData->getIdentifierQuoteString() : OUString();
                _rFilter.Name = ::dbtools::quoteName(aQuote,_rFilter.Name);
                if ( !sTableName.isEmpty() )
                {
                    sTableName += "." + _rFilter.Name;
                    _rFilter.Name = sTableName;
                }
            }
        }
    }
    catch(const Exception&)
    {
    }
 
    _rFilter.Handle = GetOSQLPredicateType( _rComp.get_active_text() );
    if ( SQLFilterOperator::SQLNULL != _rFilter.Handle && _rFilter.Handle != SQLFilterOperator::NOT_SQLNULL )
    {
        OUString sPredicateValue;
        m_aPredicateInput.getPredicateValue( _rValue.get_text(), getMatchingColumn( _rValue ) ) >>= sPredicateValue;
        if ( _rFilter.Handle == SQLFilterOperator::LIKE ||
             _rFilter.Handle == SQLFilterOperator::NOT_LIKE )
            ::Replace_OS_PlaceHolder( sPredicateValue );
        _rFilter.Value <<= sPredicateValue;
    }
    return bHaving;
}
 
Reference< XPropertySet > DlgFilterCrit::getColumn( const OUString& _rFieldName ) const
{
    Reference< XPropertySet > xColumn;
    try
    {
        if ( m_xColumns.is() && m_xColumns->hasByName( _rFieldName ) )
            m_xColumns->getByName( _rFieldName ) >>= xColumn;
 
        Reference< XNameAccess> xColumns = Reference< XColumnsSupplier >(m_xQueryComposer,UNO_QUERY_THROW)->getColumns();
        if ( xColumns.is() && !xColumn.is() )
        {
            for (auto& colName : xColumns->getElementNames())
            {
                Reference<XPropertySet> xProp(xColumns->getByName(colName), UNO_QUERY);
                if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME) )
                {
                    OUString sRealName;
                    xProp->getPropertyValue(PROPERTY_REALNAME)  >>= sRealName;
                    if ( sRealName == _rFieldName )
                    {
                        if (m_xColumns.is() && m_xColumns->hasByName(colName))
                            m_xColumns->getByName(colName) >>= xColumn;
                        break;
                    }
                }
            }
        }
    }
    catch( const Exception& )
    {
        DBG_UNHANDLED_EXCEPTION("dbaccess");
    }
 
    return xColumn;
}
 
Reference< XPropertySet > DlgFilterCrit::getQueryColumn( const OUString& _rFieldName ) const
{
    Reference< XPropertySet > xColumn;
    try
    {
        Reference< XNameAccess> xColumns = Reference< XColumnsSupplier >(m_xQueryComposer,UNO_QUERY_THROW)->getColumns();
        if ( xColumns.is() && xColumns->hasByName( _rFieldName ) )
            xColumns->getByName( _rFieldName ) >>= xColumn;
    }
    catch( const Exception& )
    {
        DBG_UNHANDLED_EXCEPTION("dbaccess");
    }
 
    return xColumn;
}
 
Reference< XPropertySet > DlgFilterCrit::getMatchingColumn( const weld::Entry& _rValueInput ) const
{
    // the name
    OUString sField;
    if ( &_rValueInput == m_xET_WHEREVALUE1.get() )
    {
        sField = m_xLB_WHEREFIELD1->get_active_text();
    }
    else if ( &_rValueInput == m_xET_WHEREVALUE2.get() )
    {
        sField = m_xLB_WHEREFIELD2->get_active_text();
    }
    else if ( &_rValueInput == m_xET_WHEREVALUE3.get() )
    {
        sField = m_xLB_WHEREFIELD3->get_active_text();
    }
    else {
        OSL_FAIL( "DlgFilterCrit::getMatchingColumn: invalid event source!" );
    }
 
    // the field itself
    return getColumn( sField );
}
 
IMPL_LINK( DlgFilterCrit, PredicateLoseFocus, weld::Widget&, rControl, void )
{
    weld::Entry& rField = dynamic_cast<weld::Entry&>(rControl);
    // retrieve the field affected
    Reference< XPropertySet> xColumn(getMatchingColumn(rField));
    // and normalize its content
    if ( xColumn.is() )
    {
        OUString sText(rField.get_text());
        m_aPredicateInput.normalizePredicateString(sText, xColumn);
        rField.set_text(sText);
    }
}
 
void DlgFilterCrit::SetLine( int nIdx, const PropertyValue& _rItem, bool _bOr )
{
    OUString aStr;
    _rItem.Value >>= aStr;
    if ( _rItem.Handle == SQLFilterOperator::LIKE ||
         _rItem.Handle == SQLFilterOperator::NOT_LIKE )
        ::Replace_SQL_PlaceHolder(aStr);
    aStr = comphelper::string::stripEnd(aStr, ' ');
 
    Reference< XPropertySet > xColumn = getColumn( _rItem.Name );
 
    // to make sure that we only set first three
    weld::ComboBox* pColumnListControl =  nullptr;
    weld::ComboBox* pPredicateListControl = nullptr;
    weld::Entry* pPredicateValueControl = nullptr;
    switch( nIdx )
    {
        case 0:
            pColumnListControl = m_xLB_WHEREFIELD1.get();
            pPredicateListControl = m_xLB_WHERECOMP1.get();
            pPredicateValueControl = m_xET_WHEREVALUE1.get();
            break;
        case 1:
            m_xLB_WHERECOND2->set_active( _bOr ? 1 : 0 );
 
            pColumnListControl = m_xLB_WHEREFIELD2.get();
            pPredicateListControl = m_xLB_WHERECOMP2.get();
            pPredicateValueControl = m_xET_WHEREVALUE2.get();
            break;
        case 2:
            m_xLB_WHERECOND3->set_active( _bOr ? 1 : 0 );
 
            pColumnListControl = m_xLB_WHEREFIELD3.get();
            pPredicateListControl = m_xLB_WHERECOMP3.get();
            pPredicateValueControl = m_xET_WHEREVALUE3.get();
            break;
    }
 
    if ( !(pColumnListControl && pPredicateListControl && pPredicateValueControl) )
        return;
 
    OUString sName;
    if ( xColumn.is() )
        xColumn->getPropertyValue(PROPERTY_NAME) >>= sName;
    else
        sName = _rItem.Name;
    // select the appropriate field name
    SelectField( *pColumnListControl, sName );
    ListSelectHdl( *pColumnListControl );
 
    // select the appropriate condition
    pPredicateListControl->set_active( GetSelectionPos( _rItem.Handle, *pPredicateListControl ) );
 
    // initially normalize this value
    OUString aString( aStr );
    m_aPredicateInput.normalizePredicateString( aString, xColumn );
    pPredicateValueControl->set_text( aString );
}
 
void DlgFilterCrit::SelectField(weld::ComboBox& rBox, std::u16string_view rField)
{
    const sal_Int32 nCnt = rBox.get_count();
 
    for( sal_Int32 i=0 ; i<nCnt ; i++ )
    {
        if (rBox.get_text(i) == rField)
        {
            rBox.set_active(i);
            return;
        }
    }
 
    rBox.set_active(0);
}
 
void DlgFilterCrit::EnableLines()
{
    // enabling/disabling of whole lines
    if( m_xLB_WHEREFIELD1->get_active() == 0 )
    {
        m_xLB_WHEREFIELD2->set_sensitive(false);
        m_xLB_WHERECOND2->set_sensitive(false);
        m_xLB_WHERECOMP2->set_sensitive(false);
        m_xET_WHEREVALUE2->set_sensitive(false);
 
        m_xLB_WHEREFIELD3->set_sensitive(false);
        m_xLB_WHERECOND3->set_sensitive(false);
        m_xLB_WHERECOMP3->set_sensitive(false);
        m_xET_WHEREVALUE3->set_sensitive(false);
    }
    else
    {
        m_xLB_WHEREFIELD2->set_sensitive(true);
        m_xLB_WHERECOND2->set_sensitive(true);
        m_xLB_WHERECOMP2->set_sensitive(true);
        m_xET_WHEREVALUE2->set_sensitive(true);
 
        m_xLB_WHEREFIELD3->set_sensitive(true);
        m_xLB_WHERECOND3->set_sensitive(true);
        m_xLB_WHERECOMP3->set_sensitive(true);
        m_xET_WHEREVALUE3->set_sensitive(true);
    }
 
    if( m_xLB_WHEREFIELD2->get_active() == 0 )
    {
        m_xLB_WHEREFIELD3->set_sensitive(false);
        m_xLB_WHERECOND3->set_sensitive(false);
        m_xLB_WHERECOMP3->set_sensitive(false);
        m_xET_WHEREVALUE3->set_sensitive(false);
    }
    else
    {
        m_xLB_WHEREFIELD3->set_sensitive(true);
        m_xLB_WHERECOND3->set_sensitive(true);
        m_xLB_WHERECOMP3->set_sensitive(true);
        m_xET_WHEREVALUE3->set_sensitive(true);
    }
 
    // comparison field equal to NOENTRY
    if( m_xLB_WHEREFIELD1->get_active() == 0 )
    {
        m_xLB_WHERECOMP1->set_sensitive(false);
        m_xET_WHEREVALUE1->set_sensitive(false);
    }
    else
    {
        m_xLB_WHEREFIELD1->set_sensitive(true);
        m_xLB_WHERECOMP1->set_sensitive(true);
        m_xET_WHEREVALUE1->set_sensitive(true);
    }
 
    if( m_xLB_WHEREFIELD2->get_active() == 0 )
    {
        m_xLB_WHERECOND2->set_sensitive(false);
        m_xLB_WHERECOMP2->set_sensitive(false);
        m_xET_WHEREVALUE2->set_sensitive(false);
    }
    else
    {
        m_xLB_WHERECOND2->set_sensitive(true);
        m_xLB_WHEREFIELD2->set_sensitive(true);
        m_xLB_WHERECOMP2->set_sensitive(true);
        m_xET_WHEREVALUE2->set_sensitive(true);
    }
 
    if( m_xLB_WHEREFIELD3->get_active() == 0 )
    {
        m_xLB_WHERECOND3->set_sensitive(false);
        m_xLB_WHERECOMP3->set_sensitive(false);
        m_xET_WHEREVALUE3->set_sensitive(false);
    }
    else
    {
        m_xLB_WHERECOND3->set_sensitive(true);
        m_xLB_WHERECOND3->set_sensitive(true);
        m_xLB_WHEREFIELD3->set_sensitive(true);
        m_xLB_WHERECOMP3->set_sensitive(true);
        m_xET_WHEREVALUE3->set_sensitive(true);
    }
 
    // comparison operator equal to ISNULL or ISNOTNULL
    if(m_xLB_WHERECOMP1->get_count() > 2 &&
        ((m_xLB_WHERECOMP1->get_active() == m_xLB_WHERECOMP1->get_count()-1) ||
         (m_xLB_WHERECOMP1->get_active() == m_xLB_WHERECOMP1->get_count()-2)) )
        m_xET_WHEREVALUE1->set_sensitive(false);
 
    if(m_xLB_WHERECOMP2->get_count() > 2 &&
        ((m_xLB_WHERECOMP2->get_active() == m_xLB_WHERECOMP2->get_count()-1) ||
         (m_xLB_WHERECOMP2->get_active() == m_xLB_WHERECOMP2->get_count()-2)) )
        m_xET_WHEREVALUE2->set_sensitive(false);
 
    if(m_xLB_WHERECOMP3->get_count() > 2 &&
        ((m_xLB_WHERECOMP3->get_active() == m_xLB_WHERECOMP3->get_count()-1) ||
         (m_xLB_WHERECOMP3->get_active() == m_xLB_WHERECOMP3->get_count()-2)) )
        m_xET_WHEREVALUE3->set_sensitive(false);
}
 
IMPL_LINK( DlgFilterCrit, ListSelectHdl, weld::ComboBox&, rListBox, void )
{
    OUString aName;
    weld::ComboBox* pComp;
    if(&rListBox == m_xLB_WHEREFIELD1.get())
    {
        aName = m_xLB_WHEREFIELD1->get_active_text();
        pComp = m_xLB_WHERECOMP1.get();
    }
    else if(&rListBox == m_xLB_WHEREFIELD2.get())
    {
        aName = m_xLB_WHEREFIELD2->get_active_text();
        pComp = m_xLB_WHERECOMP2.get();
    }
    else
    {
        aName = m_xLB_WHEREFIELD3->get_active_text();
        pComp = m_xLB_WHERECOMP3.get();
    }
 
    pComp->clear();
 
    Reference<XPropertySet> xColumn = getColumn(aName);
    if ( xColumn.is() )
    {
        sal_Int32 nDataType = 0;
        xColumn->getPropertyValue(PROPERTY_TYPE) >>= nDataType;
        sal_Int32 eColumnSearch = dbtools::getSearchColumnFlag(m_xConnection,nDataType);
 
        if(eColumnSearch  == ColumnSearch::FULL)
        {
            for(size_t i=0;i < m_aSTR_COMPARE_OPERATORS.size(); i++)
                pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]);
        }
        else if(eColumnSearch == ColumnSearch::CHAR)
        {
            for(sal_Int32 i=6; i<10; i++)
                pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]);
        }
        else if(eColumnSearch == ColumnSearch::BASIC)
        {
            size_t i;
            for( i = 0; i < 6; i++ )
                pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]);
            for(i=8; i < m_aSTR_COMPARE_OPERATORS.size(); ++i)
                pComp->append_text(m_aSTR_COMPARE_OPERATORS[i]);
        }
        else
        {
            OSL_FAIL("DlgFilterCrit::ListSelectHdl: This column should not exist at all.");
        }
    }
    pComp->set_active(0);
 
    EnableLines();
}
 
IMPL_LINK_NOARG(DlgFilterCrit, ListSelectCompHdl, weld::ComboBox&, void)
{
    EnableLines();
}
 
void DlgFilterCrit::BuildWherePart()
{
    Sequence<Sequence<PropertyValue> > aFilter(1),aHaving(1);
 
    if( m_xLB_WHEREFIELD1->get_active() != 0 )
    {
        PropertyValue aValue;
        if ( getCondition(*m_xLB_WHEREFIELD1,*m_xLB_WHERECOMP1,*m_xET_WHEREVALUE1,aValue) )
        {
            aHaving = { { std::move(aValue) } };
        }
        else
        {
            aFilter = { { std::move(aValue) } };
        }
    }
 
    if( m_xLB_WHEREFIELD2->get_active() != 0 )
    {
        PropertyValue aValue;
        Sequence<Sequence<PropertyValue> >& _rValues = aFilter;
        if ( getCondition(*m_xLB_WHEREFIELD2,*m_xLB_WHERECOMP2,*m_xET_WHEREVALUE2,aValue) )
            _rValues = aHaving;
        if ( m_xLB_WHERECOND2->get_active() )
            _rValues.realloc( _rValues.getLength() + 1);
        sal_Int32 nPos = _rValues.getLength() - 1;
        sal_Int32 nAndPos = _rValues[nPos].getLength();
        auto pValues = _rValues.getArray();
        pValues[nPos].realloc( _rValues[nPos].getLength() + 1);
        pValues[nPos].getArray()[nAndPos] = std::move(aValue);
    }
 
    if( m_xLB_WHEREFIELD3->get_active() != 0 )
    {
        PropertyValue aValue;
        Sequence<Sequence<PropertyValue> >& _rValues = aFilter;
        if ( getCondition(*m_xLB_WHEREFIELD3,*m_xLB_WHERECOMP3,*m_xET_WHEREVALUE3,aValue) )
            _rValues = aHaving;
        if (m_xLB_WHERECOND3->get_active())
            _rValues.realloc( _rValues.getLength() + 1);
        sal_Int32 nPos = _rValues.getLength() - 1;
        sal_Int32 nAndPos = _rValues[nPos].getLength();
        auto pValues = _rValues.getArray();
        pValues[nPos].realloc( _rValues[nPos].getLength() + 1);
        pValues[nPos].getArray()[nAndPos] = std::move(aValue);
    }
    try
    {
        m_xQueryComposer->setStructuredFilter(aFilter);
        m_xQueryComposer->setStructuredHavingClause(aHaving);
    }
    catch(const Exception&)
    {
        DBG_UNHANDLED_EXCEPTION("dbaccess");
    }
}
 
void DlgFilterCrit::fillLines(int &i, const Sequence< Sequence< PropertyValue > >& _aValues)
{
    bool bOr(i != 0); // WHERE clause and HAVING clause are always ANDed, nor ORed
    for (auto& rOr : _aValues)
    {
        for (auto& rAnd : rOr)
        {
            SetLine(i++, rAnd, bOr);
            bOr = false;
        }
        bOr=true;
    }
}
 
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

V547 Expression '!bIsSearchable' is always false.

V547 Expression '!bFunction' is always true.

V547 Expression is always false.

V547 Expression is always false.

V547 Expression is always false.

V1048 The 'nPredicateType' variable was assigned the same value.