Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sc/source/ui/dbgui/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 54 kB image not shown  

Quelle  filtdlg.cxx   Sprache: C

 
/* -*- 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 <sfx2/dispatch.hxx>
#include <sal/log.hxx>

#include <uiitems.hxx>
#include <reffact.hxx>
#include <viewdata.hxx>
#include <document.hxx>
#include <docsh.hxx>
#include <scresid.hxx>
#include <queryentry.hxx>

#include <foptmgr.hxx>

#include <globstr.hrc>
#include <strings.hrc>

#include <filtdlg.hxx>
#include <svx/colorwindow.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>
#include <vcl/virdev.hxx>
#include <vcl/weld.hxx>
#include <svl/numformat.hxx>
#include <svl/sharedstringpool.hxx>

#include <limits>

#define QUERY_ENTRY_COUNT 4
#define INVALID_HEADER_POS std::numeric_limits<size_t>::max()

ScFilterDlg::EntryList::EntryList() :
    mnHeaderPos(INVALID_HEADER_POS) {}

ScFilterDlg::ScFilterDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent, ScViewData& rData,
    const SfxItemSet& rArgSet)
    : ScAnyRefDlgController(pB, pCW, pParent,
        u"modules/scalc/ui/standardfilterdialog.ui"_ustr, u"StandardFilterDialog"_ustr)
    , aStrUndefined(ScResId(SCSTR_UNDEFINED))
    , aStrNone(ScResId(SCSTR_NONE))
    , aStrEmpty(ScResId(SCSTR_FILTER_EMPTY))
    , aStrNotEmpty(ScResId(SCSTR_FILTER_NOTEMPTY))
    , aStrColumn(ScResId(SCSTR_COLUMN_LETTER))
    , aStrFontColor(ScResId(SCSTR_FILTER_FONT_COLOR_COND))
    , aStrBackgroundColor(ScResId(SCSTR_FILTER_BACKGROUND_COLOR_COND))
    , nWhichQuery(rArgSet.GetPool()->GetWhichIDFromSlotID(SID_QUERY))
    , theQueryData(static_cast<const ScQueryItem&>(rArgSet.Get(nWhichQuery)).GetQueryData())
    , rViewData(rData)
    , rDoc(rViewData.GetDocument())
    , nSrcTab(rViewData.GetTabNo())
    , bRefInputMode(false)
    , m_xLbConnect1(m_xBuilder->weld_combo_box(u"connect1"_ustr))
    , m_xLbField1(m_xBuilder->weld_combo_box(u"field1"_ustr))
    , m_xLbCond1(m_xBuilder->weld_combo_box(u"cond1"_ustr))
    , m_xEdVal1(m_xBuilder->weld_combo_box(u"val1"_ustr))
    , m_xLbColor1(m_xBuilder->weld_combo_box(u"color1"_ustr))
    , m_xBtnRemove1(m_xBuilder->weld_button(u"remove1"_ustr))
    , m_xLbConnect2(m_xBuilder->weld_combo_box(u"connect2"_ustr))
    , m_xLbField2(m_xBuilder->weld_combo_box(u"field2"_ustr))
    , m_xLbCond2(m_xBuilder->weld_combo_box(u"cond2"_ustr))
    , m_xEdVal2(m_xBuilder->weld_combo_box(u"val2"_ustr))
    , m_xLbColor2(m_xBuilder->weld_combo_box(u"color2"_ustr))
    , m_xBtnRemove2(m_xBuilder->weld_button(u"remove2"_ustr))
    , m_xLbConnect3(m_xBuilder->weld_combo_box(u"connect3"_ustr))
    , m_xLbField3(m_xBuilder->weld_combo_box(u"field3"_ustr))
    , m_xLbCond3(m_xBuilder->weld_combo_box(u"cond3"_ustr))
    , m_xEdVal3(m_xBuilder->weld_combo_box(u"val3"_ustr))
    , m_xLbColor3(m_xBuilder->weld_combo_box(u"color3"_ustr))
    , m_xBtnRemove3(m_xBuilder->weld_button(u"remove3"_ustr))
    , m_xLbConnect4(m_xBuilder->weld_combo_box(u"connect4"_ustr))
    , m_xLbField4(m_xBuilder->weld_combo_box(u"field4"_ustr))
    , m_xLbCond4(m_xBuilder->weld_combo_box(u"cond4"_ustr))
    , m_xEdVal4(m_xBuilder->weld_combo_box(u"val4"_ustr))
    , m_xLbColor4(m_xBuilder->weld_combo_box(u"color4"_ustr))
    , m_xBtnRemove4(m_xBuilder->weld_button(u"remove4"_ustr))
    , m_xContents(m_xBuilder->weld_widget(u"grid"_ustr))
    , m_xScrollBar(m_xBuilder->weld_scrolled_window(u"scrollbar"_ustr, true))
    , m_xExpander(m_xBuilder->weld_expander(u"more"_ustr))
    , m_xBtnClear(m_xBuilder->weld_button(u"clear"_ustr))
    , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr))
    , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr))
    , m_xBtnCase(m_xBuilder->weld_check_button(u"case"_ustr))
    , m_xBtnRegExp(m_xBuilder->weld_check_button(u"regexp"_ustr))
    , m_xBtnHeader(m_xBuilder->weld_check_button(u"header"_ustr))
    , m_xBtnUnique(m_xBuilder->weld_check_button(u"unique"_ustr))
    , m_xBtnCopyResult(m_xBuilder->weld_check_button(u"copyresult"_ustr))
    , m_xLbCopyArea(m_xBuilder->weld_combo_box(u"lbcopyarea"_ustr))
    , m_xEdCopyArea(new formula::RefEdit(m_xBuilder->weld_entry(u"edcopyarea"_ustr)))
    , m_xRbCopyArea(new formula::RefButton(m_xBuilder->weld_button(u"rbcopyarea"_ustr)))
    , m_xBtnDestPers(m_xBuilder->weld_check_button(u"destpers"_ustr))
    , m_xFtDbAreaLabel(m_xBuilder->weld_label(u"dbarealabel"_ustr))
    , m_xFtDbArea(m_xBuilder->weld_label(u"dbarea"_ustr))
{
    m_xExpander->connect_expanded(LINK(this, ScFilterDlg, MoreExpandedHdl));
    m_xEdCopyArea->SetReferences(this, m_xFtDbAreaLabel.get());
    m_xRbCopyArea->SetReferences(this, m_xEdCopyArea.get());

    assert(m_xLbCond1->find_text(aStrFontColor) != -1);
    assert(m_xLbCond1->find_text(aStrBackgroundColor) != -1);

    Init();

    // Hack: RefInput control
    pTimer.reset( new Timer("ScFilterTimer") );
    pTimer->SetTimeout( 50 ); // Wait 50ms
    pTimer->SetInvokeHandler( LINK( this, ScFilterDlg, TimeOutHdl ) );
}

ScFilterDlg::~ScFilterDlg()
{
    pOptionsMgr.reset();
    pOutItem.reset();

    // Hack: RefInput control
    pTimer->Stop();
    pTimer.reset();
}

namespace {
VirtualDevice* lcl_getColorImage(const Color &rColor)
{
    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
    Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize());

    VclPtrInstance<VirtualDevice> xDevice;
    xDevice->SetOutputSize(aImageSize);
    const tools::Rectangle aRect(Point(0, 0), aImageSize);
    if (rColor == COL_NONE_COLOR)
    {
        const Color aW(COL_WHITE);
        const Color aG(0xef, 0xef, 0xef);
        xDevice->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), 8, aW, aG);
        xDevice->SetFillColor();
    }
    else
    {
        xDevice->SetFillColor(rColor);
    }

    xDevice->DrawRect(aRect);

    return xDevice.get();
}
}

void ScFilterDlg::Init()
{
    m_xBtnClear->connect_clicked   ( LINK( this, ScFilterDlg, BtnClearHdl ) );
    m_xBtnOk->connect_clicked      ( LINK( this, ScFilterDlg, EndDlgHdl ) );
    m_xBtnCancel->connect_clicked  ( LINK( this, ScFilterDlg, EndDlgHdl ) );
    m_xBtnHeader->connect_toggled  ( LINK( this, ScFilterDlg, CheckBoxHdl ) );
    m_xBtnCase->connect_toggled    ( LINK( this, ScFilterDlg, CheckBoxHdl ) );

    m_xLbField1->connect_changed  ( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbField2->connect_changed  ( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbField3->connect_changed  ( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbField4->connect_changed  ( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbConnect1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbConnect2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbConnect3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbConnect4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );

    m_xLbField1->append_text(u"0000000000"_ustr);
    m_xLbField1->set_active(0);
    auto nPrefWidth = m_xLbField1->get_preferred_size().Width();
    m_xLbField1->clear();

    m_xLbField1->set_size_request(nPrefWidth, -1);
    m_xLbField2->set_size_request(nPrefWidth, -1);
    m_xLbField3->set_size_request(nPrefWidth, -1);
    m_xLbField4->set_size_request(nPrefWidth, -1);

    m_xLbCond1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbCond2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbCond3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbCond4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );

    m_xLbColor1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbColor2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbColor3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
    m_xLbColor4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );

    m_xBtnRemove1->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
    m_xBtnRemove2->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
    m_xBtnRemove3->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
    m_xBtnRemove4->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );

    // for easier access:
    maFieldLbArr.reserve(QUERY_ENTRY_COUNT);
    maFieldLbArr.push_back(m_xLbField1.get());
    maFieldLbArr.push_back(m_xLbField2.get());
    maFieldLbArr.push_back(m_xLbField3.get());
    maFieldLbArr.push_back(m_xLbField4.get());
    maValueEdArr.reserve(QUERY_ENTRY_COUNT);
    maValueEdArr.push_back(m_xEdVal1.get());
    maValueEdArr.push_back(m_xEdVal2.get());
    maValueEdArr.push_back(m_xEdVal3.get());
    maValueEdArr.push_back(m_xEdVal4.get());
    maCondLbArr.reserve(QUERY_ENTRY_COUNT);
    maCondLbArr.push_back(m_xLbCond1.get());
    maCondLbArr.push_back(m_xLbCond2.get());
    maCondLbArr.push_back(m_xLbCond3.get());
    maCondLbArr.push_back(m_xLbCond4.get());
    maConnLbArr.reserve(QUERY_ENTRY_COUNT);
    maConnLbArr.push_back(m_xLbConnect1.get());
    maConnLbArr.push_back(m_xLbConnect2.get());
    maConnLbArr.push_back(m_xLbConnect3.get());
    maConnLbArr.push_back(m_xLbConnect4.get());
    maColorLbArr.reserve(QUERY_ENTRY_COUNT);
    maColorLbArr.push_back(m_xLbColor1.get());
    maColorLbArr.push_back(m_xLbColor2.get());
    maColorLbArr.push_back(m_xLbColor3.get());
    maColorLbArr.push_back(m_xLbColor4.get());
    maRemoveBtnArr.reserve(QUERY_ENTRY_COUNT);
    maRemoveBtnArr.push_back(m_xBtnRemove1.get());
    maRemoveBtnArr.push_back(m_xBtnRemove2.get());
    maRemoveBtnArr.push_back(m_xBtnRemove3.get());
    maRemoveBtnArr.push_back(m_xBtnRemove4.get());

    // Option initialization:
    pOptionsMgr.reset( new ScFilterOptionsMgr(
                            rViewData,
                            theQueryData,
                            m_xBtnCase.get(),
                            m_xBtnRegExp.get(),
                            m_xBtnHeader.get(),
                            m_xBtnUnique.get(),
                            m_xBtnCopyResult.get(),
                            m_xBtnDestPers.get(),
                            m_xLbCopyArea.get(),
                            m_xEdCopyArea.get(),
                            m_xRbCopyArea.get(),
                            m_xFtDbAreaLabel.get(),
                            m_xFtDbArea.get(),
                            aStrUndefined ) );
    // Read in field lists and select entries

    FillFieldLists();

    for (size_t i = 0; i < QUERY_ENTRY_COUNT; ++i)
    {
        OUString aValStr;
        size_t nCondPos = 0;
        size_t nFieldSelPos = 0;

        maColorLbArr[i]->set_visible(false);

        ScQueryEntry& rEntry = theQueryData.GetEntry(i);
        if ( rEntry.bDoQuery )
        {
            nCondPos = static_cast<size_t>(rEntry.eOp);
            nFieldSelPos = GetFieldSelPos( static_cast<SCCOL>(rEntry.nField) );
            if (rEntry.IsQueryByEmpty())
            {
                aValStr = aStrEmpty;
                maCondLbArr[i]->set_sensitive(false);
            }
            else if (rEntry.IsQueryByNonEmpty())
            {
                aValStr = aStrNotEmpty;
                maCondLbArr[i]->set_sensitive(false);
            }
            else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor())
            {
                nCondPos = maCondLbArr[i]->find_text(
                    rEntry.IsQueryByTextColor() ? aStrFontColor : aStrBackgroundColor);
                maValueEdArr[i]->set_visible(false);
                maColorLbArr[i]->set_visible(true);
                maColorLbArr[i]->set_sensitive(true);
            }
            else
            {
                const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
                OUString aQueryStr = rItem.maString.getString();
                SetValString(aQueryStr, rItem, aValStr);
            }
        }
        else if ( i == 0 )
        {
            nFieldSelPos = GetFieldSelPos(rViewData.GetCurX());
            rEntry.nField = nFieldSelPos ? (theQueryData.nCol1 +
                static_cast<SCCOL>(nFieldSelPos) - 1) : static_cast<SCCOL>(0);
            rEntry.bDoQuery=true;
            if (maRefreshExceptQuery.size() < i + 1)
                maRefreshExceptQuery.resize(i + 1, false);
            maRefreshExceptQuery[i] = true;

        }
        maFieldLbArr[i]->set_active( nFieldSelPos );
        maCondLbArr [i]->set_active( nCondPos );
        maValueEdArr[i]->set_entry_text( aValStr );
        maValueEdArr[i]->set_entry_completion(false);
        maValueEdArr[i]->connect_changed( LINK( this, ScFilterDlg, ValModifyHdl ) );
        UpdateValueList(i+1);
        UpdateColorList(i+1);
    }

    m_xScrollBar->connect_vadjustment_changed( LINK( this, ScFilterDlg, ScrollHdl ) );
    m_xScrollBar->vadjustment_configure(0, 0, 8, 1, 3, 4);
    Size aSize(m_xContents->get_preferred_size());
    m_xContents->set_size_request(aSize.Width(), aSize.Height());

    m_xLbConnect1->hide();
    // Disable/Enable Logic:

    (m_xLbField1->get_active() != 0)
    && (m_xLbField2->get_active() != 0)
        ? m_xLbConnect2->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(1).eConnect) )
        : m_xLbConnect2->set_active(-1);

    (m_xLbField2->get_active() != 0)
    && (m_xLbField3->get_active() != 0)
        ? m_xLbConnect3->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(2).eConnect) )
        : m_xLbConnect3->set_active(-1);

    (m_xLbField3->get_active() != 0)
    && (m_xLbField4->get_active() != 0)
        ? m_xLbConnect4->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(3).eConnect) )
        : m_xLbConnect4->set_active(-1);
    if ( m_xLbField1->get_active() == 0 )
    {
        m_xLbConnect2->set_sensitive(false);
        m_xLbField2->set_sensitive(false);
        m_xLbCond2->set_sensitive(false);
        m_xEdVal2->set_sensitive(false);
        m_xLbColor2->set_sensitive(false);
        m_xBtnRemove2->set_sensitive(false);
    }
    else if ( m_xLbConnect2->get_active() == -1 )
    {
        m_xLbField2->set_sensitive(false);
        m_xLbCond2->set_sensitive(false);
        m_xEdVal2->set_sensitive(false);
        m_xLbColor2->set_sensitive(false);
        m_xBtnRemove2->set_sensitive(false);
    }

    if ( m_xLbField2->get_active() == 0 )
    {
        m_xLbConnect3->set_sensitive(false);
        m_xLbField3->set_sensitive(false);
        m_xLbCond3->set_sensitive(false);
        m_xEdVal3->set_sensitive(false);
        m_xLbColor3->set_sensitive(false);
        m_xBtnRemove3->set_sensitive(false);
    }
    else if ( m_xLbConnect3->get_active() == -1 )
    {
        m_xLbField3->set_sensitive(false);
        m_xLbCond3->set_sensitive(false);
        m_xEdVal3->set_sensitive(false);
        m_xLbColor3->set_sensitive(false);
        m_xBtnRemove3->set_sensitive(false);
    }
    if ( m_xLbField3->get_active() == 0 )
    {
        m_xLbConnect4->set_sensitive(false);
        m_xLbField4->set_sensitive(false);
        m_xLbCond4->set_sensitive(false);
        m_xEdVal4->set_sensitive(false);
        m_xLbColor4->set_sensitive(false);
        m_xBtnRemove4->set_sensitive(false);
    }
    else if ( m_xLbConnect4->get_active() == -1 )
    {
        m_xLbField4->set_sensitive(false);
        m_xLbCond4->set_sensitive(false);
        m_xEdVal4->set_sensitive(false);
        m_xLbColor4->set_sensitive(false);
        m_xBtnRemove4->set_sensitive(false);
    }

    m_xEdVal1->set_entry_width_chars(10);
    m_xEdVal2->set_entry_width_chars(10);
    m_xEdVal3->set_entry_width_chars(10);
    m_xEdVal4->set_entry_width_chars(10);

    if (rDoc.GetChangeTrack() != nullptr)
        m_xBtnCopyResult->set_sensitive(false);
}

void ScFilterDlg::Close()
{
    rViewData.GetDocShell().CancelAutoDBRange();

    DoClose( ScFilterDlgWrapper::GetChildWindowId() );
}

// Mouse-selected cell area becomes the new selection and is shown in the
// reference text box

void ScFilterDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
{
    if ( bRefInputMode )    // Only possible if in reference edit mode
    {
        if ( rRef.aStart != rRef.aEnd )
            RefInputStart( m_xEdCopyArea.get() );
        OUString aRefStr(rRef.aStart.Format(ScRefFlags::ADDR_ABS_3D, &rDocP, rDocP.GetAddressConvention()));
        m_xEdCopyArea->SetRefString( aRefStr );
    }
}

void ScFilterDlg::SetActive()
{
    if ( bRefInputMode )
    {
        m_xEdCopyArea->GrabFocus();
        m_xEdCopyArea->GetModifyHdl().Call( *m_xEdCopyArea );
    }
    else
        m_xDialog->grab_focus();

    RefInputDone();
}

void ScFilterDlg::FillFieldLists()
{
    m_xLbField1->freeze();
    m_xLbField2->freeze();
    m_xLbField3->freeze();
    m_xLbField4->freeze();

    m_xLbField1->clear();
    m_xLbField2->clear();
    m_xLbField3->clear();
    m_xLbField4->clear();
    m_xLbField1->append_text( aStrNone );
    m_xLbField2->append_text( aStrNone );
    m_xLbField3->append_text( aStrNone );
    m_xLbField4->append_text( aStrNone );

    OUString aFieldName;
    SCTAB   nTab        = nSrcTab;
    SCCOL   nFirstCol   = theQueryData.nCol1;
    SCROW   nFirstRow   = theQueryData.nRow1;
    SCCOL   nMaxCol     = theQueryData.nCol2;
    SCCOL   col = 0;

    for ( col=nFirstCol; col<=nMaxCol; col++ )
    {
        aFieldName = rDoc.GetString(col, nFirstRow, nTab);
        if (!m_xBtnHeader->get_active() || aFieldName.isEmpty())
        {
            aFieldName = ScGlobal::ReplaceOrAppend( aStrColumn, u"%1", ScColToAlpha( col ));
        }
        m_xLbField1->append_text( aFieldName );
        m_xLbField2->append_text( aFieldName );
        m_xLbField3->append_text( aFieldName );
        m_xLbField4->append_text( aFieldName );
    }

    m_xLbField4->thaw();
    m_xLbField3->thaw();
    m_xLbField2->thaw();
    m_xLbField1->thaw();
}

void ScFilterDlg::UpdateValueList( size_t nList )
{
    bool bCaseSens = m_xBtnCase->get_active();

    if (nList > 0 && nList <= QUERY_ENTRY_COUNT)
    {
        weld::ComboBox* pValList = maValueEdArr[nList-1];
        const sal_Int32 nFieldSelPos = maFieldLbArr[nList-1]->get_active();
        OUString aCurValue = pValList->get_active_text();

        std::unique_ptr<weld::WaitObject> xWaiter;
        std::vector<weld::ComboBoxEntry> aEntries;
        aEntries.emplace_back(aStrNotEmpty);
        aEntries.emplace_back(aStrEmpty);

        if (nFieldSelPos)
        {
            xWaiter.reset(new weld::WaitObject(m_xDialog.get()));     // even if only the list box has content
            SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
            EntryList* pList = nullptr;
            if (!m_EntryLists.count(nColumn))
            {
                size_t nOffset = GetSliderPos();
                SCTAB nTab       = nSrcTab;
                SCROW nFirstRow = theQueryData.nRow1;
                SCROW nLastRow   = theQueryData.nRow2;
                if (maHasDates.size() < nOffset+nList)
                    maHasDates.resize(nOffset+nList, false);
                maHasDates[nOffset+nList-1] = false;

                // first without the first line
                std::pair<EntryListsMap::iterator, bool> r =
                    m_EntryLists.insert(std::make_pair(nColumn, std::make_unique<EntryList>()));
                if (!r.second)
                    // insertion failed.
                    return;

                pList = r.first->second.get();
                rDoc.GetFilterEntriesArea(
                    nColumn, nFirstRow+1, nLastRow,
                    nTab, bCaseSens, pList->maFilterEntries);
                maHasDates[nOffset+nList-1] = pList->maFilterEntries.mbHasDates;

                // Entry for the first line
                //! Entry (pHdrEntry) doesn't generate collection?

                pList->mnHeaderPos = INVALID_HEADER_POS;
                ScFilterEntries aHdrColl;
                rDoc.GetFilterEntriesArea(
                    nColumn, nFirstRow, nFirstRow, nTab, true, aHdrColl );
                if (!aHdrColl.empty())
                {
                    // See if the header value is already in the list.
                    std::vector<ScTypedStrData>::iterator itBeg = pList->maFilterEntries.begin(), itEnd = pList->maFilterEntries.end();
                    if (std::none_of(itBeg, itEnd, FindTypedStrData(aHdrColl.front(), bCaseSens)))
                    {
                        // Not in the list. Insert it.
                        pList->maFilterEntries.push_back(aHdrColl.front());
                        if (bCaseSens)
                            std::sort(pList->maFilterEntries.begin(), pList->maFilterEntries.end(), ScTypedStrData::LessCaseSensitive());
                        else
                            std::sort(pList->maFilterEntries.begin(), pList->maFilterEntries.end(), ScTypedStrData::LessCaseInsensitive());

                        // Record its position.
                        itBeg = pList->maFilterEntries.begin();
                        itEnd = pList->maFilterEntries.end();
                        auto it = std::find_if(itBeg, itEnd, FindTypedStrData(aHdrColl.front(), bCaseSens));
                        pList->mnHeaderPos = std::distance(itBeg, it);
                    }
                }
            }
            else
                pList = m_EntryLists[nColumn].get();

            assert(pList);

            for (const auto& rEntry : pList->maFilterEntries)
                aEntries.emplace_back(rEntry.GetString());
        }
        pValList->insert_vector(aEntries, false);
        pValList->set_entry_text(aCurValue);
    }

    UpdateHdrInValueList( nList );
}

void ScFilterDlg::UpdateHdrInValueList( size_t nList )
{
    //! GetText / SetText ??

    if (nList == 0 || nList > QUERY_ENTRY_COUNT)
        return;

    size_t nFieldSelPos = maFieldLbArr[nList-1]->get_active();
    if (!nFieldSelPos)
        return;

    SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
    if (!m_EntryLists.count(nColumn))
    {
        OSL_FAIL("column not yet initialized");
        return;
    }

    size_t const nPos = m_EntryLists[nColumn]->mnHeaderPos;
    if (nPos == INVALID_HEADER_POS)
        return;

    weld::ComboBox* pValList = maValueEdArr[nList-1];
    int nListPos = nPos + 2;                 // for "empty" and "non-empty"

    const ScTypedStrData& rHdrEntry = m_EntryLists[nColumn]->maFilterEntries.maStrData[nPos];

    const OUString& aHdrStr = rHdrEntry.GetString();
    bool bWasThere = nListPos < pValList->get_count() && aHdrStr == pValList->get_text(nListPos);
    bool bInclude = !m_xBtnHeader->get_active();

    if (bInclude)           // Include entry
    {
        if (!bWasThere)
            pValList->insert_text(nListPos, aHdrStr);
    }
    else                    // Omit entry
    {
        if (bWasThere)
            pValList->remove(nListPos);
    }
}

void ScFilterDlg::ClearValueList( size_t nList )
{
    if (nList > 0 && nList <= QUERY_ENTRY_COUNT)
    {
        weld::ComboBox* pValList = maValueEdArr[nList-1];
        pValList->clear();
        pValList->append_text( aStrNotEmpty );
        pValList->append_text( aStrEmpty );
        pValList->set_entry_text( OUString() );
    }
}

void ScFilterDlg::UpdateColorList(size_t nList)
{
    if (nList <= 0 || nList > QUERY_ENTRY_COUNT)
        return;

    size_t nPos = nList - 1;
    ScQueryEntry& rEntry = theQueryData.GetEntry(nPos);
    const sal_Int32 nFieldSelPos = maFieldLbArr[nPos]->get_active();
    if (!nFieldSelPos)
        return;

    SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
    EntryList* pList = m_EntryLists[nColumn].get();
    if (!pList)
        return;

    std::set<Color> aColors;
    OUString sSelectedCondition = maCondLbArr[nPos]->get_active_text();
    if (sSelectedCondition == aStrFontColor)
        aColors = pList->maFilterEntries.getTextColors();
    else if (sSelectedCondition == aStrBackgroundColor)
        aColors = pList->maFilterEntries.getBackgroundColors();
    else
        return;

    maColorLbArr[nPos]->clear();
    for (const auto& rColor : aColors)
    {
        OUString sId = rColor.AsRGBHexString();
        if (rColor == COL_AUTO)
        {
            OUString sText = sSelectedCondition == aStrFontColor
                                 ? ScResId(SCSTR_FILTER_AUTOMATIC_COLOR)
                                 : ScResId(SCSTR_FILTER_NO_FILL);
            maColorLbArr[nPos]->append(sId, sText);
        }
        else
        {
            VirtualDevice* pDev = lcl_getColorImage(rColor);
            maColorLbArr[nPos]->append(sId, OUString(), *pDev);
        }

        const auto& rItem = rEntry.GetQueryItem();
        if (rItem.maColor == rColor
            && ((sSelectedCondition == aStrFontColor && rItem.meType == ScQueryEntry::ByTextColor)
                || (sSelectedCondition == aStrBackgroundColor
                    && rItem.meType == ScQueryEntry::ByBackgroundColor)))
        {
            maColorLbArr[nPos]->set_active_id(sId);
        }
    }
}

size_t ScFilterDlg::GetFieldSelPos( SCCOL nField )
{
    if ( nField >= theQueryData.nCol1 && nField <= theQueryData.nCol2 )
        return static_cast<size_t>(nField - theQueryData.nCol1 + 1);
    else
        return 0;
}

ScQueryItem* ScFilterDlg::GetOutputItem()
{
    ScAddress       theCopyPos;
    ScQueryParam    theParam( theQueryData );
    bool            bCopyPosOk = false;

    if ( m_xBtnCopyResult->get_active() )
    {
        ScRefFlags nResult = theCopyPos.Parse(
            m_xEdCopyArea->GetText(), rDoc, rDoc.GetAddressConvention());
        bCopyPosOk = (nResult & ScRefFlags::VALID) == ScRefFlags::VALID;
    }

    if ( m_xBtnCopyResult->get_active() && bCopyPosOk )
    {
        theParam.bInplace   = false;
        theParam.nDestTab   = theCopyPos.Tab();
        theParam.nDestCol   = theCopyPos.Col();
        theParam.nDestRow   = theCopyPos.Row();
    }
    else
    {
        theParam.bInplace   = true;
        theParam.nDestTab   = 0;
        theParam.nDestCol   = 0;
        theParam.nDestRow   = 0;
    }

    theParam.bHasHeader     = m_xBtnHeader->get_active();
    theParam.bByRow         = true;
    theParam.bDuplicate     = !m_xBtnUnique->get_active();
    theParam.bCaseSens      = m_xBtnCase->get_active();
    theParam.eSearchType    = m_xBtnRegExp->get_active() ? utl::SearchParam::SearchType::Regexp : utl::SearchParam::SearchType::Normal;
    theParam.bDestPers      = m_xBtnDestPers->get_active();

    // only set the three - reset everything else

    pOutItem.reset( new ScQueryItem( nWhichQuery, &theParam ) );

    return pOutItem.get();
}

bool ScFilterDlg::IsRefInputMode() const
{
    return bRefInputMode;
}

// Handler:

IMPL_LINK( ScFilterDlg, BtnClearHdl, weld::Button&, rBtn, void )
{
    if ( &rBtn != m_xBtnClear.get() )
        return;

    // scroll to the top
    m_xScrollBar->vadjustment_set_value(0);
    size_t nOffset = 0;
    RefreshEditRow( nOffset);

    // clear all conditions
    m_xLbConnect1->set_active(-1);
    m_xLbConnect2->set_active(-1);
    m_xLbConnect3->set_active(-1);
    m_xLbConnect4->set_active(-1);
    m_xLbField1->set_active(0);
    m_xLbField2->set_active(0);
    m_xLbField3->set_active(0);
    m_xLbField4->set_active(0);
    m_xLbCond1->set_active(0);
    m_xLbCond2->set_active(0);
    m_xLbCond3->set_active(0);
    m_xLbCond4->set_active(0);
    ClearValueList( 1 );
    ClearValueList( 2 );
    ClearValueList( 3 );
    ClearValueList( 4 );

    // disable fields for second row onward
    m_xLbConnect2->set_sensitive(false);
    m_xLbConnect3->set_sensitive(false);
    m_xLbConnect4->set_sensitive(false);
    m_xLbField2->set_sensitive(false);
    m_xLbField3->set_sensitive(false);
    m_xLbField4->set_sensitive(false);
    m_xLbCond2->set_sensitive(false);
    m_xLbCond3->set_sensitive(false);
    m_xLbCond4->set_sensitive(false);
    m_xEdVal2->set_sensitive(false);
    m_xEdVal3->set_sensitive(false);
    m_xEdVal4->set_sensitive(false);
    m_xLbColor2->set_sensitive(false);
    m_xLbColor3->set_sensitive(false);
    m_xLbColor4->set_sensitive(false);
    m_xBtnRemove2->set_sensitive(false);
    m_xBtnRemove3->set_sensitive(false);
    m_xBtnRemove4->set_sensitive(false);

    // clear query data objects
    SCSIZE nCount = theQueryData.GetEntryCount();
    if (maRefreshExceptQuery.size() < nCount + 1)
        maRefreshExceptQuery.resize(nCount + 1, false);
    for (SCSIZE i = 0; i < nCount; ++i)
    {
        theQueryData.GetEntry(i).bDoQuery = false;
        maRefreshExceptQuery[i] = false;
        theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
    }
    maRefreshExceptQuery[0] = true;
}

IMPL_LINK( ScFilterDlg, EndDlgHdl, weld::Button&, rBtn, void )
{
    if ( &rBtn == m_xBtnOk.get() )
    {
        bool bAreaInputOk = true;

        if ( m_xBtnCopyResult->get_active() )
        {
            if ( !pOptionsMgr->VerifyPosStr( m_xEdCopyArea->GetText() ) )
            {
                if (!m_xExpander->get_expanded())
                  m_xExpander->set_expanded(true);

                std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                          VclMessageType::Warning, VclButtonsType::Ok,
                                                          ScResId(STR_INVALID_TABREF)));
                xBox->run();
                m_xEdCopyArea->GrabFocus();
                bAreaInputOk = false;
            }
        }

        if ( bAreaInputOk )
        {
            SetDispatcherLock( false );
            SwitchToDocument();
            GetBindings().GetDispatcher()->ExecuteList(FID_FILTER_OK,
                                      SfxCallMode::SLOT | SfxCallMode::RECORD,
                                      { GetOutputItem() });
            response(RET_OK);
        }
    }
    else if ( &rBtn == m_xBtnCancel.get() )
    {
        response(RET_CANCEL);
    }
}

IMPL_LINK_NOARG(ScFilterDlg, MoreExpandedHdl, weld::Expander&, void)
{
    if ( m_xExpander->get_expanded() )
        pTimer->Start();
    else
    {
        pTimer->Stop();
        bRefInputMode = false;
        //@BugID 54702 Enable/disable only in Basic class
        //SFX_APPWINDOW->Disable(FALSE);        //! general method in ScAnyRefDlg
    }
}

IMPL_LINK( ScFilterDlg, TimeOutHdl, Timer*, _pTimer, void )
{
    // Check if RefInputMode is still true every 50ms
    if (_pTimer == pTimer.get() && m_xDialog->has_toplevel_focus())
        bRefInputMode = (m_xEdCopyArea->GetWidget()->has_focus() || m_xRbCopyArea->GetWidget()->has_focus());

    if ( m_xExpander->get_expanded() )
        pTimer->Start();
}

IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
{
    /*
     * Handle enable/disable logic depending on which ListBox was selected
     */

    sal_uInt16 nOffset = GetSliderPos();

    if ( &rLb == m_xLbConnect1.get() )
    {
        m_xLbField1->set_sensitive(true);
        m_xLbCond1->set_sensitive(true);
        m_xEdVal1->set_sensitive(true);
        m_xBtnRemove1->set_sensitive(true);

        const sal_Int32 nConnect1 = m_xLbConnect1->get_active();
        size_t nQE = nOffset;
        theQueryData.GetEntry(nQE).eConnect =static_cast<ScQueryConnect>(nConnect1);
        if (maRefreshExceptQuery.size() < nQE + 1)
            maRefreshExceptQuery.resize(nQE + 1, false);
        maRefreshExceptQuery[nQE] = true;
    }
    else if ( &rLb == m_xLbConnect2.get() )
    {
        m_xLbField2->set_sensitive(true);
        m_xLbCond2->set_sensitive(true);
        m_xEdVal2->set_sensitive(true);
        m_xBtnRemove2->set_sensitive(true);

        const sal_Int32 nConnect2 = m_xLbConnect2->get_active();
        size_t nQE = 1+nOffset;
        theQueryData.GetEntry(nQE).eConnect =static_cast<ScQueryConnect>(nConnect2);
        if (maRefreshExceptQuery.size() < nQE + 1)
            maRefreshExceptQuery.resize(nQE + 1, false);
        maRefreshExceptQuery[nQE]=true;
    }
    else if ( &rLb == m_xLbConnect3.get() )
    {
        m_xLbField3->set_sensitive(true);
        m_xLbCond3->set_sensitive(true);
        m_xEdVal3->set_sensitive(true);
        m_xBtnRemove3->set_sensitive(true);

        const sal_Int32 nConnect3 = m_xLbConnect3->get_active();
        size_t nQE = 2 + nOffset;
        theQueryData.GetEntry(nQE).eConnect = static_cast<ScQueryConnect>(nConnect3);
        if (maRefreshExceptQuery.size() < nQE + 1)
            maRefreshExceptQuery.resize(nQE + 1, false);
        maRefreshExceptQuery[nQE] = true;

    }
    else if ( &rLb == m_xLbConnect4.get() )
    {
        m_xLbField4->set_sensitive(true);
        m_xLbCond4->set_sensitive(true);
        m_xEdVal4->set_sensitive(true);
        m_xLbColor4->set_sensitive(true);
        m_xBtnRemove4->set_sensitive(true);

        const sal_Int32 nConnect4 = m_xLbConnect4->get_active();
        size_t nQE = 3 + nOffset;
        theQueryData.GetEntry(nQE).eConnect = static_cast<ScQueryConnect>(nConnect4);
        if (maRefreshExceptQuery.size() < nQE + 1)
            maRefreshExceptQuery.resize(nQE + 1, false);
        maRefreshExceptQuery[nQE] = true;
    }
    else if ( &rLb == m_xLbField1.get() )
    {
        if ( m_xLbField1->get_active() == 0 )
        {
            m_xLbConnect2->set_active(-1);
            m_xLbConnect3->set_active(-1);
            m_xLbConnect4->set_active(-1);
            m_xLbField2->set_active( 0 );
            m_xLbField3->set_active( 0 );
            m_xLbField4->set_active( 0 );
            m_xLbCond2->set_active( 0 );
            m_xLbCond3->set_active( 0 );
            m_xLbCond4->set_active( 0 );
            ClearValueList( 1 );
            ClearValueList( 2 );
            ClearValueList( 3 );
            ClearValueList( 4 );

            m_xLbConnect2->set_sensitive(false);
            m_xLbConnect3->set_sensitive(false);
            m_xLbConnect4->set_sensitive(false);
            m_xLbField2->set_sensitive(false);
            m_xLbField3->set_sensitive(false);
            m_xLbField4->set_sensitive(false);
            m_xLbCond2->set_sensitive(false);
            m_xLbCond3->set_sensitive(false);
            m_xLbCond4->set_sensitive(false);
            m_xEdVal2->set_sensitive(false);
            m_xEdVal3->set_sensitive(false);
            m_xEdVal4->set_sensitive(false);
            m_xLbColor2->set_sensitive(false);
            m_xLbColor3->set_sensitive(false);
            m_xLbColor4->set_sensitive(false);
            m_xBtnRemove2->set_sensitive(false);
            m_xBtnRemove3->set_sensitive(false);
            m_xBtnRemove4->set_sensitive(false);
            SCSIZE nCount = theQueryData.GetEntryCount();
            if (maRefreshExceptQuery.size() < nCount + 1)
                maRefreshExceptQuery.resize(nCount + 1, false);
            for (SCSIZE i = nOffset; i < nCount; ++i)
            {
                theQueryData.GetEntry(i).bDoQuery = false;
                maRefreshExceptQuery[i] = false;
                theQueryData.GetEntry(i).nField =  static_cast<SCCOL>(0);
            }
            maRefreshExceptQuery[nOffset] = true;
        }
        else
        {
            UpdateValueList( 1 );
            UpdateColorList( 1 );
            if ( !m_xLbConnect2->get_sensitive() )
            {
                m_xLbConnect2->set_sensitive(true);
            }
            theQueryData.GetEntry(nOffset).bDoQuery = true;
            const sal_Int32 nField  = rLb.get_active();
            theQueryData.GetEntry(nOffset).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
        }
    }
    else if ( &rLb == m_xLbField2.get() )
    {
        if ( m_xLbField2->get_active() == 0 )
        {
            m_xLbConnect3->set_active(-1);
            m_xLbConnect4->set_active(-1);
            m_xLbField3->set_active( 0 );
            m_xLbField4->set_active( 0 );
            m_xLbCond3->set_active( 0 );
            m_xLbCond4->set_active( 0 );
            ClearValueList( 2 );
            ClearValueList( 3 );
            ClearValueList( 4 );

            m_xLbConnect3->set_sensitive(false);
            m_xLbConnect4->set_sensitive(false);
            m_xLbField3->set_sensitive(false);
            m_xLbField4->set_sensitive(false);
            m_xLbCond3->set_sensitive(false);
            m_xLbCond4->set_sensitive(false);
            m_xEdVal3->set_sensitive(false);
            m_xEdVal4->set_sensitive(false);
            m_xLbColor3->set_sensitive(false);
            m_xLbColor4->set_sensitive(false);
            m_xBtnRemove3->set_sensitive(false);
            m_xBtnRemove4->set_sensitive(false);

            sal_uInt16 nTemp=nOffset+1;
            SCSIZE nCount = theQueryData.GetEntryCount();
            if (maRefreshExceptQuery.size() < nCount)
                maRefreshExceptQuery.resize(nCount, false);
            for (SCSIZE i= nTemp; i< nCount; i++)
            {
                theQueryData.GetEntry(i).bDoQuery = false;
                maRefreshExceptQuery[i] = false;
                theQueryData.GetEntry(i).nField =  static_cast<SCCOL>(0);
            }
            maRefreshExceptQuery[nTemp] = true;
        }
        else
        {
            UpdateValueList( 2 );
            UpdateColorList( 2 );
            if ( !m_xLbConnect3->get_sensitive() )
            {
                m_xLbConnect3->set_sensitive(true);
            }
            const sal_Int32 nField = rLb.get_active();
            sal_uInt16 nQ=1+nOffset;
            theQueryData.GetEntry(nQ).bDoQuery = true;
            theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
        }
    }
    else if ( &rLb == m_xLbField3.get() )
    {
        if ( m_xLbField3->get_active() == 0 )
        {
            m_xLbConnect4->set_active(-1);
            m_xLbField4->set_active( 0 );
            m_xLbCond4->set_active( 0 );
            ClearValueList( 3 );
            ClearValueList( 4 );

            m_xLbConnect4->set_sensitive(false);
            m_xLbField4->set_sensitive(false);
            m_xLbCond4->set_sensitive(false);
            m_xEdVal4->set_sensitive(false);
            m_xLbColor4->set_sensitive(false);
            m_xBtnRemove4->set_sensitive(false);

            sal_uInt16 nTemp=nOffset+2;
            SCSIZE nCount = theQueryData.GetEntryCount();
            if (maRefreshExceptQuery.size() < nCount)
                maRefreshExceptQuery.resize(nCount, false);
            for (SCSIZE i = nTemp; i < nCount; ++i)
            {
                theQueryData.GetEntry(i).bDoQuery = false;
                maRefreshExceptQuery[i] = false;
                theQueryData.GetEntry(i).nField =  static_cast<SCCOL>(0);
            }
            maRefreshExceptQuery[nTemp] = true;
        }
        else
        {
            UpdateValueList( 3 );
            UpdateColorList( 3 );
            if ( !m_xLbConnect4->get_sensitive() )
            {
                m_xLbConnect4->set_sensitive(true);
            }

            const sal_Int32 nField = rLb.get_active();
            sal_uInt16 nQ=2+nOffset;
            theQueryData.GetEntry(nQ).bDoQuery = true;
            theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;

        }
    }
    else if ( &rLb == m_xLbField4.get() )
    {
        if ( m_xLbField4->get_active() == 0 )
        {
            ClearValueList( 4 );
            sal_uInt16 nTemp=nOffset+3;
            SCSIZE nCount = theQueryData.GetEntryCount();
            if (maRefreshExceptQuery.size() < nCount)
                maRefreshExceptQuery.resize(nCount, false);
            for (SCSIZE i = nTemp; i < nCount; ++i)
            {
                theQueryData.GetEntry(i).bDoQuery = false;
                maRefreshExceptQuery[i] = false;
                theQueryData.GetEntry(i).nField =  static_cast<SCCOL>(0);
            }
            maRefreshExceptQuery[nTemp] = true;
        }
        else
        {
            UpdateValueList( 4 );
            UpdateColorList( 4 );
            const sal_Int32 nField = rLb.get_active();
            sal_uInt16 nQ=3+nOffset;
            theQueryData.GetEntry(nQ).bDoQuery = true;
            theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
        }

    }
    else if (&rLb == m_xLbCond1.get() || &rLb == m_xLbCond2.get() || &rLb == m_xLbCond3.get()
             || &rLb == m_xLbCond4.get())
    {
        ScQueryOp op;
        sal_uInt16 nQ = 0;
        bool bEnableColorLb = false;
        if (rLb.get_active_text() == aStrFontColor || rLb.get_active_text() == aStrBackgroundColor)
        {
            bEnableColorLb = true;
            op = SC_EQUAL;
        }
        else
        {
            op = static_cast<ScQueryOp>(rLb.get_active());
        }

        if (&rLb == m_xLbCond1.get())
        {
            nQ = nOffset;
            m_xLbColor1->set_visible(bEnableColorLb);
            m_xLbColor1->set_sensitive(bEnableColorLb);
            m_xEdVal1->set_visible(!bEnableColorLb);
            UpdateColorList(1);
        }
        else if (&rLb == m_xLbCond2.get())
        {
            nQ = 1 + nOffset;
            m_xLbColor2->set_visible(bEnableColorLb);
            m_xLbColor2->set_sensitive(bEnableColorLb);
            m_xEdVal2->set_visible(!bEnableColorLb);
            UpdateColorList(2);
        }
        else if (&rLb == m_xLbCond3.get())
        {
            nQ = 2 + nOffset;
            m_xLbColor3->set_visible(bEnableColorLb);
            m_xLbColor3->set_sensitive(bEnableColorLb);
            m_xEdVal3->set_visible(!bEnableColorLb);
            UpdateColorList(3);
        }
        else if (&rLb == m_xLbCond4.get())
        {
            nQ = 3 + nOffset;
            m_xLbColor4->set_visible(bEnableColorLb);
            m_xLbColor4->set_sensitive(bEnableColorLb);
            m_xEdVal4->set_visible(!bEnableColorLb);
            UpdateColorList(4);
        }

        theQueryData.GetEntry(nQ).eOp = op;
    }
    else if (&rLb == m_xLbColor1.get() || &rLb == m_xLbColor2.get() || &rLb == m_xLbColor3.get()
             || &rLb == m_xLbColor4.get())
    {
        sal_uInt16 nQ = 0;
        if (&rLb == m_xLbColor1.get())
        {
            nQ = nOffset;
        }
        else if (&rLb == m_xLbColor2.get())
        {
            nQ = 1 + nOffset;
        }
        else if (&rLb == m_xLbColor3.get())
        {
            nQ = 2 + nOffset;
        }
        else if (&rLb == m_xLbColor4.get())
        {
            nQ = 3 + nOffset;
        }

        ScQueryEntry& aEntry = theQueryData.GetEntry(nQ);
        Color aColor = Color::STRtoRGB(maColorLbArr[nQ]->get_active_id());
        if (maCondLbArr[nQ]->get_active_text() == aStrFontColor)
        {
            aEntry.SetQueryByTextColor(aColor);
        }
        else if (maCondLbArr[nQ]->get_active_text() == aStrBackgroundColor)
        {
            aEntry.SetQueryByBackgroundColor(aColor);
        }
    }
}

IMPL_LINK( ScFilterDlg, CheckBoxHdl, weld::Toggleable&, rBox, void )
{
    //  Column headers:
    //      Field list: Columnxx <-> column header string
    //      Value list: Column header value not applicable.
    //  Upper/lower case:
    //      Value list: completely new

    if ( &rBox == m_xBtnHeader.get() )              // Field list and value list
    {
        const sal_Int32 nCurSel1 = m_xLbField1->get_active();
        const sal_Int32 nCurSel2 = m_xLbField2->get_active();
        const sal_Int32 nCurSel3 = m_xLbField3->get_active();
        const sal_Int32 nCurSel4 = m_xLbField4->get_active();
        FillFieldLists();
        m_xLbField1->set_active( nCurSel1 );
        m_xLbField2->set_active( nCurSel2 );
        m_xLbField3->set_active( nCurSel3 );
        m_xLbField4->set_active( nCurSel4 );

        UpdateHdrInValueList( 1 );
        UpdateHdrInValueList( 2 );
        UpdateHdrInValueList( 3 );
        UpdateHdrInValueList( 4 );
    }

    if ( &rBox != m_xBtnCase.get() )            // Complete value list
        return;

    m_EntryLists.clear();
    UpdateValueList( 1 );       // current text is recorded
    UpdateValueList( 2 );
    UpdateValueList( 3 );
    UpdateValueList( 4 );

    UpdateColorList( 1 );
    UpdateColorList( 2 );
    UpdateColorList( 3 );
    UpdateColorList( 4 );
}

IMPL_LINK( ScFilterDlg, ValModifyHdl, weld::ComboBox&, rEd, void )
{
    size_t nOffset = GetSliderPos();
    size_t i = 0;
    size_t nQE = i + nOffset;
    OUString aStrVal = rEd.get_active_text();
    weld::ComboBox*  pLbCond   = m_xLbCond1.get();
    weld::ComboBox*  pLbField  = m_xLbField1.get();
    if ( &rEd == m_xEdVal2.get() )
    {
        pLbCond  = m_xLbCond2.get();
        pLbField = m_xLbField2.get();
        i=1;
        nQE=i+nOffset;
    }
    if ( &rEd == m_xEdVal3.get() )
    {
        pLbCond = m_xLbCond3.get();
        pLbField = m_xLbField3.get();
        i=2;
        nQE=i+nOffset;
    }
    if ( &rEd == m_xEdVal4.get() )
    {
        pLbCond = m_xLbCond4.get();
        pLbField = m_xLbField4.get();
        i=3;
        nQE=i+nOffset;
    }

    if ( aStrEmpty == aStrVal || aStrNotEmpty == aStrVal )
    {
        pLbCond->set_active_text(OUString('='));
        pLbCond->set_sensitive(false);
    }
    else
        pLbCond->set_sensitive(true);

    if (maHasDates.size() < nQE + 1)
        maHasDates.resize(nQE + 1, false);
    if (maRefreshExceptQuery.size() < nQE + 1)
        maRefreshExceptQuery.resize(nQE + 1, false);

    ScQueryEntry& rEntry = theQueryData.GetEntry( nQE );
    ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
    bool bDoThis = (pLbField->get_active() != 0);
    rEntry.bDoQuery = bDoThis;

    if ( !(rEntry.bDoQuery || maRefreshExceptQuery[nQE]) )
        return;

    bool bByEmptyOrNotByEmpty = false;
    if ( aStrEmpty == aStrVal )
    {
        bByEmptyOrNotByEmpty = true;
        rEntry.SetQueryByEmpty();
    }
    else if ( aStrNotEmpty == aStrVal )
    {
        bByEmptyOrNotByEmpty = true;
        rEntry.SetQueryByNonEmpty();
    }
    else
    {
        rItem.maString = rDoc.GetSharedStringPool().intern(aStrVal);
        rItem.mfVal = 0.0;

        sal_uInt32 nIndex = 0;
        bool bNumber = rDoc.GetFormatTable()->IsNumberFormat(
            rItem.maString.getString(), nIndex, rItem.mfVal);
        rItem.meType = bNumber ? ScQueryEntry::ByValue : ScQueryEntry::ByString;
    }

    const sal_Int32 nField = pLbField->get_active();
    rEntry.nField = nField ? (theQueryData.nCol1 +
        static_cast<SCCOL>(nField) - 1) : static_cast<SCCOL>(0);

    ScQueryOp eOp  = static_cast<ScQueryOp>(pLbCond->get_active());
    rEntry.eOp     = eOp;
    if (maHasDates[nQE] && !bByEmptyOrNotByEmpty)
        rItem.meType = ScQueryEntry::ByDate;
}

IMPL_LINK( ScFilterDlg, BtnRemoveHdl, weld::Button&, rBtn, void )
{
    // Calculate the row to delete
    sal_uInt16 nOffset = GetSliderPos();
    int nButtonIndex = 0;
    if ( &rBtn == m_xBtnRemove2.get() )
        nButtonIndex = 1;
    if ( &rBtn == m_xBtnRemove3.get() )
        nButtonIndex = 2;
    if ( &rBtn == m_xBtnRemove4.get() )
        nButtonIndex = 3;
    SCSIZE nRowToDelete = nOffset + nButtonIndex;

    // Check that the index is sensible
    SCSIZE nCount = theQueryData.GetEntryCount();
    if (nRowToDelete >= nCount)
    {
        SAL_WARN( "sc""ScFilterDlg::BtnRemoveHdl: could not delete row - invalid index.");
        return;
    }

    // Resize maRefreshExceptQuery
    if (maRefreshExceptQuery.size() < nCount + 1)
        maRefreshExceptQuery.resize(nCount + 1, false);

    // Move all the subsequent rows back one position;
    // also find the last row, which we will delete
    SCSIZE nRowToClear = nCount-1;
    for (SCSIZE i = nRowToDelete; i < nCount-1; ++i)
    {
        if (theQueryData.GetEntry(i+1).bDoQuery)
        {
            theQueryData.GetEntry(i) = theQueryData.GetEntry(i+1);
        }
        else
        {
            nRowToClear = i;
            break;
        }
    }

    // If the next row is being edited, but not confirmed, move it back
    // one position
    if (nRowToClear < nCount-1  &&  maRefreshExceptQuery[nRowToClear+1])
    {
        theQueryData.GetEntry(nRowToClear) = theQueryData.GetEntry(nRowToClear+1);
        maRefreshExceptQuery[nRowToClear] = true;
        maRefreshExceptQuery[nRowToClear+1] = false;
    }
    else
    {
        // Remove the very last one, since everything has moved back
        theQueryData.GetEntry(nRowToClear).bDoQuery = false;
        theQueryData.GetEntry(nRowToClear).nField =  static_cast<SCCOL>(0);
        maRefreshExceptQuery[nRowToClear] = false;
    }

    // Always enable the very first row
    if (!theQueryData.GetEntry(0).bDoQuery)
    {
        maRefreshExceptQuery[0] = true;
    }

    // Refresh the UI
    RefreshEditRow( nOffset );

    // Special handling if the very first row was cleared
    if (!theQueryData.GetEntry(0).bDoQuery)
    {
        m_xLbConnect1->set_active(-1);
        m_xLbField1->set_active(0);
        m_xLbField1->set_sensitive(true);
        m_xLbCond1->set_active(0);
        m_xLbCond1->set_sensitive(true);
        ClearValueList(1);
    }
}

IMPL_LINK_NOARG(ScFilterDlg, ScrollHdl, weld::ScrolledWindow&, void)
{
    SliderMoved();
}

void ScFilterDlg::SliderMoved()
{
    size_t nOffset = GetSliderPos();
    RefreshEditRow( nOffset);
}

size_t ScFilterDlg::GetSliderPos() const
{
    return static_cast<size_t>(m_xScrollBar->vadjustment_get_value());
}

void ScFilterDlg::RefreshEditRow( size_t nOffset )
{
    if (nOffset==0)
        maConnLbArr[0]->hide();
    else
        maConnLbArr[0]->show();

    for (size_t i = 0; i < QUERY_ENTRY_COUNT; ++i)
    {
        OUString aValStr;
        size_t nCondPos = 0;
        size_t nFieldSelPos = 0;
        size_t nQE = i + nOffset;

        maColorLbArr[i]->set_visible(false);

        if (maRefreshExceptQuery.size() < nQE + 1)
            maRefreshExceptQuery.resize(nQE + 1, false);

        ScQueryEntry& rEntry = theQueryData.GetEntry( nQE);
        if ( rEntry.bDoQuery || maRefreshExceptQuery[nQE] )
        {
            nCondPos = static_cast<size_t>(rEntry.eOp);
            if(rEntry.bDoQuery)
               nFieldSelPos = GetFieldSelPos( static_cast<SCCOL>(rEntry.nField) );

            const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
            OUString aQueryStr = rItem.maString.getString();
            if (rEntry.IsQueryByEmpty())
            {
                aValStr = aStrEmpty;
                maCondLbArr[i]->set_sensitive(false);
            }
            else if (rEntry.IsQueryByNonEmpty())
            {
                aValStr = aStrNotEmpty;
                maCondLbArr[i]->set_sensitive(false);
            }
            else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor())
            {
                nCondPos = maCondLbArr[i]->find_text(
                    rEntry.IsQueryByTextColor() ? aStrFontColor : aStrBackgroundColor);

                maValueEdArr[i]->set_visible(false);
                maColorLbArr[i]->set_visible(true);
                maColorLbArr[i]->set_sensitive(true);
            }
            else
            {
                SetValString(aQueryStr, rItem, aValStr);
                maCondLbArr[i]->set_sensitive(true);
            }
            maFieldLbArr[i]->set_sensitive(true);
            maValueEdArr[i]->set_sensitive(true);
            maRemoveBtnArr[i]->set_sensitive(true);

            if (nOffset==0)
            {
                if (i<3)
                {
                    if(rEntry.bDoQuery)
                        maConnLbArr[i+1]->set_sensitive(true);
                    else
                        maConnLbArr[i+1]->set_sensitive(false);
                    size_t nQENext = nQE + 1;
                    if (maRefreshExceptQuery.size() < nQENext + 1)
                        maRefreshExceptQuery.resize(nQENext + 1, false);
                    if (theQueryData.GetEntry(nQENext).bDoQuery || maRefreshExceptQuery[nQENext])
                        maConnLbArr[i+1]->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(nQENext).eConnect) );
                    else
                        maConnLbArr[i+1]->set_active(-1);
                }
            }
            else
            {
                if(theQueryData.GetEntry( nQE-1).bDoQuery)
                    maConnLbArr[i]->set_sensitive(true);
                else
                    maConnLbArr[i]->set_sensitive(false);

                if (maRefreshExceptQuery.size() < nQE + 1)
                    maRefreshExceptQuery.resize(nQE + 1, false);
                if(rEntry.bDoQuery || maRefreshExceptQuery[nQE])
                    maConnLbArr[i]->set_active( static_cast<sal_uInt16>(rEntry.eConnect) );
                else
                    maConnLbArr[i]->set_active(-1);
            }

        }
        else
        {
            if (nOffset==0)
            {
                if(i<3)
                {
                    maConnLbArr[i+1]->set_active(-1);
                    maConnLbArr[i+1]->set_sensitive(false);
                }
            }
            else
            {
                if(theQueryData.GetEntry( nQE-1).bDoQuery)
                    maConnLbArr[i]->set_sensitive(true);
                else
                    maConnLbArr[i]->set_sensitive(false);
                maConnLbArr[i]->set_active(-1);
            }
            maFieldLbArr[i]->set_sensitive(false);
            maCondLbArr[i]->set_sensitive(false);
            maValueEdArr[i]->set_sensitive(false);
            maRemoveBtnArr[i]->set_sensitive(false);
        }
        maFieldLbArr[i]->set_active( nFieldSelPos );
        maCondLbArr [i]->set_active( nCondPos );
        maValueEdArr[i]->set_entry_text( aValStr );
        UpdateValueList(i+1);
        UpdateColorList(i+1);
    }
}

void ScFilterDlg::SetValString( const OUString& rQueryStr, const ScQueryEntry::Item& rItem,
    OUString& rValStr )
{
    if (rQueryStr.isEmpty())
    {
        if (rItem.meType == ScQueryEntry::ByValue)
        {
            rValStr = rDoc.GetFormatTable()->GetInputLineString(rItem.mfVal, 0);
        }
        else if (rItem.meType == ScQueryEntry::ByDate)
        {
            SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
            rValStr = pFormatter->GetInputLineString(rItem.mfVal,
                                           pFormatter->GetStandardFormat( SvNumFormatType::DATE));
        }
        else
        {
            SAL_WARN( "sc""ScFilterDlg::SetValString: empty query string, really?");
            rValStr = rQueryStr;
        }
    }
    else
    {
        // XXX NOTE: if not ByString we just assume this has been
        // set to a proper string corresponding to the numeric
        // value earlier!
        rValStr = rQueryStr;
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=91 H=99 G=94

¤ Dauer der Verarbeitung: 0.16 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.