diff options
Diffstat (limited to 'sc/source/ui/dbgui/filtdlg.cxx')
-rw-r--r-- | sc/source/ui/dbgui/filtdlg.cxx | 1571 |
1 files changed, 1571 insertions, 0 deletions
diff --git a/sc/source/ui/dbgui/filtdlg.cxx b/sc/source/ui/dbgui/filtdlg.cxx new file mode 100644 index 000000000..2af415670 --- /dev/null +++ b/sc/source/ui/dbgui/filtdlg.cxx @@ -0,0 +1,1571 @@ +/* -*- 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, + const SfxItemSet& rArgSet) + : ScAnyRefDlgController(pB, pCW, pParent, + "modules/scalc/ui/standardfilterdialog.ui", "StandardFilterDialog") + , aStrUndefined(ScResId(SCSTR_UNDEFINED)) + , aStrNone(ScResId(SCSTR_NONE)) + , aStrEmpty(ScResId(SCSTR_FILTER_EMPTY)) + , aStrNotEmpty(ScResId(SCSTR_FILTER_NOTEMPTY)) + , aStrColumn(ScResId(SCSTR_COLUMN_LETTER)) + , aStrTextColor(ScResId(SCSTR_FILTER_TEXT_COLOR_COND)) + , aStrBackgroundColor(ScResId(SCSTR_FILTER_BACKGROUND_COLOR_COND)) + , nWhichQuery(rArgSet.GetPool()->GetWhich(SID_QUERY)) + , theQueryData(static_cast<const ScQueryItem&>(rArgSet.Get(nWhichQuery)).GetQueryData()) + , pViewData(nullptr) + , pDoc(nullptr) + , nSrcTab(0) + , bRefInputMode(false) + , m_xLbConnect1(m_xBuilder->weld_combo_box("connect1")) + , m_xLbField1(m_xBuilder->weld_combo_box("field1")) + , m_xLbCond1(m_xBuilder->weld_combo_box("cond1")) + , m_xEdVal1(m_xBuilder->weld_combo_box("val1")) + , m_xLbColor1(m_xBuilder->weld_combo_box("color1")) + , m_xBtnRemove1(m_xBuilder->weld_button("remove1")) + , m_xLbConnect2(m_xBuilder->weld_combo_box("connect2")) + , m_xLbField2(m_xBuilder->weld_combo_box("field2")) + , m_xLbCond2(m_xBuilder->weld_combo_box("cond2")) + , m_xEdVal2(m_xBuilder->weld_combo_box("val2")) + , m_xLbColor2(m_xBuilder->weld_combo_box("color2")) + , m_xBtnRemove2(m_xBuilder->weld_button("remove2")) + , m_xLbConnect3(m_xBuilder->weld_combo_box("connect3")) + , m_xLbField3(m_xBuilder->weld_combo_box("field3")) + , m_xLbCond3(m_xBuilder->weld_combo_box("cond3")) + , m_xEdVal3(m_xBuilder->weld_combo_box("val3")) + , m_xLbColor3(m_xBuilder->weld_combo_box("color3")) + , m_xBtnRemove3(m_xBuilder->weld_button("remove3")) + , m_xLbConnect4(m_xBuilder->weld_combo_box("connect4")) + , m_xLbField4(m_xBuilder->weld_combo_box("field4")) + , m_xLbCond4(m_xBuilder->weld_combo_box("cond4")) + , m_xEdVal4(m_xBuilder->weld_combo_box("val4")) + , m_xLbColor4(m_xBuilder->weld_combo_box("color4")) + , m_xBtnRemove4(m_xBuilder->weld_button("remove4")) + , m_xContents(m_xBuilder->weld_widget("grid")) + , m_xScrollBar(m_xBuilder->weld_scrolled_window("scrollbar", true)) + , m_xExpander(m_xBuilder->weld_expander("more")) + , m_xBtnClear(m_xBuilder->weld_button("clear")) + , m_xBtnOk(m_xBuilder->weld_button("ok")) + , m_xBtnCancel(m_xBuilder->weld_button("cancel")) + , m_xBtnCase(m_xBuilder->weld_check_button("case")) + , m_xBtnRegExp(m_xBuilder->weld_check_button("regexp")) + , m_xBtnHeader(m_xBuilder->weld_check_button("header")) + , m_xBtnUnique(m_xBuilder->weld_check_button("unique")) + , m_xBtnCopyResult(m_xBuilder->weld_check_button("copyresult")) + , m_xLbCopyArea(m_xBuilder->weld_combo_box("lbcopyarea")) + , m_xEdCopyArea(new formula::RefEdit(m_xBuilder->weld_entry("edcopyarea"))) + , m_xRbCopyArea(new formula::RefButton(m_xBuilder->weld_button("rbcopyarea"))) + , m_xBtnDestPers(m_xBuilder->weld_check_button("destpers")) + , m_xFtDbAreaLabel(m_xBuilder->weld_label("dbarealabel")) + , m_xFtDbArea(m_xBuilder->weld_label("dbarea")) +{ + 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(aStrTextColor) != -1); + assert(m_xLbCond1->find_text(aStrBackgroundColor) != -1); + + Init( rArgSet ); + + // 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( const SfxItemSet& rArgSet ) +{ + const ScQueryItem& rQueryItem = static_cast<const ScQueryItem&>( + rArgSet.Get( nWhichQuery )); + + 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("0000000000"); + 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 ) ); + + pViewData = rQueryItem.GetViewData(); + pDoc = pViewData ? &pViewData->GetDocument() : nullptr; + nSrcTab = pViewData ? pViewData->GetTabNo() : static_cast<SCTAB>(0); + + // 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( + pViewData, + 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() ? aStrTextColor : 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 = pViewData ? GetFieldSelPos(pViewData->GetCurX()) : 0; + 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 (pDoc != nullptr && pDoc->GetChangeTrack() != nullptr) + m_xBtnCopyResult->set_sensitive(false); +} + +void ScFilterDlg::Close() +{ + if (pViewData) + pViewData->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 ); + + if ( pDoc ) + { + 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 = pDoc->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 (pDoc && 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(); + pDoc->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; + pDoc->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 (!pDoc) + return; + + 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 (!pDoc || 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 == aStrTextColor) + 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 == aStrTextColor + ? 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); + } + + auto aItem = rEntry.GetQueryItem(); + if (aItem.maColor == rColor + && ((sSelectedCondition == aStrTextColor && aItem.meType == ScQueryEntry::ByTextColor) + || (sSelectedCondition == aStrBackgroundColor + && aItem.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(), *pDoc, pDoc->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() == aStrTextColor || 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); + } + + auto aEntry = theQueryData.GetEntry(nQ); + aEntry.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() == aStrTextColor) + { + 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 = pDoc->GetSharedStringPool().intern(aStrVal); + rItem.mfVal = 0.0; + rItem.meType = 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() ? aStrTextColor : 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()) + { + pDoc = pViewData ? &pViewData->GetDocument() : nullptr; + if (rItem.meType == ScQueryEntry::ByValue) + { + if (pDoc) + { + pDoc->GetFormatTable()->GetInputLineString(rItem.mfVal, 0, rValStr); + } + } + else if (rItem.meType == ScQueryEntry::ByDate) + { + if (pDoc) + { + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + pFormatter->GetInputLineString(rItem.mfVal, + pFormatter->GetStandardFormat( SvNumFormatType::DATE), rValStr); + } + } + 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: */ |