tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / dbgui / filtdlg.cxx
blob9735b15c711e5d1d1f8092f8af36c5c8f3f4dc7d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/dispatch.hxx>
21 #include <sal/log.hxx>
23 #include <uiitems.hxx>
24 #include <reffact.hxx>
25 #include <viewdata.hxx>
26 #include <document.hxx>
27 #include <docsh.hxx>
28 #include <scresid.hxx>
29 #include <queryentry.hxx>
31 #include <foptmgr.hxx>
33 #include <globstr.hrc>
34 #include <strings.hrc>
36 #include <filtdlg.hxx>
37 #include <svx/colorwindow.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/settings.hxx>
40 #include <vcl/virdev.hxx>
41 #include <vcl/weld.hxx>
42 #include <svl/numformat.hxx>
43 #include <svl/sharedstringpool.hxx>
45 #include <limits>
47 #define QUERY_ENTRY_COUNT 4
48 #define INVALID_HEADER_POS std::numeric_limits<size_t>::max()
50 ScFilterDlg::EntryList::EntryList() :
51 mnHeaderPos(INVALID_HEADER_POS) {}
53 ScFilterDlg::ScFilterDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
54 const SfxItemSet& rArgSet)
55 : ScAnyRefDlgController(pB, pCW, pParent,
56 u"modules/scalc/ui/standardfilterdialog.ui"_ustr, u"StandardFilterDialog"_ustr)
57 , aStrUndefined(ScResId(SCSTR_UNDEFINED))
58 , aStrNone(ScResId(SCSTR_NONE))
59 , aStrEmpty(ScResId(SCSTR_FILTER_EMPTY))
60 , aStrNotEmpty(ScResId(SCSTR_FILTER_NOTEMPTY))
61 , aStrColumn(ScResId(SCSTR_COLUMN_LETTER))
62 , aStrFontColor(ScResId(SCSTR_FILTER_FONT_COLOR_COND))
63 , aStrBackgroundColor(ScResId(SCSTR_FILTER_BACKGROUND_COLOR_COND))
64 , nWhichQuery(rArgSet.GetPool()->GetWhichIDFromSlotID(SID_QUERY))
65 , theQueryData(static_cast<const ScQueryItem&>(rArgSet.Get(nWhichQuery)).GetQueryData())
66 , pViewData(nullptr)
67 , pDoc(nullptr)
68 , nSrcTab(0)
69 , bRefInputMode(false)
70 , m_xLbConnect1(m_xBuilder->weld_combo_box(u"connect1"_ustr))
71 , m_xLbField1(m_xBuilder->weld_combo_box(u"field1"_ustr))
72 , m_xLbCond1(m_xBuilder->weld_combo_box(u"cond1"_ustr))
73 , m_xEdVal1(m_xBuilder->weld_combo_box(u"val1"_ustr))
74 , m_xLbColor1(m_xBuilder->weld_combo_box(u"color1"_ustr))
75 , m_xBtnRemove1(m_xBuilder->weld_button(u"remove1"_ustr))
76 , m_xLbConnect2(m_xBuilder->weld_combo_box(u"connect2"_ustr))
77 , m_xLbField2(m_xBuilder->weld_combo_box(u"field2"_ustr))
78 , m_xLbCond2(m_xBuilder->weld_combo_box(u"cond2"_ustr))
79 , m_xEdVal2(m_xBuilder->weld_combo_box(u"val2"_ustr))
80 , m_xLbColor2(m_xBuilder->weld_combo_box(u"color2"_ustr))
81 , m_xBtnRemove2(m_xBuilder->weld_button(u"remove2"_ustr))
82 , m_xLbConnect3(m_xBuilder->weld_combo_box(u"connect3"_ustr))
83 , m_xLbField3(m_xBuilder->weld_combo_box(u"field3"_ustr))
84 , m_xLbCond3(m_xBuilder->weld_combo_box(u"cond3"_ustr))
85 , m_xEdVal3(m_xBuilder->weld_combo_box(u"val3"_ustr))
86 , m_xLbColor3(m_xBuilder->weld_combo_box(u"color3"_ustr))
87 , m_xBtnRemove3(m_xBuilder->weld_button(u"remove3"_ustr))
88 , m_xLbConnect4(m_xBuilder->weld_combo_box(u"connect4"_ustr))
89 , m_xLbField4(m_xBuilder->weld_combo_box(u"field4"_ustr))
90 , m_xLbCond4(m_xBuilder->weld_combo_box(u"cond4"_ustr))
91 , m_xEdVal4(m_xBuilder->weld_combo_box(u"val4"_ustr))
92 , m_xLbColor4(m_xBuilder->weld_combo_box(u"color4"_ustr))
93 , m_xBtnRemove4(m_xBuilder->weld_button(u"remove4"_ustr))
94 , m_xContents(m_xBuilder->weld_widget(u"grid"_ustr))
95 , m_xScrollBar(m_xBuilder->weld_scrolled_window(u"scrollbar"_ustr, true))
96 , m_xExpander(m_xBuilder->weld_expander(u"more"_ustr))
97 , m_xBtnClear(m_xBuilder->weld_button(u"clear"_ustr))
98 , m_xBtnOk(m_xBuilder->weld_button(u"ok"_ustr))
99 , m_xBtnCancel(m_xBuilder->weld_button(u"cancel"_ustr))
100 , m_xBtnCase(m_xBuilder->weld_check_button(u"case"_ustr))
101 , m_xBtnRegExp(m_xBuilder->weld_check_button(u"regexp"_ustr))
102 , m_xBtnHeader(m_xBuilder->weld_check_button(u"header"_ustr))
103 , m_xBtnUnique(m_xBuilder->weld_check_button(u"unique"_ustr))
104 , m_xBtnCopyResult(m_xBuilder->weld_check_button(u"copyresult"_ustr))
105 , m_xLbCopyArea(m_xBuilder->weld_combo_box(u"lbcopyarea"_ustr))
106 , m_xEdCopyArea(new formula::RefEdit(m_xBuilder->weld_entry(u"edcopyarea"_ustr)))
107 , m_xRbCopyArea(new formula::RefButton(m_xBuilder->weld_button(u"rbcopyarea"_ustr)))
108 , m_xBtnDestPers(m_xBuilder->weld_check_button(u"destpers"_ustr))
109 , m_xFtDbAreaLabel(m_xBuilder->weld_label(u"dbarealabel"_ustr))
110 , m_xFtDbArea(m_xBuilder->weld_label(u"dbarea"_ustr))
112 m_xExpander->connect_expanded(LINK(this, ScFilterDlg, MoreExpandedHdl));
113 m_xEdCopyArea->SetReferences(this, m_xFtDbAreaLabel.get());
114 m_xRbCopyArea->SetReferences(this, m_xEdCopyArea.get());
116 assert(m_xLbCond1->find_text(aStrFontColor) != -1);
117 assert(m_xLbCond1->find_text(aStrBackgroundColor) != -1);
119 Init( rArgSet );
121 // Hack: RefInput control
122 pTimer.reset( new Timer("ScFilterTimer") );
123 pTimer->SetTimeout( 50 ); // Wait 50ms
124 pTimer->SetInvokeHandler( LINK( this, ScFilterDlg, TimeOutHdl ) );
127 ScFilterDlg::~ScFilterDlg()
129 pOptionsMgr.reset();
130 pOutItem.reset();
132 // Hack: RefInput control
133 pTimer->Stop();
134 pTimer.reset();
137 namespace {
138 VirtualDevice* lcl_getColorImage(const Color &rColor)
140 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
141 Size aImageSize(rStyleSettings.GetListBoxPreviewDefaultPixelSize());
143 VclPtrInstance<VirtualDevice> xDevice;
144 xDevice->SetOutputSize(aImageSize);
145 const tools::Rectangle aRect(Point(0, 0), aImageSize);
146 if (rColor == COL_NONE_COLOR)
148 const Color aW(COL_WHITE);
149 const Color aG(0xef, 0xef, 0xef);
150 xDevice->DrawCheckered(aRect.TopLeft(), aRect.GetSize(), 8, aW, aG);
151 xDevice->SetFillColor();
153 else
155 xDevice->SetFillColor(rColor);
158 xDevice->DrawRect(aRect);
160 return xDevice.get();
164 void ScFilterDlg::Init( const SfxItemSet& rArgSet )
166 const ScQueryItem& rQueryItem = static_cast<const ScQueryItem&>(
167 rArgSet.Get( nWhichQuery ));
169 m_xBtnClear->connect_clicked ( LINK( this, ScFilterDlg, BtnClearHdl ) );
170 m_xBtnOk->connect_clicked ( LINK( this, ScFilterDlg, EndDlgHdl ) );
171 m_xBtnCancel->connect_clicked ( LINK( this, ScFilterDlg, EndDlgHdl ) );
172 m_xBtnHeader->connect_toggled ( LINK( this, ScFilterDlg, CheckBoxHdl ) );
173 m_xBtnCase->connect_toggled ( LINK( this, ScFilterDlg, CheckBoxHdl ) );
175 m_xLbField1->connect_changed ( LINK( this, ScFilterDlg, LbSelectHdl ) );
176 m_xLbField2->connect_changed ( LINK( this, ScFilterDlg, LbSelectHdl ) );
177 m_xLbField3->connect_changed ( LINK( this, ScFilterDlg, LbSelectHdl ) );
178 m_xLbField4->connect_changed ( LINK( this, ScFilterDlg, LbSelectHdl ) );
179 m_xLbConnect1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
180 m_xLbConnect2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
181 m_xLbConnect3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
182 m_xLbConnect4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
184 m_xLbField1->append_text(u"0000000000"_ustr);
185 m_xLbField1->set_active(0);
186 auto nPrefWidth = m_xLbField1->get_preferred_size().Width();
187 m_xLbField1->clear();
189 m_xLbField1->set_size_request(nPrefWidth, -1);
190 m_xLbField2->set_size_request(nPrefWidth, -1);
191 m_xLbField3->set_size_request(nPrefWidth, -1);
192 m_xLbField4->set_size_request(nPrefWidth, -1);
194 m_xLbCond1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
195 m_xLbCond2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
196 m_xLbCond3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
197 m_xLbCond4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
199 m_xLbColor1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
200 m_xLbColor2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
201 m_xLbColor3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
202 m_xLbColor4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
204 m_xBtnRemove1->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
205 m_xBtnRemove2->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
206 m_xBtnRemove3->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
207 m_xBtnRemove4->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
209 pViewData = rQueryItem.GetViewData();
210 pDoc = pViewData ? &pViewData->GetDocument() : nullptr;
211 nSrcTab = pViewData ? pViewData->GetTabNo() : static_cast<SCTAB>(0);
213 // for easier access:
214 maFieldLbArr.reserve(QUERY_ENTRY_COUNT);
215 maFieldLbArr.push_back(m_xLbField1.get());
216 maFieldLbArr.push_back(m_xLbField2.get());
217 maFieldLbArr.push_back(m_xLbField3.get());
218 maFieldLbArr.push_back(m_xLbField4.get());
219 maValueEdArr.reserve(QUERY_ENTRY_COUNT);
220 maValueEdArr.push_back(m_xEdVal1.get());
221 maValueEdArr.push_back(m_xEdVal2.get());
222 maValueEdArr.push_back(m_xEdVal3.get());
223 maValueEdArr.push_back(m_xEdVal4.get());
224 maCondLbArr.reserve(QUERY_ENTRY_COUNT);
225 maCondLbArr.push_back(m_xLbCond1.get());
226 maCondLbArr.push_back(m_xLbCond2.get());
227 maCondLbArr.push_back(m_xLbCond3.get());
228 maCondLbArr.push_back(m_xLbCond4.get());
229 maConnLbArr.reserve(QUERY_ENTRY_COUNT);
230 maConnLbArr.push_back(m_xLbConnect1.get());
231 maConnLbArr.push_back(m_xLbConnect2.get());
232 maConnLbArr.push_back(m_xLbConnect3.get());
233 maConnLbArr.push_back(m_xLbConnect4.get());
234 maColorLbArr.reserve(QUERY_ENTRY_COUNT);
235 maColorLbArr.push_back(m_xLbColor1.get());
236 maColorLbArr.push_back(m_xLbColor2.get());
237 maColorLbArr.push_back(m_xLbColor3.get());
238 maColorLbArr.push_back(m_xLbColor4.get());
239 maRemoveBtnArr.reserve(QUERY_ENTRY_COUNT);
240 maRemoveBtnArr.push_back(m_xBtnRemove1.get());
241 maRemoveBtnArr.push_back(m_xBtnRemove2.get());
242 maRemoveBtnArr.push_back(m_xBtnRemove3.get());
243 maRemoveBtnArr.push_back(m_xBtnRemove4.get());
245 // Option initialization:
246 pOptionsMgr.reset( new ScFilterOptionsMgr(
247 pViewData,
248 theQueryData,
249 m_xBtnCase.get(),
250 m_xBtnRegExp.get(),
251 m_xBtnHeader.get(),
252 m_xBtnUnique.get(),
253 m_xBtnCopyResult.get(),
254 m_xBtnDestPers.get(),
255 m_xLbCopyArea.get(),
256 m_xEdCopyArea.get(),
257 m_xRbCopyArea.get(),
258 m_xFtDbAreaLabel.get(),
259 m_xFtDbArea.get(),
260 aStrUndefined ) );
261 // Read in field lists and select entries
263 FillFieldLists();
265 for (size_t i = 0; i < QUERY_ENTRY_COUNT; ++i)
267 OUString aValStr;
268 size_t nCondPos = 0;
269 size_t nFieldSelPos = 0;
271 maColorLbArr[i]->set_visible(false);
273 ScQueryEntry& rEntry = theQueryData.GetEntry(i);
274 if ( rEntry.bDoQuery )
276 nCondPos = static_cast<size_t>(rEntry.eOp);
277 nFieldSelPos = GetFieldSelPos( static_cast<SCCOL>(rEntry.nField) );
278 if (rEntry.IsQueryByEmpty())
280 aValStr = aStrEmpty;
281 maCondLbArr[i]->set_sensitive(false);
283 else if (rEntry.IsQueryByNonEmpty())
285 aValStr = aStrNotEmpty;
286 maCondLbArr[i]->set_sensitive(false);
288 else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor())
290 nCondPos = maCondLbArr[i]->find_text(
291 rEntry.IsQueryByTextColor() ? aStrFontColor : aStrBackgroundColor);
292 maValueEdArr[i]->set_visible(false);
293 maColorLbArr[i]->set_visible(true);
294 maColorLbArr[i]->set_sensitive(true);
296 else
298 const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
299 OUString aQueryStr = rItem.maString.getString();
300 SetValString(aQueryStr, rItem, aValStr);
303 else if ( i == 0 )
305 nFieldSelPos = pViewData ? GetFieldSelPos(pViewData->GetCurX()) : 0;
306 rEntry.nField = nFieldSelPos ? (theQueryData.nCol1 +
307 static_cast<SCCOL>(nFieldSelPos) - 1) : static_cast<SCCOL>(0);
308 rEntry.bDoQuery=true;
309 if (maRefreshExceptQuery.size() < i + 1)
310 maRefreshExceptQuery.resize(i + 1, false);
311 maRefreshExceptQuery[i] = true;
314 maFieldLbArr[i]->set_active( nFieldSelPos );
315 maCondLbArr [i]->set_active( nCondPos );
316 maValueEdArr[i]->set_entry_text( aValStr );
317 maValueEdArr[i]->set_entry_completion(false);
318 maValueEdArr[i]->connect_changed( LINK( this, ScFilterDlg, ValModifyHdl ) );
319 UpdateValueList(i+1);
320 UpdateColorList(i+1);
323 m_xScrollBar->connect_vadjustment_changed( LINK( this, ScFilterDlg, ScrollHdl ) );
324 m_xScrollBar->vadjustment_configure(0, 0, 8, 1, 3, 4);
325 Size aSize(m_xContents->get_preferred_size());
326 m_xContents->set_size_request(aSize.Width(), aSize.Height());
328 m_xLbConnect1->hide();
329 // Disable/Enable Logic:
331 (m_xLbField1->get_active() != 0)
332 && (m_xLbField2->get_active() != 0)
333 ? m_xLbConnect2->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(1).eConnect) )
334 : m_xLbConnect2->set_active(-1);
336 (m_xLbField2->get_active() != 0)
337 && (m_xLbField3->get_active() != 0)
338 ? m_xLbConnect3->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(2).eConnect) )
339 : m_xLbConnect3->set_active(-1);
341 (m_xLbField3->get_active() != 0)
342 && (m_xLbField4->get_active() != 0)
343 ? m_xLbConnect4->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(3).eConnect) )
344 : m_xLbConnect4->set_active(-1);
345 if ( m_xLbField1->get_active() == 0 )
347 m_xLbConnect2->set_sensitive(false);
348 m_xLbField2->set_sensitive(false);
349 m_xLbCond2->set_sensitive(false);
350 m_xEdVal2->set_sensitive(false);
351 m_xLbColor2->set_sensitive(false);
352 m_xBtnRemove2->set_sensitive(false);
354 else if ( m_xLbConnect2->get_active() == -1 )
356 m_xLbField2->set_sensitive(false);
357 m_xLbCond2->set_sensitive(false);
358 m_xEdVal2->set_sensitive(false);
359 m_xLbColor2->set_sensitive(false);
360 m_xBtnRemove2->set_sensitive(false);
363 if ( m_xLbField2->get_active() == 0 )
365 m_xLbConnect3->set_sensitive(false);
366 m_xLbField3->set_sensitive(false);
367 m_xLbCond3->set_sensitive(false);
368 m_xEdVal3->set_sensitive(false);
369 m_xLbColor3->set_sensitive(false);
370 m_xBtnRemove3->set_sensitive(false);
372 else if ( m_xLbConnect3->get_active() == -1 )
374 m_xLbField3->set_sensitive(false);
375 m_xLbCond3->set_sensitive(false);
376 m_xEdVal3->set_sensitive(false);
377 m_xLbColor3->set_sensitive(false);
378 m_xBtnRemove3->set_sensitive(false);
380 if ( m_xLbField3->get_active() == 0 )
382 m_xLbConnect4->set_sensitive(false);
383 m_xLbField4->set_sensitive(false);
384 m_xLbCond4->set_sensitive(false);
385 m_xEdVal4->set_sensitive(false);
386 m_xLbColor4->set_sensitive(false);
387 m_xBtnRemove4->set_sensitive(false);
389 else if ( m_xLbConnect4->get_active() == -1 )
391 m_xLbField4->set_sensitive(false);
392 m_xLbCond4->set_sensitive(false);
393 m_xEdVal4->set_sensitive(false);
394 m_xLbColor4->set_sensitive(false);
395 m_xBtnRemove4->set_sensitive(false);
398 m_xEdVal1->set_entry_width_chars(10);
399 m_xEdVal2->set_entry_width_chars(10);
400 m_xEdVal3->set_entry_width_chars(10);
401 m_xEdVal4->set_entry_width_chars(10);
403 if (pDoc != nullptr && pDoc->GetChangeTrack() != nullptr)
404 m_xBtnCopyResult->set_sensitive(false);
407 void ScFilterDlg::Close()
409 if (pViewData)
410 pViewData->GetDocShell()->CancelAutoDBRange();
412 DoClose( ScFilterDlgWrapper::GetChildWindowId() );
415 // Mouse-selected cell area becomes the new selection and is shown in the
416 // reference text box
418 void ScFilterDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
420 if ( bRefInputMode ) // Only possible if in reference edit mode
422 if ( rRef.aStart != rRef.aEnd )
423 RefInputStart( m_xEdCopyArea.get() );
424 OUString aRefStr(rRef.aStart.Format(ScRefFlags::ADDR_ABS_3D, &rDocP, rDocP.GetAddressConvention()));
425 m_xEdCopyArea->SetRefString( aRefStr );
429 void ScFilterDlg::SetActive()
431 if ( bRefInputMode )
433 m_xEdCopyArea->GrabFocus();
434 m_xEdCopyArea->GetModifyHdl().Call( *m_xEdCopyArea );
436 else
437 m_xDialog->grab_focus();
439 RefInputDone();
442 void ScFilterDlg::FillFieldLists()
444 m_xLbField1->freeze();
445 m_xLbField2->freeze();
446 m_xLbField3->freeze();
447 m_xLbField4->freeze();
449 m_xLbField1->clear();
450 m_xLbField2->clear();
451 m_xLbField3->clear();
452 m_xLbField4->clear();
453 m_xLbField1->append_text( aStrNone );
454 m_xLbField2->append_text( aStrNone );
455 m_xLbField3->append_text( aStrNone );
456 m_xLbField4->append_text( aStrNone );
458 if ( pDoc )
460 OUString aFieldName;
461 SCTAB nTab = nSrcTab;
462 SCCOL nFirstCol = theQueryData.nCol1;
463 SCROW nFirstRow = theQueryData.nRow1;
464 SCCOL nMaxCol = theQueryData.nCol2;
465 SCCOL col = 0;
467 for ( col=nFirstCol; col<=nMaxCol; col++ )
469 aFieldName = pDoc->GetString(col, nFirstRow, nTab);
470 if (!m_xBtnHeader->get_active() || aFieldName.isEmpty())
472 aFieldName = ScGlobal::ReplaceOrAppend( aStrColumn, u"%1", ScColToAlpha( col ));
474 m_xLbField1->append_text( aFieldName );
475 m_xLbField2->append_text( aFieldName );
476 m_xLbField3->append_text( aFieldName );
477 m_xLbField4->append_text( aFieldName );
481 m_xLbField4->thaw();
482 m_xLbField3->thaw();
483 m_xLbField2->thaw();
484 m_xLbField1->thaw();
487 void ScFilterDlg::UpdateValueList( size_t nList )
489 bool bCaseSens = m_xBtnCase->get_active();
491 if (pDoc && nList > 0 && nList <= QUERY_ENTRY_COUNT)
493 weld::ComboBox* pValList = maValueEdArr[nList-1];
494 const sal_Int32 nFieldSelPos = maFieldLbArr[nList-1]->get_active();
495 OUString aCurValue = pValList->get_active_text();
497 std::unique_ptr<weld::WaitObject> xWaiter;
498 std::vector<weld::ComboBoxEntry> aEntries;
499 aEntries.emplace_back(aStrNotEmpty);
500 aEntries.emplace_back(aStrEmpty);
502 if (nFieldSelPos)
504 xWaiter.reset(new weld::WaitObject(m_xDialog.get())); // even if only the list box has content
505 SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
506 EntryList* pList = nullptr;
507 if (!m_EntryLists.count(nColumn))
509 size_t nOffset = GetSliderPos();
510 SCTAB nTab = nSrcTab;
511 SCROW nFirstRow = theQueryData.nRow1;
512 SCROW nLastRow = theQueryData.nRow2;
513 if (maHasDates.size() < nOffset+nList)
514 maHasDates.resize(nOffset+nList, false);
515 maHasDates[nOffset+nList-1] = false;
517 // first without the first line
518 std::pair<EntryListsMap::iterator, bool> r =
519 m_EntryLists.insert(std::make_pair(nColumn, std::make_unique<EntryList>()));
520 if (!r.second)
521 // insertion failed.
522 return;
524 pList = r.first->second.get();
525 pDoc->GetFilterEntriesArea(
526 nColumn, nFirstRow+1, nLastRow,
527 nTab, bCaseSens, pList->maFilterEntries);
528 maHasDates[nOffset+nList-1] = pList->maFilterEntries.mbHasDates;
530 // Entry for the first line
531 //! Entry (pHdrEntry) doesn't generate collection?
533 pList->mnHeaderPos = INVALID_HEADER_POS;
534 ScFilterEntries aHdrColl;
535 pDoc->GetFilterEntriesArea(
536 nColumn, nFirstRow, nFirstRow, nTab, true, aHdrColl );
537 if (!aHdrColl.empty())
539 // See if the header value is already in the list.
540 std::vector<ScTypedStrData>::iterator itBeg = pList->maFilterEntries.begin(), itEnd = pList->maFilterEntries.end();
541 if (std::none_of(itBeg, itEnd, FindTypedStrData(aHdrColl.front(), bCaseSens)))
543 // Not in the list. Insert it.
544 pList->maFilterEntries.push_back(aHdrColl.front());
545 if (bCaseSens)
546 std::sort(pList->maFilterEntries.begin(), pList->maFilterEntries.end(), ScTypedStrData::LessCaseSensitive());
547 else
548 std::sort(pList->maFilterEntries.begin(), pList->maFilterEntries.end(), ScTypedStrData::LessCaseInsensitive());
550 // Record its position.
551 itBeg = pList->maFilterEntries.begin();
552 itEnd = pList->maFilterEntries.end();
553 auto it = std::find_if(itBeg, itEnd, FindTypedStrData(aHdrColl.front(), bCaseSens));
554 pList->mnHeaderPos = std::distance(itBeg, it);
558 else
559 pList = m_EntryLists[nColumn].get();
561 assert(pList);
563 for (const auto& rEntry : pList->maFilterEntries)
564 aEntries.emplace_back(rEntry.GetString());
566 pValList->insert_vector(aEntries, false);
567 pValList->set_entry_text(aCurValue);
570 UpdateHdrInValueList( nList );
573 void ScFilterDlg::UpdateHdrInValueList( size_t nList )
575 //! GetText / SetText ??
577 if (!pDoc)
578 return;
580 if (nList == 0 || nList > QUERY_ENTRY_COUNT)
581 return;
583 size_t nFieldSelPos = maFieldLbArr[nList-1]->get_active();
584 if (!nFieldSelPos)
585 return;
587 SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
588 if (!m_EntryLists.count(nColumn))
590 OSL_FAIL("column not yet initialized");
591 return;
594 size_t const nPos = m_EntryLists[nColumn]->mnHeaderPos;
595 if (nPos == INVALID_HEADER_POS)
596 return;
598 weld::ComboBox* pValList = maValueEdArr[nList-1];
599 int nListPos = nPos + 2; // for "empty" and "non-empty"
601 const ScTypedStrData& rHdrEntry = m_EntryLists[nColumn]->maFilterEntries.maStrData[nPos];
603 const OUString& aHdrStr = rHdrEntry.GetString();
604 bool bWasThere = nListPos < pValList->get_count() && aHdrStr == pValList->get_text(nListPos);
605 bool bInclude = !m_xBtnHeader->get_active();
607 if (bInclude) // Include entry
609 if (!bWasThere)
610 pValList->insert_text(nListPos, aHdrStr);
612 else // Omit entry
614 if (bWasThere)
615 pValList->remove(nListPos);
619 void ScFilterDlg::ClearValueList( size_t nList )
621 if (nList > 0 && nList <= QUERY_ENTRY_COUNT)
623 weld::ComboBox* pValList = maValueEdArr[nList-1];
624 pValList->clear();
625 pValList->append_text( aStrNotEmpty );
626 pValList->append_text( aStrEmpty );
627 pValList->set_entry_text( OUString() );
631 void ScFilterDlg::UpdateColorList(size_t nList)
633 if (!pDoc || nList <= 0 || nList > QUERY_ENTRY_COUNT)
634 return;
636 size_t nPos = nList - 1;
637 ScQueryEntry& rEntry = theQueryData.GetEntry(nPos);
638 const sal_Int32 nFieldSelPos = maFieldLbArr[nPos]->get_active();
639 if (!nFieldSelPos)
640 return;
642 SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
643 EntryList* pList = m_EntryLists[nColumn].get();
644 if (!pList)
645 return;
647 std::set<Color> aColors;
648 OUString sSelectedCondition = maCondLbArr[nPos]->get_active_text();
649 if (sSelectedCondition == aStrFontColor)
650 aColors = pList->maFilterEntries.getTextColors();
651 else if (sSelectedCondition == aStrBackgroundColor)
652 aColors = pList->maFilterEntries.getBackgroundColors();
653 else
654 return;
656 maColorLbArr[nPos]->clear();
657 for (const auto& rColor : aColors)
659 OUString sId = rColor.AsRGBHexString();
660 if (rColor == COL_AUTO)
662 OUString sText = sSelectedCondition == aStrFontColor
663 ? ScResId(SCSTR_FILTER_AUTOMATIC_COLOR)
664 : ScResId(SCSTR_FILTER_NO_FILL);
665 maColorLbArr[nPos]->append(sId, sText);
667 else
669 VirtualDevice* pDev = lcl_getColorImage(rColor);
670 maColorLbArr[nPos]->append(sId, OUString(), *pDev);
673 const auto& rItem = rEntry.GetQueryItem();
674 if (rItem.maColor == rColor
675 && ((sSelectedCondition == aStrFontColor && rItem.meType == ScQueryEntry::ByTextColor)
676 || (sSelectedCondition == aStrBackgroundColor
677 && rItem.meType == ScQueryEntry::ByBackgroundColor)))
679 maColorLbArr[nPos]->set_active_id(sId);
684 size_t ScFilterDlg::GetFieldSelPos( SCCOL nField )
686 if ( nField >= theQueryData.nCol1 && nField <= theQueryData.nCol2 )
687 return static_cast<size_t>(nField - theQueryData.nCol1 + 1);
688 else
689 return 0;
692 ScQueryItem* ScFilterDlg::GetOutputItem()
694 ScAddress theCopyPos;
695 ScQueryParam theParam( theQueryData );
696 bool bCopyPosOk = false;
698 if ( m_xBtnCopyResult->get_active() )
700 ScRefFlags nResult = theCopyPos.Parse(
701 m_xEdCopyArea->GetText(), *pDoc, pDoc->GetAddressConvention());
702 bCopyPosOk = (nResult & ScRefFlags::VALID) == ScRefFlags::VALID;
705 if ( m_xBtnCopyResult->get_active() && bCopyPosOk )
707 theParam.bInplace = false;
708 theParam.nDestTab = theCopyPos.Tab();
709 theParam.nDestCol = theCopyPos.Col();
710 theParam.nDestRow = theCopyPos.Row();
712 else
714 theParam.bInplace = true;
715 theParam.nDestTab = 0;
716 theParam.nDestCol = 0;
717 theParam.nDestRow = 0;
720 theParam.bHasHeader = m_xBtnHeader->get_active();
721 theParam.bByRow = true;
722 theParam.bDuplicate = !m_xBtnUnique->get_active();
723 theParam.bCaseSens = m_xBtnCase->get_active();
724 theParam.eSearchType = m_xBtnRegExp->get_active() ? utl::SearchParam::SearchType::Regexp : utl::SearchParam::SearchType::Normal;
725 theParam.bDestPers = m_xBtnDestPers->get_active();
727 // only set the three - reset everything else
729 pOutItem.reset( new ScQueryItem( nWhichQuery, &theParam ) );
731 return pOutItem.get();
734 bool ScFilterDlg::IsRefInputMode() const
736 return bRefInputMode;
739 // Handler:
741 IMPL_LINK( ScFilterDlg, BtnClearHdl, weld::Button&, rBtn, void )
743 if ( &rBtn != m_xBtnClear.get() )
744 return;
746 // scroll to the top
747 m_xScrollBar->vadjustment_set_value(0);
748 size_t nOffset = 0;
749 RefreshEditRow( nOffset);
751 // clear all conditions
752 m_xLbConnect1->set_active(-1);
753 m_xLbConnect2->set_active(-1);
754 m_xLbConnect3->set_active(-1);
755 m_xLbConnect4->set_active(-1);
756 m_xLbField1->set_active(0);
757 m_xLbField2->set_active(0);
758 m_xLbField3->set_active(0);
759 m_xLbField4->set_active(0);
760 m_xLbCond1->set_active(0);
761 m_xLbCond2->set_active(0);
762 m_xLbCond3->set_active(0);
763 m_xLbCond4->set_active(0);
764 ClearValueList( 1 );
765 ClearValueList( 2 );
766 ClearValueList( 3 );
767 ClearValueList( 4 );
769 // disable fields for second row onward
770 m_xLbConnect2->set_sensitive(false);
771 m_xLbConnect3->set_sensitive(false);
772 m_xLbConnect4->set_sensitive(false);
773 m_xLbField2->set_sensitive(false);
774 m_xLbField3->set_sensitive(false);
775 m_xLbField4->set_sensitive(false);
776 m_xLbCond2->set_sensitive(false);
777 m_xLbCond3->set_sensitive(false);
778 m_xLbCond4->set_sensitive(false);
779 m_xEdVal2->set_sensitive(false);
780 m_xEdVal3->set_sensitive(false);
781 m_xEdVal4->set_sensitive(false);
782 m_xLbColor2->set_sensitive(false);
783 m_xLbColor3->set_sensitive(false);
784 m_xLbColor4->set_sensitive(false);
785 m_xBtnRemove2->set_sensitive(false);
786 m_xBtnRemove3->set_sensitive(false);
787 m_xBtnRemove4->set_sensitive(false);
789 // clear query data objects
790 SCSIZE nCount = theQueryData.GetEntryCount();
791 if (maRefreshExceptQuery.size() < nCount + 1)
792 maRefreshExceptQuery.resize(nCount + 1, false);
793 for (SCSIZE i = 0; i < nCount; ++i)
795 theQueryData.GetEntry(i).bDoQuery = false;
796 maRefreshExceptQuery[i] = false;
797 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
799 maRefreshExceptQuery[0] = true;
802 IMPL_LINK( ScFilterDlg, EndDlgHdl, weld::Button&, rBtn, void )
804 if ( &rBtn == m_xBtnOk.get() )
806 bool bAreaInputOk = true;
808 if ( m_xBtnCopyResult->get_active() )
810 if ( !pOptionsMgr->VerifyPosStr( m_xEdCopyArea->GetText() ) )
812 if (!m_xExpander->get_expanded())
813 m_xExpander->set_expanded(true);
815 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
816 VclMessageType::Warning, VclButtonsType::Ok,
817 ScResId(STR_INVALID_TABREF)));
818 xBox->run();
819 m_xEdCopyArea->GrabFocus();
820 bAreaInputOk = false;
824 if ( bAreaInputOk )
826 SetDispatcherLock( false );
827 SwitchToDocument();
828 GetBindings().GetDispatcher()->ExecuteList(FID_FILTER_OK,
829 SfxCallMode::SLOT | SfxCallMode::RECORD,
830 { GetOutputItem() });
831 response(RET_OK);
834 else if ( &rBtn == m_xBtnCancel.get() )
836 response(RET_CANCEL);
840 IMPL_LINK_NOARG(ScFilterDlg, MoreExpandedHdl, weld::Expander&, void)
842 if ( m_xExpander->get_expanded() )
843 pTimer->Start();
844 else
846 pTimer->Stop();
847 bRefInputMode = false;
848 //@BugID 54702 Enable/disable only in Basic class
849 //SFX_APPWINDOW->Disable(FALSE); //! general method in ScAnyRefDlg
853 IMPL_LINK( ScFilterDlg, TimeOutHdl, Timer*, _pTimer, void )
855 // Check if RefInputMode is still true every 50ms
856 if (_pTimer == pTimer.get() && m_xDialog->has_toplevel_focus())
857 bRefInputMode = (m_xEdCopyArea->GetWidget()->has_focus() || m_xRbCopyArea->GetWidget()->has_focus());
859 if ( m_xExpander->get_expanded() )
860 pTimer->Start();
863 IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
866 * Handle enable/disable logic depending on which ListBox was selected
868 sal_uInt16 nOffset = GetSliderPos();
870 if ( &rLb == m_xLbConnect1.get() )
872 m_xLbField1->set_sensitive(true);
873 m_xLbCond1->set_sensitive(true);
874 m_xEdVal1->set_sensitive(true);
875 m_xBtnRemove1->set_sensitive(true);
877 const sal_Int32 nConnect1 = m_xLbConnect1->get_active();
878 size_t nQE = nOffset;
879 theQueryData.GetEntry(nQE).eConnect =static_cast<ScQueryConnect>(nConnect1);
880 if (maRefreshExceptQuery.size() < nQE + 1)
881 maRefreshExceptQuery.resize(nQE + 1, false);
882 maRefreshExceptQuery[nQE] = true;
884 else if ( &rLb == m_xLbConnect2.get() )
886 m_xLbField2->set_sensitive(true);
887 m_xLbCond2->set_sensitive(true);
888 m_xEdVal2->set_sensitive(true);
889 m_xBtnRemove2->set_sensitive(true);
891 const sal_Int32 nConnect2 = m_xLbConnect2->get_active();
892 size_t nQE = 1+nOffset;
893 theQueryData.GetEntry(nQE).eConnect =static_cast<ScQueryConnect>(nConnect2);
894 if (maRefreshExceptQuery.size() < nQE + 1)
895 maRefreshExceptQuery.resize(nQE + 1, false);
896 maRefreshExceptQuery[nQE]=true;
898 else if ( &rLb == m_xLbConnect3.get() )
900 m_xLbField3->set_sensitive(true);
901 m_xLbCond3->set_sensitive(true);
902 m_xEdVal3->set_sensitive(true);
903 m_xBtnRemove3->set_sensitive(true);
905 const sal_Int32 nConnect3 = m_xLbConnect3->get_active();
906 size_t nQE = 2 + nOffset;
907 theQueryData.GetEntry(nQE).eConnect = static_cast<ScQueryConnect>(nConnect3);
908 if (maRefreshExceptQuery.size() < nQE + 1)
909 maRefreshExceptQuery.resize(nQE + 1, false);
910 maRefreshExceptQuery[nQE] = true;
913 else if ( &rLb == m_xLbConnect4.get() )
915 m_xLbField4->set_sensitive(true);
916 m_xLbCond4->set_sensitive(true);
917 m_xEdVal4->set_sensitive(true);
918 m_xLbColor4->set_sensitive(true);
919 m_xBtnRemove4->set_sensitive(true);
921 const sal_Int32 nConnect4 = m_xLbConnect4->get_active();
922 size_t nQE = 3 + nOffset;
923 theQueryData.GetEntry(nQE).eConnect = static_cast<ScQueryConnect>(nConnect4);
924 if (maRefreshExceptQuery.size() < nQE + 1)
925 maRefreshExceptQuery.resize(nQE + 1, false);
926 maRefreshExceptQuery[nQE] = true;
928 else if ( &rLb == m_xLbField1.get() )
930 if ( m_xLbField1->get_active() == 0 )
932 m_xLbConnect2->set_active(-1);
933 m_xLbConnect3->set_active(-1);
934 m_xLbConnect4->set_active(-1);
935 m_xLbField2->set_active( 0 );
936 m_xLbField3->set_active( 0 );
937 m_xLbField4->set_active( 0 );
938 m_xLbCond2->set_active( 0 );
939 m_xLbCond3->set_active( 0 );
940 m_xLbCond4->set_active( 0 );
941 ClearValueList( 1 );
942 ClearValueList( 2 );
943 ClearValueList( 3 );
944 ClearValueList( 4 );
946 m_xLbConnect2->set_sensitive(false);
947 m_xLbConnect3->set_sensitive(false);
948 m_xLbConnect4->set_sensitive(false);
949 m_xLbField2->set_sensitive(false);
950 m_xLbField3->set_sensitive(false);
951 m_xLbField4->set_sensitive(false);
952 m_xLbCond2->set_sensitive(false);
953 m_xLbCond3->set_sensitive(false);
954 m_xLbCond4->set_sensitive(false);
955 m_xEdVal2->set_sensitive(false);
956 m_xEdVal3->set_sensitive(false);
957 m_xEdVal4->set_sensitive(false);
958 m_xLbColor2->set_sensitive(false);
959 m_xLbColor3->set_sensitive(false);
960 m_xLbColor4->set_sensitive(false);
961 m_xBtnRemove2->set_sensitive(false);
962 m_xBtnRemove3->set_sensitive(false);
963 m_xBtnRemove4->set_sensitive(false);
964 SCSIZE nCount = theQueryData.GetEntryCount();
965 if (maRefreshExceptQuery.size() < nCount + 1)
966 maRefreshExceptQuery.resize(nCount + 1, false);
967 for (SCSIZE i = nOffset; i < nCount; ++i)
969 theQueryData.GetEntry(i).bDoQuery = false;
970 maRefreshExceptQuery[i] = false;
971 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
973 maRefreshExceptQuery[nOffset] = true;
975 else
977 UpdateValueList( 1 );
978 UpdateColorList( 1 );
979 if ( !m_xLbConnect2->get_sensitive() )
981 m_xLbConnect2->set_sensitive(true);
983 theQueryData.GetEntry(nOffset).bDoQuery = true;
984 const sal_Int32 nField = rLb.get_active();
985 theQueryData.GetEntry(nOffset).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
988 else if ( &rLb == m_xLbField2.get() )
990 if ( m_xLbField2->get_active() == 0 )
992 m_xLbConnect3->set_active(-1);
993 m_xLbConnect4->set_active(-1);
994 m_xLbField3->set_active( 0 );
995 m_xLbField4->set_active( 0 );
996 m_xLbCond3->set_active( 0 );
997 m_xLbCond4->set_active( 0 );
998 ClearValueList( 2 );
999 ClearValueList( 3 );
1000 ClearValueList( 4 );
1002 m_xLbConnect3->set_sensitive(false);
1003 m_xLbConnect4->set_sensitive(false);
1004 m_xLbField3->set_sensitive(false);
1005 m_xLbField4->set_sensitive(false);
1006 m_xLbCond3->set_sensitive(false);
1007 m_xLbCond4->set_sensitive(false);
1008 m_xEdVal3->set_sensitive(false);
1009 m_xEdVal4->set_sensitive(false);
1010 m_xLbColor3->set_sensitive(false);
1011 m_xLbColor4->set_sensitive(false);
1012 m_xBtnRemove3->set_sensitive(false);
1013 m_xBtnRemove4->set_sensitive(false);
1015 sal_uInt16 nTemp=nOffset+1;
1016 SCSIZE nCount = theQueryData.GetEntryCount();
1017 if (maRefreshExceptQuery.size() < nCount)
1018 maRefreshExceptQuery.resize(nCount, false);
1019 for (SCSIZE i= nTemp; i< nCount; i++)
1021 theQueryData.GetEntry(i).bDoQuery = false;
1022 maRefreshExceptQuery[i] = false;
1023 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
1025 maRefreshExceptQuery[nTemp] = true;
1027 else
1029 UpdateValueList( 2 );
1030 UpdateColorList( 2 );
1031 if ( !m_xLbConnect3->get_sensitive() )
1033 m_xLbConnect3->set_sensitive(true);
1035 const sal_Int32 nField = rLb.get_active();
1036 sal_uInt16 nQ=1+nOffset;
1037 theQueryData.GetEntry(nQ).bDoQuery = true;
1038 theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
1041 else if ( &rLb == m_xLbField3.get() )
1043 if ( m_xLbField3->get_active() == 0 )
1045 m_xLbConnect4->set_active(-1);
1046 m_xLbField4->set_active( 0 );
1047 m_xLbCond4->set_active( 0 );
1048 ClearValueList( 3 );
1049 ClearValueList( 4 );
1051 m_xLbConnect4->set_sensitive(false);
1052 m_xLbField4->set_sensitive(false);
1053 m_xLbCond4->set_sensitive(false);
1054 m_xEdVal4->set_sensitive(false);
1055 m_xLbColor4->set_sensitive(false);
1056 m_xBtnRemove4->set_sensitive(false);
1058 sal_uInt16 nTemp=nOffset+2;
1059 SCSIZE nCount = theQueryData.GetEntryCount();
1060 if (maRefreshExceptQuery.size() < nCount)
1061 maRefreshExceptQuery.resize(nCount, false);
1062 for (SCSIZE i = nTemp; i < nCount; ++i)
1064 theQueryData.GetEntry(i).bDoQuery = false;
1065 maRefreshExceptQuery[i] = false;
1066 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
1068 maRefreshExceptQuery[nTemp] = true;
1070 else
1072 UpdateValueList( 3 );
1073 UpdateColorList( 3 );
1074 if ( !m_xLbConnect4->get_sensitive() )
1076 m_xLbConnect4->set_sensitive(true);
1079 const sal_Int32 nField = rLb.get_active();
1080 sal_uInt16 nQ=2+nOffset;
1081 theQueryData.GetEntry(nQ).bDoQuery = true;
1082 theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
1086 else if ( &rLb == m_xLbField4.get() )
1088 if ( m_xLbField4->get_active() == 0 )
1090 ClearValueList( 4 );
1091 sal_uInt16 nTemp=nOffset+3;
1092 SCSIZE nCount = theQueryData.GetEntryCount();
1093 if (maRefreshExceptQuery.size() < nCount)
1094 maRefreshExceptQuery.resize(nCount, false);
1095 for (SCSIZE i = nTemp; i < nCount; ++i)
1097 theQueryData.GetEntry(i).bDoQuery = false;
1098 maRefreshExceptQuery[i] = false;
1099 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
1101 maRefreshExceptQuery[nTemp] = true;
1103 else
1105 UpdateValueList( 4 );
1106 UpdateColorList( 4 );
1107 const sal_Int32 nField = rLb.get_active();
1108 sal_uInt16 nQ=3+nOffset;
1109 theQueryData.GetEntry(nQ).bDoQuery = true;
1110 theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
1114 else if (&rLb == m_xLbCond1.get() || &rLb == m_xLbCond2.get() || &rLb == m_xLbCond3.get()
1115 || &rLb == m_xLbCond4.get())
1117 ScQueryOp op;
1118 sal_uInt16 nQ = 0;
1119 bool bEnableColorLb = false;
1120 if (rLb.get_active_text() == aStrFontColor || rLb.get_active_text() == aStrBackgroundColor)
1122 bEnableColorLb = true;
1123 op = SC_EQUAL;
1125 else
1127 op = static_cast<ScQueryOp>(rLb.get_active());
1130 if (&rLb == m_xLbCond1.get())
1132 nQ = nOffset;
1133 m_xLbColor1->set_visible(bEnableColorLb);
1134 m_xLbColor1->set_sensitive(bEnableColorLb);
1135 m_xEdVal1->set_visible(!bEnableColorLb);
1136 UpdateColorList(1);
1138 else if (&rLb == m_xLbCond2.get())
1140 nQ = 1 + nOffset;
1141 m_xLbColor2->set_visible(bEnableColorLb);
1142 m_xLbColor2->set_sensitive(bEnableColorLb);
1143 m_xEdVal2->set_visible(!bEnableColorLb);
1144 UpdateColorList(2);
1146 else if (&rLb == m_xLbCond3.get())
1148 nQ = 2 + nOffset;
1149 m_xLbColor3->set_visible(bEnableColorLb);
1150 m_xLbColor3->set_sensitive(bEnableColorLb);
1151 m_xEdVal3->set_visible(!bEnableColorLb);
1152 UpdateColorList(3);
1154 else if (&rLb == m_xLbCond4.get())
1156 nQ = 3 + nOffset;
1157 m_xLbColor4->set_visible(bEnableColorLb);
1158 m_xLbColor4->set_sensitive(bEnableColorLb);
1159 m_xEdVal4->set_visible(!bEnableColorLb);
1160 UpdateColorList(4);
1163 auto aEntry = theQueryData.GetEntry(nQ);
1164 aEntry.eOp = op;
1166 else if (&rLb == m_xLbColor1.get() || &rLb == m_xLbColor2.get() || &rLb == m_xLbColor3.get()
1167 || &rLb == m_xLbColor4.get())
1169 sal_uInt16 nQ = 0;
1170 if (&rLb == m_xLbColor1.get())
1172 nQ = nOffset;
1174 else if (&rLb == m_xLbColor2.get())
1176 nQ = 1 + nOffset;
1178 else if (&rLb == m_xLbColor3.get())
1180 nQ = 2 + nOffset;
1182 else if (&rLb == m_xLbColor4.get())
1184 nQ = 3 + nOffset;
1187 ScQueryEntry& aEntry = theQueryData.GetEntry(nQ);
1188 Color aColor = Color::STRtoRGB(maColorLbArr[nQ]->get_active_id());
1189 if (maCondLbArr[nQ]->get_active_text() == aStrFontColor)
1191 aEntry.SetQueryByTextColor(aColor);
1193 else if (maCondLbArr[nQ]->get_active_text() == aStrBackgroundColor)
1195 aEntry.SetQueryByBackgroundColor(aColor);
1200 IMPL_LINK( ScFilterDlg, CheckBoxHdl, weld::Toggleable&, rBox, void )
1202 // Column headers:
1203 // Field list: Columnxx <-> column header string
1204 // Value list: Column header value not applicable.
1205 // Upper/lower case:
1206 // Value list: completely new
1208 if ( &rBox == m_xBtnHeader.get() ) // Field list and value list
1210 const sal_Int32 nCurSel1 = m_xLbField1->get_active();
1211 const sal_Int32 nCurSel2 = m_xLbField2->get_active();
1212 const sal_Int32 nCurSel3 = m_xLbField3->get_active();
1213 const sal_Int32 nCurSel4 = m_xLbField4->get_active();
1214 FillFieldLists();
1215 m_xLbField1->set_active( nCurSel1 );
1216 m_xLbField2->set_active( nCurSel2 );
1217 m_xLbField3->set_active( nCurSel3 );
1218 m_xLbField4->set_active( nCurSel4 );
1220 UpdateHdrInValueList( 1 );
1221 UpdateHdrInValueList( 2 );
1222 UpdateHdrInValueList( 3 );
1223 UpdateHdrInValueList( 4 );
1226 if ( &rBox != m_xBtnCase.get() ) // Complete value list
1227 return;
1229 m_EntryLists.clear();
1230 UpdateValueList( 1 ); // current text is recorded
1231 UpdateValueList( 2 );
1232 UpdateValueList( 3 );
1233 UpdateValueList( 4 );
1235 UpdateColorList( 1 );
1236 UpdateColorList( 2 );
1237 UpdateColorList( 3 );
1238 UpdateColorList( 4 );
1241 IMPL_LINK( ScFilterDlg, ValModifyHdl, weld::ComboBox&, rEd, void )
1243 size_t nOffset = GetSliderPos();
1244 size_t i = 0;
1245 size_t nQE = i + nOffset;
1246 OUString aStrVal = rEd.get_active_text();
1247 weld::ComboBox* pLbCond = m_xLbCond1.get();
1248 weld::ComboBox* pLbField = m_xLbField1.get();
1249 if ( &rEd == m_xEdVal2.get() )
1251 pLbCond = m_xLbCond2.get();
1252 pLbField = m_xLbField2.get();
1253 i=1;
1254 nQE=i+nOffset;
1256 if ( &rEd == m_xEdVal3.get() )
1258 pLbCond = m_xLbCond3.get();
1259 pLbField = m_xLbField3.get();
1260 i=2;
1261 nQE=i+nOffset;
1263 if ( &rEd == m_xEdVal4.get() )
1265 pLbCond = m_xLbCond4.get();
1266 pLbField = m_xLbField4.get();
1267 i=3;
1268 nQE=i+nOffset;
1271 if ( aStrEmpty == aStrVal || aStrNotEmpty == aStrVal )
1273 pLbCond->set_active_text(OUString('='));
1274 pLbCond->set_sensitive(false);
1276 else
1277 pLbCond->set_sensitive(true);
1279 if (maHasDates.size() < nQE + 1)
1280 maHasDates.resize(nQE + 1, false);
1281 if (maRefreshExceptQuery.size() < nQE + 1)
1282 maRefreshExceptQuery.resize(nQE + 1, false);
1284 ScQueryEntry& rEntry = theQueryData.GetEntry( nQE );
1285 ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
1286 bool bDoThis = (pLbField->get_active() != 0);
1287 rEntry.bDoQuery = bDoThis;
1289 if ( !(rEntry.bDoQuery || maRefreshExceptQuery[nQE]) )
1290 return;
1292 bool bByEmptyOrNotByEmpty = false;
1293 if ( aStrEmpty == aStrVal )
1295 bByEmptyOrNotByEmpty = true;
1296 rEntry.SetQueryByEmpty();
1298 else if ( aStrNotEmpty == aStrVal )
1300 bByEmptyOrNotByEmpty = true;
1301 rEntry.SetQueryByNonEmpty();
1303 else
1305 rItem.maString = pDoc->GetSharedStringPool().intern(aStrVal);
1306 rItem.mfVal = 0.0;
1307 rItem.meType = ScQueryEntry::ByString;
1310 const sal_Int32 nField = pLbField->get_active();
1311 rEntry.nField = nField ? (theQueryData.nCol1 +
1312 static_cast<SCCOL>(nField) - 1) : static_cast<SCCOL>(0);
1314 ScQueryOp eOp = static_cast<ScQueryOp>(pLbCond->get_active());
1315 rEntry.eOp = eOp;
1316 if (maHasDates[nQE] && !bByEmptyOrNotByEmpty)
1317 rItem.meType = ScQueryEntry::ByDate;
1320 IMPL_LINK( ScFilterDlg, BtnRemoveHdl, weld::Button&, rBtn, void )
1322 // Calculate the row to delete
1323 sal_uInt16 nOffset = GetSliderPos();
1324 int nButtonIndex = 0;
1325 if ( &rBtn == m_xBtnRemove2.get() )
1326 nButtonIndex = 1;
1327 if ( &rBtn == m_xBtnRemove3.get() )
1328 nButtonIndex = 2;
1329 if ( &rBtn == m_xBtnRemove4.get() )
1330 nButtonIndex = 3;
1331 SCSIZE nRowToDelete = nOffset + nButtonIndex;
1333 // Check that the index is sensible
1334 SCSIZE nCount = theQueryData.GetEntryCount();
1335 if (nRowToDelete >= nCount)
1337 SAL_WARN( "sc", "ScFilterDlg::BtnRemoveHdl: could not delete row - invalid index.");
1338 return;
1341 // Resize maRefreshExceptQuery
1342 if (maRefreshExceptQuery.size() < nCount + 1)
1343 maRefreshExceptQuery.resize(nCount + 1, false);
1345 // Move all the subsequent rows back one position;
1346 // also find the last row, which we will delete
1347 SCSIZE nRowToClear = nCount-1;
1348 for (SCSIZE i = nRowToDelete; i < nCount-1; ++i)
1350 if (theQueryData.GetEntry(i+1).bDoQuery)
1352 theQueryData.GetEntry(i) = theQueryData.GetEntry(i+1);
1354 else
1356 nRowToClear = i;
1357 break;
1361 // If the next row is being edited, but not confirmed, move it back
1362 // one position
1363 if (nRowToClear < nCount-1 && maRefreshExceptQuery[nRowToClear+1])
1365 theQueryData.GetEntry(nRowToClear) = theQueryData.GetEntry(nRowToClear+1);
1366 maRefreshExceptQuery[nRowToClear] = true;
1367 maRefreshExceptQuery[nRowToClear+1] = false;
1369 else
1371 // Remove the very last one, since everything has moved back
1372 theQueryData.GetEntry(nRowToClear).bDoQuery = false;
1373 theQueryData.GetEntry(nRowToClear).nField = static_cast<SCCOL>(0);
1374 maRefreshExceptQuery[nRowToClear] = false;
1377 // Always enable the very first row
1378 if (!theQueryData.GetEntry(0).bDoQuery)
1380 maRefreshExceptQuery[0] = true;
1383 // Refresh the UI
1384 RefreshEditRow( nOffset );
1386 // Special handling if the very first row was cleared
1387 if (!theQueryData.GetEntry(0).bDoQuery)
1389 m_xLbConnect1->set_active(-1);
1390 m_xLbField1->set_active(0);
1391 m_xLbField1->set_sensitive(true);
1392 m_xLbCond1->set_active(0);
1393 m_xLbCond1->set_sensitive(true);
1394 ClearValueList(1);
1398 IMPL_LINK_NOARG(ScFilterDlg, ScrollHdl, weld::ScrolledWindow&, void)
1400 SliderMoved();
1403 void ScFilterDlg::SliderMoved()
1405 size_t nOffset = GetSliderPos();
1406 RefreshEditRow( nOffset);
1409 size_t ScFilterDlg::GetSliderPos() const
1411 return static_cast<size_t>(m_xScrollBar->vadjustment_get_value());
1414 void ScFilterDlg::RefreshEditRow( size_t nOffset )
1416 if (nOffset==0)
1417 maConnLbArr[0]->hide();
1418 else
1419 maConnLbArr[0]->show();
1421 for (size_t i = 0; i < QUERY_ENTRY_COUNT; ++i)
1423 OUString aValStr;
1424 size_t nCondPos = 0;
1425 size_t nFieldSelPos = 0;
1426 size_t nQE = i + nOffset;
1428 maColorLbArr[i]->set_visible(false);
1430 if (maRefreshExceptQuery.size() < nQE + 1)
1431 maRefreshExceptQuery.resize(nQE + 1, false);
1433 ScQueryEntry& rEntry = theQueryData.GetEntry( nQE);
1434 if ( rEntry.bDoQuery || maRefreshExceptQuery[nQE] )
1436 nCondPos = static_cast<size_t>(rEntry.eOp);
1437 if(rEntry.bDoQuery)
1438 nFieldSelPos = GetFieldSelPos( static_cast<SCCOL>(rEntry.nField) );
1440 const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
1441 OUString aQueryStr = rItem.maString.getString();
1442 if (rEntry.IsQueryByEmpty())
1444 aValStr = aStrEmpty;
1445 maCondLbArr[i]->set_sensitive(false);
1447 else if (rEntry.IsQueryByNonEmpty())
1449 aValStr = aStrNotEmpty;
1450 maCondLbArr[i]->set_sensitive(false);
1452 else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor())
1454 nCondPos = maCondLbArr[i]->find_text(
1455 rEntry.IsQueryByTextColor() ? aStrFontColor : aStrBackgroundColor);
1457 maValueEdArr[i]->set_visible(false);
1458 maColorLbArr[i]->set_visible(true);
1459 maColorLbArr[i]->set_sensitive(true);
1461 else
1463 SetValString(aQueryStr, rItem, aValStr);
1464 maCondLbArr[i]->set_sensitive(true);
1466 maFieldLbArr[i]->set_sensitive(true);
1467 maValueEdArr[i]->set_sensitive(true);
1468 maRemoveBtnArr[i]->set_sensitive(true);
1470 if (nOffset==0)
1472 if (i<3)
1474 if(rEntry.bDoQuery)
1475 maConnLbArr[i+1]->set_sensitive(true);
1476 else
1477 maConnLbArr[i+1]->set_sensitive(false);
1478 size_t nQENext = nQE + 1;
1479 if (maRefreshExceptQuery.size() < nQENext + 1)
1480 maRefreshExceptQuery.resize(nQENext + 1, false);
1481 if (theQueryData.GetEntry(nQENext).bDoQuery || maRefreshExceptQuery[nQENext])
1482 maConnLbArr[i+1]->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(nQENext).eConnect) );
1483 else
1484 maConnLbArr[i+1]->set_active(-1);
1487 else
1489 if(theQueryData.GetEntry( nQE-1).bDoQuery)
1490 maConnLbArr[i]->set_sensitive(true);
1491 else
1492 maConnLbArr[i]->set_sensitive(false);
1494 if (maRefreshExceptQuery.size() < nQE + 1)
1495 maRefreshExceptQuery.resize(nQE + 1, false);
1496 if(rEntry.bDoQuery || maRefreshExceptQuery[nQE])
1497 maConnLbArr[i]->set_active( static_cast<sal_uInt16>(rEntry.eConnect) );
1498 else
1499 maConnLbArr[i]->set_active(-1);
1503 else
1505 if (nOffset==0)
1507 if(i<3)
1509 maConnLbArr[i+1]->set_active(-1);
1510 maConnLbArr[i+1]->set_sensitive(false);
1513 else
1515 if(theQueryData.GetEntry( nQE-1).bDoQuery)
1516 maConnLbArr[i]->set_sensitive(true);
1517 else
1518 maConnLbArr[i]->set_sensitive(false);
1519 maConnLbArr[i]->set_active(-1);
1521 maFieldLbArr[i]->set_sensitive(false);
1522 maCondLbArr[i]->set_sensitive(false);
1523 maValueEdArr[i]->set_sensitive(false);
1524 maRemoveBtnArr[i]->set_sensitive(false);
1526 maFieldLbArr[i]->set_active( nFieldSelPos );
1527 maCondLbArr [i]->set_active( nCondPos );
1528 maValueEdArr[i]->set_entry_text( aValStr );
1529 UpdateValueList(i+1);
1530 UpdateColorList(i+1);
1534 void ScFilterDlg::SetValString( const OUString& rQueryStr, const ScQueryEntry::Item& rItem,
1535 OUString& rValStr )
1537 if (rQueryStr.isEmpty())
1539 pDoc = pViewData ? &pViewData->GetDocument() : nullptr;
1540 if (rItem.meType == ScQueryEntry::ByValue)
1542 if (pDoc)
1543 rValStr = pDoc->GetFormatTable()->GetInputLineString(rItem.mfVal, 0);
1545 else if (rItem.meType == ScQueryEntry::ByDate)
1547 if (pDoc)
1549 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1550 rValStr = pFormatter->GetInputLineString(rItem.mfVal,
1551 pFormatter->GetStandardFormat( SvNumFormatType::DATE));
1554 else
1556 SAL_WARN( "sc", "ScFilterDlg::SetValString: empty query string, really?");
1557 rValStr = rQueryStr;
1560 else
1562 // XXX NOTE: if not ByString we just assume this has been
1563 // set to a proper string corresponding to the numeric
1564 // value earlier!
1565 rValStr = rQueryStr;
1569 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */