1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <sfx2/dispatch.hxx>
21 #include <sal/log.hxx>
22
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>
30
31 #include <foptmgr.hxx>
32
33 #include <globstr.hrc>
34 #include <strings.hrc>
35
36 #include <filtdlg.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/weld.hxx>
39 #include <svl/sharedstringpool.hxx>
40
41 #include <limits>
42
43 #define QUERY_ENTRY_COUNT 4
44 #define INVALID_HEADER_POS std::numeric_limits<size_t>::max()
45
EntryList()46 ScFilterDlg::EntryList::EntryList() :
47 mnHeaderPos(INVALID_HEADER_POS) {}
48
ScFilterDlg(SfxBindings * pB,SfxChildWindow * pCW,weld::Window * pParent,const SfxItemSet & rArgSet)49 ScFilterDlg::ScFilterDlg(SfxBindings* pB, SfxChildWindow* pCW, weld::Window* pParent,
50 const SfxItemSet& rArgSet)
51 : ScAnyRefDlgController(pB, pCW, pParent,
52 "modules/scalc/ui/standardfilterdialog.ui", "StandardFilterDialog")
53 , aStrUndefined(ScResId(SCSTR_UNDEFINED))
54 , aStrNone(ScResId(SCSTR_NONE))
55 , aStrEmpty(ScResId(SCSTR_FILTER_EMPTY))
56 , aStrNotEmpty(ScResId(SCSTR_FILTER_NOTEMPTY))
57 , aStrColumn(ScResId(SCSTR_COLUMN))
58 , nWhichQuery(rArgSet.GetPool()->GetWhich(SID_QUERY))
59 , theQueryData(static_cast<const ScQueryItem&>(rArgSet.Get(nWhichQuery)).GetQueryData())
60 , pViewData(nullptr)
61 , pDoc(nullptr)
62 , nSrcTab(0)
63 , bRefInputMode(false)
64 , m_xLbConnect1(m_xBuilder->weld_combo_box("connect1"))
65 , m_xLbField1(m_xBuilder->weld_combo_box("field1"))
66 , m_xLbCond1(m_xBuilder->weld_combo_box("cond1"))
67 , m_xEdVal1(m_xBuilder->weld_combo_box("val1"))
68 , m_xBtnRemove1(m_xBuilder->weld_button("remove1"))
69 , m_xLbConnect2(m_xBuilder->weld_combo_box("connect2"))
70 , m_xLbField2(m_xBuilder->weld_combo_box("field2"))
71 , m_xLbCond2(m_xBuilder->weld_combo_box("cond2"))
72 , m_xEdVal2(m_xBuilder->weld_combo_box("val2"))
73 , m_xBtnRemove2(m_xBuilder->weld_button("remove2"))
74 , m_xLbConnect3(m_xBuilder->weld_combo_box("connect3"))
75 , m_xLbField3(m_xBuilder->weld_combo_box("field3"))
76 , m_xLbCond3(m_xBuilder->weld_combo_box("cond3"))
77 , m_xEdVal3(m_xBuilder->weld_combo_box("val3"))
78 , m_xBtnRemove3(m_xBuilder->weld_button("remove3"))
79 , m_xLbConnect4(m_xBuilder->weld_combo_box("connect4"))
80 , m_xLbField4(m_xBuilder->weld_combo_box("field4"))
81 , m_xLbCond4(m_xBuilder->weld_combo_box("cond4"))
82 , m_xEdVal4(m_xBuilder->weld_combo_box("val4"))
83 , m_xBtnRemove4(m_xBuilder->weld_button("remove4"))
84 , m_xContents(m_xBuilder->weld_widget("grid"))
85 , m_xScrollBar(m_xBuilder->weld_scrolled_window("scrollbar", true))
86 , m_xExpander(m_xBuilder->weld_expander("more"))
87 , m_xBtnClear(m_xBuilder->weld_button("clear"))
88 , m_xBtnOk(m_xBuilder->weld_button("ok"))
89 , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
90 , m_xBtnCase(m_xBuilder->weld_check_button("case"))
91 , m_xBtnRegExp(m_xBuilder->weld_check_button("regexp"))
92 , m_xBtnHeader(m_xBuilder->weld_check_button("header"))
93 , m_xBtnUnique(m_xBuilder->weld_check_button("unique"))
94 , m_xBtnCopyResult(m_xBuilder->weld_check_button("copyresult"))
95 , m_xLbCopyArea(m_xBuilder->weld_combo_box("lbcopyarea"))
96 , m_xEdCopyArea(new formula::RefEdit(m_xBuilder->weld_entry("edcopyarea")))
97 , m_xRbCopyArea(new formula::RefButton(m_xBuilder->weld_button("rbcopyarea")))
98 , m_xBtnDestPers(m_xBuilder->weld_check_button("destpers"))
99 , m_xFtDbAreaLabel(m_xBuilder->weld_label("dbarealabel"))
100 , m_xFtDbArea(m_xBuilder->weld_label("dbarea"))
101 {
102 m_xExpander->connect_expanded(LINK(this, ScFilterDlg, MoreExpandedHdl));
103 m_xEdCopyArea->SetReferences(this, m_xFtDbAreaLabel.get());
104 m_xRbCopyArea->SetReferences(this, m_xEdCopyArea.get());
105
106 Init( rArgSet );
107
108 // Hack: RefInput control
109 pTimer.reset( new Timer("ScFilterTimer") );
110 pTimer->SetTimeout( 50 ); // Wait 50ms
111 pTimer->SetInvokeHandler( LINK( this, ScFilterDlg, TimeOutHdl ) );
112 }
113
~ScFilterDlg()114 ScFilterDlg::~ScFilterDlg()
115 {
116 pOptionsMgr.reset();
117 pOutItem.reset();
118
119 // Hack: RefInput control
120 pTimer->Stop();
121 pTimer.reset();
122 }
123
Init(const SfxItemSet & rArgSet)124 void ScFilterDlg::Init( const SfxItemSet& rArgSet )
125 {
126 const ScQueryItem& rQueryItem = static_cast<const ScQueryItem&>(
127 rArgSet.Get( nWhichQuery ));
128
129 m_xBtnClear->connect_clicked ( LINK( this, ScFilterDlg, BtnClearHdl ) );
130 m_xBtnOk->connect_clicked ( LINK( this, ScFilterDlg, EndDlgHdl ) );
131 m_xBtnCancel->connect_clicked ( LINK( this, ScFilterDlg, EndDlgHdl ) );
132 m_xBtnHeader->connect_toggled ( LINK( this, ScFilterDlg, CheckBoxHdl ) );
133 m_xBtnCase->connect_toggled ( LINK( this, ScFilterDlg, CheckBoxHdl ) );
134
135 m_xLbField1->connect_changed ( LINK( this, ScFilterDlg, LbSelectHdl ) );
136 m_xLbField2->connect_changed ( LINK( this, ScFilterDlg, LbSelectHdl ) );
137 m_xLbField3->connect_changed ( LINK( this, ScFilterDlg, LbSelectHdl ) );
138 m_xLbField4->connect_changed ( LINK( this, ScFilterDlg, LbSelectHdl ) );
139 m_xLbConnect1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
140 m_xLbConnect2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
141 m_xLbConnect3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
142 m_xLbConnect4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
143
144 m_xLbField1->append_text("0000000000");
145 m_xLbField1->set_active(0);
146 auto nPrefWidth = m_xLbField1->get_preferred_size().Width();
147 m_xLbField1->clear();
148
149 m_xLbField1->set_size_request(nPrefWidth, -1);
150 m_xLbField2->set_size_request(nPrefWidth, -1);
151 m_xLbField3->set_size_request(nPrefWidth, -1);
152 m_xLbField4->set_size_request(nPrefWidth, -1);
153
154 m_xLbCond1->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
155 m_xLbCond2->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
156 m_xLbCond3->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
157 m_xLbCond4->connect_changed( LINK( this, ScFilterDlg, LbSelectHdl ) );
158
159 m_xBtnRemove1->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
160 m_xBtnRemove2->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
161 m_xBtnRemove3->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
162 m_xBtnRemove4->connect_clicked( LINK( this, ScFilterDlg, BtnRemoveHdl ) );
163
164 pViewData = rQueryItem.GetViewData();
165 pDoc = pViewData ? &pViewData->GetDocument() : nullptr;
166 nSrcTab = pViewData ? pViewData->GetTabNo() : static_cast<SCTAB>(0);
167
168 // for easier access:
169 maFieldLbArr.reserve(QUERY_ENTRY_COUNT);
170 maFieldLbArr.push_back(m_xLbField1.get());
171 maFieldLbArr.push_back(m_xLbField2.get());
172 maFieldLbArr.push_back(m_xLbField3.get());
173 maFieldLbArr.push_back(m_xLbField4.get());
174 maValueEdArr.reserve(QUERY_ENTRY_COUNT);
175 maValueEdArr.push_back(m_xEdVal1.get());
176 maValueEdArr.push_back(m_xEdVal2.get());
177 maValueEdArr.push_back(m_xEdVal3.get());
178 maValueEdArr.push_back(m_xEdVal4.get());
179 maCondLbArr.reserve(QUERY_ENTRY_COUNT);
180 maCondLbArr.push_back(m_xLbCond1.get());
181 maCondLbArr.push_back(m_xLbCond2.get());
182 maCondLbArr.push_back(m_xLbCond3.get());
183 maCondLbArr.push_back(m_xLbCond4.get());
184 maConnLbArr.reserve(QUERY_ENTRY_COUNT);
185 maConnLbArr.push_back(m_xLbConnect1.get());
186 maConnLbArr.push_back(m_xLbConnect2.get());
187 maConnLbArr.push_back(m_xLbConnect3.get());
188 maConnLbArr.push_back(m_xLbConnect4.get());
189 maRemoveBtnArr.reserve(QUERY_ENTRY_COUNT);
190 maRemoveBtnArr.push_back(m_xBtnRemove1.get());
191 maRemoveBtnArr.push_back(m_xBtnRemove2.get());
192 maRemoveBtnArr.push_back(m_xBtnRemove3.get());
193 maRemoveBtnArr.push_back(m_xBtnRemove4.get());
194
195 // Option initialization:
196 pOptionsMgr.reset( new ScFilterOptionsMgr(
197 pViewData,
198 theQueryData,
199 m_xBtnCase.get(),
200 m_xBtnRegExp.get(),
201 m_xBtnHeader.get(),
202 m_xBtnUnique.get(),
203 m_xBtnCopyResult.get(),
204 m_xBtnDestPers.get(),
205 m_xLbCopyArea.get(),
206 m_xEdCopyArea.get(),
207 m_xRbCopyArea.get(),
208 m_xFtDbAreaLabel.get(),
209 m_xFtDbArea.get(),
210 aStrUndefined ) );
211 // Read in field lists and select entries
212
213 FillFieldLists();
214
215 for (size_t i = 0; i < QUERY_ENTRY_COUNT; ++i)
216 {
217 OUString aValStr;
218 size_t nCondPos = 0;
219 size_t nFieldSelPos = 0;
220
221 ScQueryEntry& rEntry = theQueryData.GetEntry(i);
222 if ( rEntry.bDoQuery )
223 {
224 nCondPos = static_cast<size_t>(rEntry.eOp);
225 nFieldSelPos = GetFieldSelPos( static_cast<SCCOL>(rEntry.nField) );
226 if (rEntry.IsQueryByEmpty())
227 {
228 aValStr = aStrEmpty;
229 maCondLbArr[i]->set_sensitive(false);
230 }
231 else if (rEntry.IsQueryByNonEmpty())
232 {
233 aValStr = aStrNotEmpty;
234 maCondLbArr[i]->set_sensitive(false);
235 }
236 else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor())
237 {
238 // No support for color filters in filter dialog currently
239 continue;
240 }
241 else
242 {
243 const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
244 OUString aQueryStr = rItem.maString.getString();
245 SetValString(aQueryStr, rItem, aValStr);
246 }
247 }
248 else if ( i == 0 )
249 {
250 nFieldSelPos = pViewData ? GetFieldSelPos(pViewData->GetCurX()) : 0;
251 rEntry.nField = nFieldSelPos ? (theQueryData.nCol1 +
252 static_cast<SCCOL>(nFieldSelPos) - 1) : static_cast<SCCOL>(0);
253 rEntry.bDoQuery=true;
254 if (maRefreshExceptQuery.size() < i + 1)
255 maRefreshExceptQuery.resize(i + 1, false);
256 maRefreshExceptQuery[i] = true;
257
258 }
259 maFieldLbArr[i]->set_active( nFieldSelPos );
260 maCondLbArr [i]->set_active( nCondPos );
261 maValueEdArr[i]->set_entry_text( aValStr );
262 maValueEdArr[i]->set_entry_completion(false);
263 maValueEdArr[i]->connect_changed( LINK( this, ScFilterDlg, ValModifyHdl ) );
264 UpdateValueList(i+1);
265 }
266
267 m_xScrollBar->connect_vadjustment_changed( LINK( this, ScFilterDlg, ScrollHdl ) );
268 m_xScrollBar->vadjustment_configure(0, 0, 8, 1, 3, 4);
269 Size aSize(m_xContents->get_preferred_size());
270 m_xContents->set_size_request(aSize.Width(), aSize.Height());
271
272 m_xLbConnect1->hide();
273 // Disable/Enable Logic:
274
275 (m_xLbField1->get_active() != 0)
276 && (m_xLbField2->get_active() != 0)
277 ? m_xLbConnect2->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(1).eConnect) )
278 : m_xLbConnect2->set_active(-1);
279
280 (m_xLbField2->get_active() != 0)
281 && (m_xLbField3->get_active() != 0)
282 ? m_xLbConnect3->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(2).eConnect) )
283 : m_xLbConnect3->set_active(-1);
284
285 (m_xLbField3->get_active() != 0)
286 && (m_xLbField4->get_active() != 0)
287 ? m_xLbConnect4->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(3).eConnect) )
288 : m_xLbConnect4->set_active(-1);
289 if ( m_xLbField1->get_active() == 0 )
290 {
291 m_xLbConnect2->set_sensitive(false);
292 m_xLbField2->set_sensitive(false);
293 m_xLbCond2->set_sensitive(false);
294 m_xEdVal2->set_sensitive(false);
295 m_xBtnRemove2->set_sensitive(false);
296 }
297 else if ( m_xLbConnect2->get_active() == -1 )
298 {
299 m_xLbField2->set_sensitive(false);
300 m_xLbCond2->set_sensitive(false);
301 m_xEdVal2->set_sensitive(false);
302 m_xBtnRemove2->set_sensitive(false);
303 }
304
305 if ( m_xLbField2->get_active() == 0 )
306 {
307 m_xLbConnect3->set_sensitive(false);
308 m_xLbField3->set_sensitive(false);
309 m_xLbCond3->set_sensitive(false);
310 m_xEdVal3->set_sensitive(false);
311 m_xBtnRemove3->set_sensitive(false);
312 }
313 else if ( m_xLbConnect3->get_active() == -1 )
314 {
315 m_xLbField3->set_sensitive(false);
316 m_xLbCond3->set_sensitive(false);
317 m_xEdVal3->set_sensitive(false);
318 m_xBtnRemove3->set_sensitive(false);
319 }
320 if ( m_xLbField3->get_active() == 0 )
321 {
322 m_xLbConnect4->set_sensitive(false);
323 m_xLbField4->set_sensitive(false);
324 m_xLbCond4->set_sensitive(false);
325 m_xEdVal4->set_sensitive(false);
326 m_xBtnRemove4->set_sensitive(false);
327 }
328 else if ( m_xLbConnect4->get_active() == -1 )
329 {
330 m_xLbField4->set_sensitive(false);
331 m_xLbCond4->set_sensitive(false);
332 m_xEdVal4->set_sensitive(false);
333 m_xBtnRemove4->set_sensitive(false);
334 }
335
336 m_xEdVal1->set_entry_width_chars(10);
337 m_xEdVal2->set_entry_width_chars(10);
338 m_xEdVal3->set_entry_width_chars(10);
339 m_xEdVal4->set_entry_width_chars(10);
340
341 if (pDoc != nullptr && pDoc->GetChangeTrack() != nullptr)
342 m_xBtnCopyResult->set_sensitive(false);
343 }
344
Close()345 void ScFilterDlg::Close()
346 {
347 if (pViewData)
348 pViewData->GetDocShell()->CancelAutoDBRange();
349
350 DoClose( ScFilterDlgWrapper::GetChildWindowId() );
351 }
352
353 // Mouse-selected cell area becomes the new selection and is shown in the
354 // reference text box
355
SetReference(const ScRange & rRef,ScDocument & rDocP)356 void ScFilterDlg::SetReference( const ScRange& rRef, ScDocument& rDocP )
357 {
358 if ( bRefInputMode ) // Only possible if in reference edit mode
359 {
360 if ( rRef.aStart != rRef.aEnd )
361 RefInputStart( m_xEdCopyArea.get() );
362 OUString aRefStr(rRef.aStart.Format(ScRefFlags::ADDR_ABS_3D, &rDocP, rDocP.GetAddressConvention()));
363 m_xEdCopyArea->SetRefString( aRefStr );
364 }
365 }
366
SetActive()367 void ScFilterDlg::SetActive()
368 {
369 if ( bRefInputMode )
370 {
371 m_xEdCopyArea->GrabFocus();
372 m_xEdCopyArea->GetModifyHdl().Call( *m_xEdCopyArea );
373 }
374 else
375 m_xDialog->grab_focus();
376
377 RefInputDone();
378 }
379
FillFieldLists()380 void ScFilterDlg::FillFieldLists()
381 {
382 m_xLbField1->freeze();
383 m_xLbField2->freeze();
384 m_xLbField3->freeze();
385 m_xLbField4->freeze();
386
387 m_xLbField1->clear();
388 m_xLbField2->clear();
389 m_xLbField3->clear();
390 m_xLbField4->clear();
391 m_xLbField1->append_text( aStrNone );
392 m_xLbField2->append_text( aStrNone );
393 m_xLbField3->append_text( aStrNone );
394 m_xLbField4->append_text( aStrNone );
395
396 if ( pDoc )
397 {
398 OUString aFieldName;
399 SCTAB nTab = nSrcTab;
400 SCCOL nFirstCol = theQueryData.nCol1;
401 SCROW nFirstRow = theQueryData.nRow1;
402 SCCOL nMaxCol = theQueryData.nCol2;
403 SCCOL col = 0;
404
405 for ( col=nFirstCol; col<=nMaxCol; col++ )
406 {
407 aFieldName = pDoc->GetString(col, nFirstRow, nTab);
408 if (!m_xBtnHeader->get_active() || aFieldName.isEmpty())
409 {
410 aFieldName = ScGlobal::ReplaceOrAppend( aStrColumn, u"%1", ScColToAlpha( col ));
411 }
412 m_xLbField1->append_text( aFieldName );
413 m_xLbField2->append_text( aFieldName );
414 m_xLbField3->append_text( aFieldName );
415 m_xLbField4->append_text( aFieldName );
416 }
417 }
418
419 m_xLbField4->thaw();
420 m_xLbField3->thaw();
421 m_xLbField2->thaw();
422 m_xLbField1->thaw();
423 }
424
UpdateValueList(size_t nList)425 void ScFilterDlg::UpdateValueList( size_t nList )
426 {
427 bool bCaseSens = m_xBtnCase->get_active();
428
429 if (pDoc && nList > 0 && nList <= QUERY_ENTRY_COUNT)
430 {
431 weld::ComboBox* pValList = maValueEdArr[nList-1];
432 const sal_Int32 nFieldSelPos = maFieldLbArr[nList-1]->get_active();
433 OUString aCurValue = pValList->get_active_text();
434
435 std::unique_ptr<weld::WaitObject> xWaiter;
436 std::vector<weld::ComboBoxEntry> aEntries;
437 aEntries.emplace_back(aStrNotEmpty);
438 aEntries.emplace_back(aStrEmpty);
439
440 if (nFieldSelPos)
441 {
442 xWaiter.reset(new weld::WaitObject(m_xDialog.get())); // even if only the list box has content
443 SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
444 EntryList* pList = nullptr;
445 if (!m_EntryLists.count(nColumn))
446 {
447 size_t nOffset = GetSliderPos();
448 SCTAB nTab = nSrcTab;
449 SCROW nFirstRow = theQueryData.nRow1;
450 SCROW nLastRow = theQueryData.nRow2;
451 if (maHasDates.size() < nOffset+nList)
452 maHasDates.resize(nOffset+nList, false);
453 maHasDates[nOffset+nList-1] = false;
454
455 // first without the first line
456 std::pair<EntryListsMap::iterator, bool> r =
457 m_EntryLists.insert(std::make_pair(nColumn, std::make_unique<EntryList>()));
458 if (!r.second)
459 // insertion failed.
460 return;
461
462 pList = r.first->second.get();
463 pDoc->GetFilterEntriesArea(
464 nColumn, nFirstRow+1, nLastRow,
465 nTab, bCaseSens, pList->maFilterEntries);
466 maHasDates[nOffset+nList-1] = pList->maFilterEntries.mbHasDates;
467
468 // Entry for the first line
469 //! Entry (pHdrEntry) doesn't generate collection?
470
471 pList->mnHeaderPos = INVALID_HEADER_POS;
472 ScFilterEntries aHdrColl;
473 pDoc->GetFilterEntriesArea(
474 nColumn, nFirstRow, nFirstRow, nTab, true, aHdrColl );
475 if (!aHdrColl.empty())
476 {
477 // See if the header value is already in the list.
478 std::vector<ScTypedStrData>::iterator itBeg = pList->maFilterEntries.begin(), itEnd = pList->maFilterEntries.end();
479 if (std::none_of(itBeg, itEnd, FindTypedStrData(aHdrColl.front(), bCaseSens)))
480 {
481 // Not in the list. Insert it.
482 pList->maFilterEntries.push_back(aHdrColl.front());
483 if (bCaseSens)
484 std::sort(pList->maFilterEntries.begin(), pList->maFilterEntries.end(), ScTypedStrData::LessCaseSensitive());
485 else
486 std::sort(pList->maFilterEntries.begin(), pList->maFilterEntries.end(), ScTypedStrData::LessCaseInsensitive());
487
488 // Record its position.
489 itBeg = pList->maFilterEntries.begin();
490 itEnd = pList->maFilterEntries.end();
491 auto it = std::find_if(itBeg, itEnd, FindTypedStrData(aHdrColl.front(), bCaseSens));
492 pList->mnHeaderPos = std::distance(itBeg, it);
493 }
494 }
495 }
496 else
497 pList = m_EntryLists[nColumn].get();
498
499 assert(pList);
500
501 for (const auto& rEntry : pList->maFilterEntries)
502 aEntries.emplace_back(rEntry.GetString());
503 }
504 pValList->insert_vector(aEntries, false);
505 pValList->set_entry_text(aCurValue);
506 }
507
508 UpdateHdrInValueList( nList );
509 }
510
UpdateHdrInValueList(size_t nList)511 void ScFilterDlg::UpdateHdrInValueList( size_t nList )
512 {
513 //! GetText / SetText ??
514
515 if (!pDoc)
516 return;
517
518 if (nList == 0 || nList > QUERY_ENTRY_COUNT)
519 return;
520
521 size_t nFieldSelPos = maFieldLbArr[nList-1]->get_active();
522 if (!nFieldSelPos)
523 return;
524
525 SCCOL nColumn = theQueryData.nCol1 + static_cast<SCCOL>(nFieldSelPos) - 1;
526 if (!m_EntryLists.count(nColumn))
527 {
528 OSL_FAIL("column not yet initialized");
529 return;
530 }
531
532 size_t const nPos = m_EntryLists[nColumn]->mnHeaderPos;
533 if (nPos == INVALID_HEADER_POS)
534 return;
535
536 weld::ComboBox* pValList = maValueEdArr[nList-1];
537 int nListPos = nPos + 2; // for "empty" and "non-empty"
538
539 const ScTypedStrData& rHdrEntry = m_EntryLists[nColumn]->maFilterEntries.maStrData[nPos];
540
541 const OUString& aHdrStr = rHdrEntry.GetString();
542 bool bWasThere = nListPos < pValList->get_count() && aHdrStr == pValList->get_text(nListPos);
543 bool bInclude = !m_xBtnHeader->get_active();
544
545 if (bInclude) // Include entry
546 {
547 if (!bWasThere)
548 pValList->insert_text(nListPos, aHdrStr);
549 }
550 else // Omit entry
551 {
552 if (bWasThere)
553 pValList->remove(nListPos);
554 }
555 }
556
ClearValueList(size_t nList)557 void ScFilterDlg::ClearValueList( size_t nList )
558 {
559 if (nList > 0 && nList <= QUERY_ENTRY_COUNT)
560 {
561 weld::ComboBox* pValList = maValueEdArr[nList-1];
562 pValList->clear();
563 pValList->append_text( aStrNotEmpty );
564 pValList->append_text( aStrEmpty );
565 pValList->set_entry_text( EMPTY_OUSTRING );
566 }
567 }
568
GetFieldSelPos(SCCOL nField)569 size_t ScFilterDlg::GetFieldSelPos( SCCOL nField )
570 {
571 if ( nField >= theQueryData.nCol1 && nField <= theQueryData.nCol2 )
572 return static_cast<size_t>(nField - theQueryData.nCol1 + 1);
573 else
574 return 0;
575 }
576
GetOutputItem()577 ScQueryItem* ScFilterDlg::GetOutputItem()
578 {
579 ScAddress theCopyPos;
580 ScQueryParam theParam( theQueryData );
581 bool bCopyPosOk = false;
582
583 if ( m_xBtnCopyResult->get_active() )
584 {
585 ScRefFlags nResult = theCopyPos.Parse(
586 m_xEdCopyArea->GetText(), *pDoc, pDoc->GetAddressConvention());
587 bCopyPosOk = (nResult & ScRefFlags::VALID) == ScRefFlags::VALID;
588 }
589
590 if ( m_xBtnCopyResult->get_active() && bCopyPosOk )
591 {
592 theParam.bInplace = false;
593 theParam.nDestTab = theCopyPos.Tab();
594 theParam.nDestCol = theCopyPos.Col();
595 theParam.nDestRow = theCopyPos.Row();
596 }
597 else
598 {
599 theParam.bInplace = true;
600 theParam.nDestTab = 0;
601 theParam.nDestCol = 0;
602 theParam.nDestRow = 0;
603 }
604
605 theParam.bHasHeader = m_xBtnHeader->get_active();
606 theParam.bByRow = true;
607 theParam.bDuplicate = !m_xBtnUnique->get_active();
608 theParam.bCaseSens = m_xBtnCase->get_active();
609 theParam.eSearchType = m_xBtnRegExp->get_active() ? utl::SearchParam::SearchType::Regexp : utl::SearchParam::SearchType::Normal;
610 theParam.bDestPers = m_xBtnDestPers->get_active();
611
612 // only set the three - reset everything else
613
614 pOutItem.reset( new ScQueryItem( nWhichQuery, &theParam ) );
615
616 return pOutItem.get();
617 }
618
IsRefInputMode() const619 bool ScFilterDlg::IsRefInputMode() const
620 {
621 return bRefInputMode;
622 }
623
624 // Handler:
625
IMPL_LINK(ScFilterDlg,BtnClearHdl,weld::Button &,rBtn,void)626 IMPL_LINK( ScFilterDlg, BtnClearHdl, weld::Button&, rBtn, void )
627 {
628 if ( &rBtn != m_xBtnClear.get() )
629 return;
630
631 // scroll to the top
632 m_xScrollBar->vadjustment_set_value(0);
633 size_t nOffset = 0;
634 RefreshEditRow( nOffset);
635
636 // clear all conditions
637 m_xLbConnect1->set_active(-1);
638 m_xLbConnect2->set_active(-1);
639 m_xLbConnect3->set_active(-1);
640 m_xLbConnect4->set_active(-1);
641 m_xLbField1->set_active(0);
642 m_xLbField2->set_active(0);
643 m_xLbField3->set_active(0);
644 m_xLbField4->set_active(0);
645 m_xLbCond1->set_active(0);
646 m_xLbCond2->set_active(0);
647 m_xLbCond3->set_active(0);
648 m_xLbCond4->set_active(0);
649 ClearValueList( 1 );
650 ClearValueList( 2 );
651 ClearValueList( 3 );
652 ClearValueList( 4 );
653
654 // disable fields for second row onward
655 m_xLbConnect2->set_sensitive(false);
656 m_xLbConnect3->set_sensitive(false);
657 m_xLbConnect4->set_sensitive(false);
658 m_xLbField2->set_sensitive(false);
659 m_xLbField3->set_sensitive(false);
660 m_xLbField4->set_sensitive(false);
661 m_xLbCond2->set_sensitive(false);
662 m_xLbCond3->set_sensitive(false);
663 m_xLbCond4->set_sensitive(false);
664 m_xEdVal2->set_sensitive(false);
665 m_xEdVal3->set_sensitive(false);
666 m_xEdVal4->set_sensitive(false);
667 m_xBtnRemove2->set_sensitive(false);
668 m_xBtnRemove3->set_sensitive(false);
669 m_xBtnRemove4->set_sensitive(false);
670
671 // clear query data objects
672 SCSIZE nCount = theQueryData.GetEntryCount();
673 if (maRefreshExceptQuery.size() < nCount + 1)
674 maRefreshExceptQuery.resize(nCount + 1, false);
675 for (SCSIZE i = 0; i < nCount; ++i)
676 {
677 theQueryData.GetEntry(i).bDoQuery = false;
678 maRefreshExceptQuery[i] = false;
679 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
680 }
681 maRefreshExceptQuery[0] = true;
682 }
683
IMPL_LINK(ScFilterDlg,EndDlgHdl,weld::Button &,rBtn,void)684 IMPL_LINK( ScFilterDlg, EndDlgHdl, weld::Button&, rBtn, void )
685 {
686 if ( &rBtn == m_xBtnOk.get() )
687 {
688 bool bAreaInputOk = true;
689
690 if ( m_xBtnCopyResult->get_active() )
691 {
692 if ( !pOptionsMgr->VerifyPosStr( m_xEdCopyArea->GetText() ) )
693 {
694 if (!m_xExpander->get_expanded())
695 m_xExpander->set_expanded(true);
696
697 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
698 VclMessageType::Warning, VclButtonsType::Ok,
699 ScResId(STR_INVALID_TABREF)));
700 xBox->run();
701 m_xEdCopyArea->GrabFocus();
702 bAreaInputOk = false;
703 }
704 }
705
706 if ( bAreaInputOk )
707 {
708 SetDispatcherLock( false );
709 SwitchToDocument();
710 GetBindings().GetDispatcher()->ExecuteList(FID_FILTER_OK,
711 SfxCallMode::SLOT | SfxCallMode::RECORD,
712 { GetOutputItem() });
713 response(RET_OK);
714 }
715 }
716 else if ( &rBtn == m_xBtnCancel.get() )
717 {
718 response(RET_CANCEL);
719 }
720 }
721
IMPL_LINK_NOARG(ScFilterDlg,MoreExpandedHdl,weld::Expander &,void)722 IMPL_LINK_NOARG(ScFilterDlg, MoreExpandedHdl, weld::Expander&, void)
723 {
724 if ( m_xExpander->get_expanded() )
725 pTimer->Start();
726 else
727 {
728 pTimer->Stop();
729 bRefInputMode = false;
730 //@BugID 54702 Enable/disable only in Basic class
731 //SFX_APPWINDOW->Disable(FALSE); //! general method in ScAnyRefDlg
732 }
733 }
734
IMPL_LINK(ScFilterDlg,TimeOutHdl,Timer *,_pTimer,void)735 IMPL_LINK( ScFilterDlg, TimeOutHdl, Timer*, _pTimer, void )
736 {
737 // Check if RefInputMode is still true every 50ms
738 if (_pTimer == pTimer.get() && m_xDialog->has_toplevel_focus())
739 bRefInputMode = (m_xEdCopyArea->GetWidget()->has_focus() || m_xRbCopyArea->GetWidget()->has_focus());
740
741 if ( m_xExpander->get_expanded() )
742 pTimer->Start();
743 }
744
IMPL_LINK(ScFilterDlg,LbSelectHdl,weld::ComboBox &,rLb,void)745 IMPL_LINK(ScFilterDlg, LbSelectHdl, weld::ComboBox&, rLb, void)
746 {
747 /*
748 * Handle enable/disable logic depending on which ListBox was selected
749 */
750 sal_uInt16 nOffset = GetSliderPos();
751
752 if ( &rLb == m_xLbConnect1.get() )
753 {
754 m_xLbField1->set_sensitive(true);
755 m_xLbCond1->set_sensitive(true);
756 m_xEdVal1->set_sensitive(true);
757 m_xBtnRemove1->set_sensitive(true);
758
759 const sal_Int32 nConnect1 = m_xLbConnect1->get_active();
760 size_t nQE = nOffset;
761 theQueryData.GetEntry(nQE).eConnect =static_cast<ScQueryConnect>(nConnect1);
762 if (maRefreshExceptQuery.size() < nQE + 1)
763 maRefreshExceptQuery.resize(nQE + 1, false);
764 maRefreshExceptQuery[nQE] = true;
765 }
766 else if ( &rLb == m_xLbConnect2.get() )
767 {
768 m_xLbField2->set_sensitive(true);
769 m_xLbCond2->set_sensitive(true);
770 m_xEdVal2->set_sensitive(true);
771 m_xBtnRemove2->set_sensitive(true);
772
773 const sal_Int32 nConnect2 = m_xLbConnect2->get_active();
774 size_t nQE = 1+nOffset;
775 theQueryData.GetEntry(nQE).eConnect =static_cast<ScQueryConnect>(nConnect2);
776 if (maRefreshExceptQuery.size() < nQE + 1)
777 maRefreshExceptQuery.resize(nQE + 1, false);
778 maRefreshExceptQuery[nQE]=true;
779 }
780 else if ( &rLb == m_xLbConnect3.get() )
781 {
782 m_xLbField3->set_sensitive(true);
783 m_xLbCond3->set_sensitive(true);
784 m_xEdVal3->set_sensitive(true);
785 m_xBtnRemove3->set_sensitive(true);
786
787 const sal_Int32 nConnect3 = m_xLbConnect3->get_active();
788 size_t nQE = 2 + nOffset;
789 theQueryData.GetEntry(nQE).eConnect = static_cast<ScQueryConnect>(nConnect3);
790 if (maRefreshExceptQuery.size() < nQE + 1)
791 maRefreshExceptQuery.resize(nQE + 1, false);
792 maRefreshExceptQuery[nQE] = true;
793
794 }
795 else if ( &rLb == m_xLbConnect4.get() )
796 {
797 m_xLbField4->set_sensitive(true);
798 m_xLbCond4->set_sensitive(true);
799 m_xEdVal4->set_sensitive(true);
800 m_xBtnRemove4->set_sensitive(true);
801
802 const sal_Int32 nConnect4 = m_xLbConnect4->get_active();
803 size_t nQE = 3 + nOffset;
804 theQueryData.GetEntry(nQE).eConnect = static_cast<ScQueryConnect>(nConnect4);
805 if (maRefreshExceptQuery.size() < nQE + 1)
806 maRefreshExceptQuery.resize(nQE + 1, false);
807 maRefreshExceptQuery[nQE] = true;
808 }
809 else if ( &rLb == m_xLbField1.get() )
810 {
811 if ( m_xLbField1->get_active() == 0 )
812 {
813 m_xLbConnect2->set_active(-1);
814 m_xLbConnect3->set_active(-1);
815 m_xLbConnect4->set_active(-1);
816 m_xLbField2->set_active( 0 );
817 m_xLbField3->set_active( 0 );
818 m_xLbField4->set_active( 0 );
819 m_xLbCond2->set_active( 0 );
820 m_xLbCond3->set_active( 0 );
821 m_xLbCond4->set_active( 0 );
822 ClearValueList( 1 );
823 ClearValueList( 2 );
824 ClearValueList( 3 );
825 ClearValueList( 4 );
826
827 m_xLbConnect2->set_sensitive(false);
828 m_xLbConnect3->set_sensitive(false);
829 m_xLbConnect4->set_sensitive(false);
830 m_xLbField2->set_sensitive(false);
831 m_xLbField3->set_sensitive(false);
832 m_xLbField4->set_sensitive(false);
833 m_xLbCond2->set_sensitive(false);
834 m_xLbCond3->set_sensitive(false);
835 m_xLbCond4->set_sensitive(false);
836 m_xEdVal2->set_sensitive(false);
837 m_xEdVal3->set_sensitive(false);
838 m_xEdVal4->set_sensitive(false);
839 m_xBtnRemove2->set_sensitive(false);
840 m_xBtnRemove3->set_sensitive(false);
841 m_xBtnRemove4->set_sensitive(false);
842 SCSIZE nCount = theQueryData.GetEntryCount();
843 if (maRefreshExceptQuery.size() < nCount + 1)
844 maRefreshExceptQuery.resize(nCount + 1, false);
845 for (SCSIZE i = nOffset; i < nCount; ++i)
846 {
847 theQueryData.GetEntry(i).bDoQuery = false;
848 maRefreshExceptQuery[i] = false;
849 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
850 }
851 maRefreshExceptQuery[nOffset] = true;
852 }
853 else
854 {
855 UpdateValueList( 1 );
856 if ( !m_xLbConnect2->get_sensitive() )
857 {
858 m_xLbConnect2->set_sensitive(true);
859 }
860 theQueryData.GetEntry(nOffset).bDoQuery = true;
861 const sal_Int32 nField = rLb.get_active();
862 theQueryData.GetEntry(nOffset).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
863 }
864 }
865 else if ( &rLb == m_xLbField2.get() )
866 {
867 if ( m_xLbField2->get_active() == 0 )
868 {
869 m_xLbConnect3->set_active(-1);
870 m_xLbConnect4->set_active(-1);
871 m_xLbField3->set_active( 0 );
872 m_xLbField4->set_active( 0 );
873 m_xLbCond3->set_active( 0 );
874 m_xLbCond4->set_active( 0 );
875 ClearValueList( 2 );
876 ClearValueList( 3 );
877 ClearValueList( 4 );
878
879 m_xLbConnect3->set_sensitive(false);
880 m_xLbConnect4->set_sensitive(false);
881 m_xLbField3->set_sensitive(false);
882 m_xLbField4->set_sensitive(false);
883 m_xLbCond3->set_sensitive(false);
884 m_xLbCond4->set_sensitive(false);
885 m_xEdVal3->set_sensitive(false);
886 m_xEdVal4->set_sensitive(false);
887 m_xBtnRemove3->set_sensitive(false);
888 m_xBtnRemove4->set_sensitive(false);
889
890 sal_uInt16 nTemp=nOffset+1;
891 SCSIZE nCount = theQueryData.GetEntryCount();
892 if (maRefreshExceptQuery.size() < nCount)
893 maRefreshExceptQuery.resize(nCount, false);
894 for (SCSIZE i= nTemp; i< nCount; i++)
895 {
896 theQueryData.GetEntry(i).bDoQuery = false;
897 maRefreshExceptQuery[i] = false;
898 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
899 }
900 maRefreshExceptQuery[nTemp] = true;
901 }
902 else
903 {
904 UpdateValueList( 2 );
905 if ( !m_xLbConnect3->get_sensitive() )
906 {
907 m_xLbConnect3->set_sensitive(true);
908 }
909 const sal_Int32 nField = rLb.get_active();
910 sal_uInt16 nQ=1+nOffset;
911 theQueryData.GetEntry(nQ).bDoQuery = true;
912 theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
913 }
914 }
915 else if ( &rLb == m_xLbField3.get() )
916 {
917 if ( m_xLbField3->get_active() == 0 )
918 {
919 m_xLbConnect4->set_active(-1);
920 m_xLbField4->set_active( 0 );
921 m_xLbCond4->set_active( 0 );
922 ClearValueList( 3 );
923 ClearValueList( 4 );
924
925 m_xLbConnect4->set_sensitive(false);
926 m_xLbField4->set_sensitive(false);
927 m_xLbCond4->set_sensitive(false);
928 m_xEdVal4->set_sensitive(false);
929 m_xBtnRemove4->set_sensitive(false);
930
931 sal_uInt16 nTemp=nOffset+2;
932 SCSIZE nCount = theQueryData.GetEntryCount();
933 if (maRefreshExceptQuery.size() < nCount)
934 maRefreshExceptQuery.resize(nCount, false);
935 for (SCSIZE i = nTemp; i < nCount; ++i)
936 {
937 theQueryData.GetEntry(i).bDoQuery = false;
938 maRefreshExceptQuery[i] = false;
939 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
940 }
941 maRefreshExceptQuery[nTemp] = true;
942 }
943 else
944 {
945 UpdateValueList( 3 );
946 if ( !m_xLbConnect4->get_sensitive() )
947 {
948 m_xLbConnect4->set_sensitive(true);
949 }
950
951 const sal_Int32 nField = rLb.get_active();
952 sal_uInt16 nQ=2+nOffset;
953 theQueryData.GetEntry(nQ).bDoQuery = true;
954 theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
955
956 }
957 }
958 else if ( &rLb == m_xLbField4.get() )
959 {
960 if ( m_xLbField4->get_active() == 0 )
961 {
962 ClearValueList( 4 );
963 sal_uInt16 nTemp=nOffset+3;
964 SCSIZE nCount = theQueryData.GetEntryCount();
965 if (maRefreshExceptQuery.size() < nCount)
966 maRefreshExceptQuery.resize(nCount, false);
967 for (SCSIZE i = nTemp; i < nCount; ++i)
968 {
969 theQueryData.GetEntry(i).bDoQuery = false;
970 maRefreshExceptQuery[i] = false;
971 theQueryData.GetEntry(i).nField = static_cast<SCCOL>(0);
972 }
973 maRefreshExceptQuery[nTemp] = true;
974 }
975 else
976 {
977 UpdateValueList( 4 );
978 const sal_Int32 nField = rLb.get_active();
979 sal_uInt16 nQ=3+nOffset;
980 theQueryData.GetEntry(nQ).bDoQuery = true;
981 theQueryData.GetEntry(nQ).nField = theQueryData.nCol1 + static_cast<SCCOL>(nField) - 1 ;
982 }
983
984 }
985 else if ( &rLb == m_xLbCond1.get())
986 {
987 theQueryData.GetEntry(nOffset).eOp=static_cast<ScQueryOp>(rLb.get_active());
988 }
989 else if ( &rLb == m_xLbCond2.get())
990 {
991 sal_uInt16 nQ=1+nOffset;
992 theQueryData.GetEntry(nQ).eOp=static_cast<ScQueryOp>(rLb.get_active());
993 }
994 else if ( &rLb == m_xLbCond3.get())
995 {
996 sal_uInt16 nQ=2+nOffset;
997 theQueryData.GetEntry(nQ).eOp=static_cast<ScQueryOp>(rLb.get_active());
998 }
999 else
1000 {
1001 sal_uInt16 nQ=3+nOffset;
1002 theQueryData.GetEntry(nQ).eOp=static_cast<ScQueryOp>(rLb.get_active());
1003 }
1004 }
1005
IMPL_LINK(ScFilterDlg,CheckBoxHdl,weld::Toggleable &,rBox,void)1006 IMPL_LINK( ScFilterDlg, CheckBoxHdl, weld::Toggleable&, rBox, void )
1007 {
1008 // Column headers:
1009 // Field list: Columnxx <-> column header string
1010 // Value list: Column header value not applicable.
1011 // Upper/lower case:
1012 // Value list: completely new
1013
1014 if ( &rBox == m_xBtnHeader.get() ) // Field list and value list
1015 {
1016 const sal_Int32 nCurSel1 = m_xLbField1->get_active();
1017 const sal_Int32 nCurSel2 = m_xLbField2->get_active();
1018 const sal_Int32 nCurSel3 = m_xLbField3->get_active();
1019 const sal_Int32 nCurSel4 = m_xLbField4->get_active();
1020 FillFieldLists();
1021 m_xLbField1->set_active( nCurSel1 );
1022 m_xLbField2->set_active( nCurSel2 );
1023 m_xLbField3->set_active( nCurSel3 );
1024 m_xLbField4->set_active( nCurSel4 );
1025
1026 UpdateHdrInValueList( 1 );
1027 UpdateHdrInValueList( 2 );
1028 UpdateHdrInValueList( 3 );
1029 UpdateHdrInValueList( 4 );
1030 }
1031
1032 if ( &rBox == m_xBtnCase.get() ) // Complete value list
1033 {
1034 m_EntryLists.clear();
1035 UpdateValueList( 1 ); // current text is recorded
1036 UpdateValueList( 2 );
1037 UpdateValueList( 3 );
1038 UpdateValueList( 4 );
1039 }
1040 }
1041
IMPL_LINK(ScFilterDlg,ValModifyHdl,weld::ComboBox &,rEd,void)1042 IMPL_LINK( ScFilterDlg, ValModifyHdl, weld::ComboBox&, rEd, void )
1043 {
1044 size_t nOffset = GetSliderPos();
1045 size_t i = 0;
1046 size_t nQE = i + nOffset;
1047 OUString aStrVal = rEd.get_active_text();
1048 weld::ComboBox* pLbCond = m_xLbCond1.get();
1049 weld::ComboBox* pLbField = m_xLbField1.get();
1050 if ( &rEd == m_xEdVal2.get() )
1051 {
1052 pLbCond = m_xLbCond2.get();
1053 pLbField = m_xLbField2.get();
1054 i=1;
1055 nQE=i+nOffset;
1056 }
1057 if ( &rEd == m_xEdVal3.get() )
1058 {
1059 pLbCond = m_xLbCond3.get();
1060 pLbField = m_xLbField3.get();
1061 i=2;
1062 nQE=i+nOffset;
1063 }
1064 if ( &rEd == m_xEdVal4.get() )
1065 {
1066 pLbCond = m_xLbCond4.get();
1067 pLbField = m_xLbField4.get();
1068 i=3;
1069 nQE=i+nOffset;
1070 }
1071
1072 if ( aStrEmpty == aStrVal || aStrNotEmpty == aStrVal )
1073 {
1074 pLbCond->set_active_text(OUString('='));
1075 pLbCond->set_sensitive(false);
1076 }
1077 else
1078 pLbCond->set_sensitive(true);
1079
1080 if (maHasDates.size() < nQE + 1)
1081 maHasDates.resize(nQE + 1, false);
1082 if (maRefreshExceptQuery.size() < nQE + 1)
1083 maRefreshExceptQuery.resize(nQE + 1, false);
1084
1085 ScQueryEntry& rEntry = theQueryData.GetEntry( nQE );
1086 ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
1087 bool bDoThis = (pLbField->get_active() != 0);
1088 rEntry.bDoQuery = bDoThis;
1089
1090 if ( !(rEntry.bDoQuery || maRefreshExceptQuery[nQE]) )
1091 return;
1092
1093 bool bByEmptyOrNotByEmpty = false;
1094 if ( aStrEmpty == aStrVal )
1095 {
1096 bByEmptyOrNotByEmpty = true;
1097 rEntry.SetQueryByEmpty();
1098 }
1099 else if ( aStrNotEmpty == aStrVal )
1100 {
1101 bByEmptyOrNotByEmpty = true;
1102 rEntry.SetQueryByNonEmpty();
1103 }
1104 else
1105 {
1106 rItem.maString = pDoc->GetSharedStringPool().intern(aStrVal);
1107 rItem.mfVal = 0.0;
1108 rItem.meType = ScQueryEntry::ByString;
1109 }
1110
1111 const sal_Int32 nField = pLbField->get_active();
1112 rEntry.nField = nField ? (theQueryData.nCol1 +
1113 static_cast<SCCOL>(nField) - 1) : static_cast<SCCOL>(0);
1114
1115 ScQueryOp eOp = static_cast<ScQueryOp>(pLbCond->get_active());
1116 rEntry.eOp = eOp;
1117 if (maHasDates[nQE] && !bByEmptyOrNotByEmpty)
1118 rItem.meType = ScQueryEntry::ByDate;
1119 }
1120
IMPL_LINK(ScFilterDlg,BtnRemoveHdl,weld::Button &,rBtn,void)1121 IMPL_LINK( ScFilterDlg, BtnRemoveHdl, weld::Button&, rBtn, void )
1122 {
1123 // Calculate the row to delete
1124 sal_uInt16 nOffset = GetSliderPos();
1125 int nButtonIndex = 0;
1126 if ( &rBtn == m_xBtnRemove2.get() )
1127 nButtonIndex = 1;
1128 if ( &rBtn == m_xBtnRemove3.get() )
1129 nButtonIndex = 2;
1130 if ( &rBtn == m_xBtnRemove4.get() )
1131 nButtonIndex = 3;
1132 SCSIZE nRowToDelete = nOffset + nButtonIndex;
1133
1134 // Check that the index is sensible
1135 SCSIZE nCount = theQueryData.GetEntryCount();
1136 if (nRowToDelete >= nCount)
1137 {
1138 SAL_WARN( "sc", "ScFilterDlg::BtnRemoveHdl: could not delete row - invalid index.");
1139 return;
1140 }
1141
1142 // Resize maRefreshExceptQuery
1143 if (maRefreshExceptQuery.size() < nCount + 1)
1144 maRefreshExceptQuery.resize(nCount + 1, false);
1145
1146 // Move all the subsequent rows back one position;
1147 // also find the last row, which we will delete
1148 SCSIZE nRowToClear = nCount-1;
1149 for (SCSIZE i = nRowToDelete; i < nCount-1; ++i)
1150 {
1151 if (theQueryData.GetEntry(i+1).bDoQuery)
1152 {
1153 theQueryData.GetEntry(i) = theQueryData.GetEntry(i+1);
1154 }
1155 else
1156 {
1157 nRowToClear = i;
1158 break;
1159 }
1160 }
1161
1162 // If the next row is being edited, but not confirmed, move it back
1163 // one position
1164 if (nRowToClear < nCount-1 && maRefreshExceptQuery[nRowToClear+1])
1165 {
1166 theQueryData.GetEntry(nRowToClear) = theQueryData.GetEntry(nRowToClear+1);
1167 maRefreshExceptQuery[nRowToClear] = true;
1168 maRefreshExceptQuery[nRowToClear+1] = false;
1169 }
1170 else
1171 {
1172 // Remove the very last one, since everything has moved back
1173 theQueryData.GetEntry(nRowToClear).bDoQuery = false;
1174 theQueryData.GetEntry(nRowToClear).nField = static_cast<SCCOL>(0);
1175 maRefreshExceptQuery[nRowToClear] = false;
1176 }
1177
1178 // Always enable the very first row
1179 if (!theQueryData.GetEntry(0).bDoQuery)
1180 {
1181 maRefreshExceptQuery[0] = true;
1182 }
1183
1184 // Refresh the UI
1185 RefreshEditRow( nOffset );
1186
1187 // Special handling if the very first row was cleared
1188 if (!theQueryData.GetEntry(0).bDoQuery)
1189 {
1190 m_xLbConnect1->set_active(-1);
1191 m_xLbField1->set_active(0);
1192 m_xLbField1->set_sensitive(true);
1193 m_xLbCond1->set_active(0);
1194 m_xLbCond1->set_sensitive(true);
1195 ClearValueList(1);
1196 }
1197 }
1198
IMPL_LINK_NOARG(ScFilterDlg,ScrollHdl,weld::ScrolledWindow &,void)1199 IMPL_LINK_NOARG(ScFilterDlg, ScrollHdl, weld::ScrolledWindow&, void)
1200 {
1201 SliderMoved();
1202 }
1203
SliderMoved()1204 void ScFilterDlg::SliderMoved()
1205 {
1206 size_t nOffset = GetSliderPos();
1207 RefreshEditRow( nOffset);
1208 }
1209
GetSliderPos() const1210 size_t ScFilterDlg::GetSliderPos() const
1211 {
1212 return static_cast<size_t>(m_xScrollBar->vadjustment_get_value());
1213 }
1214
RefreshEditRow(size_t nOffset)1215 void ScFilterDlg::RefreshEditRow( size_t nOffset )
1216 {
1217 if (nOffset==0)
1218 maConnLbArr[0]->hide();
1219 else
1220 maConnLbArr[0]->show();
1221
1222 for (size_t i = 0; i < QUERY_ENTRY_COUNT; ++i)
1223 {
1224 OUString aValStr;
1225 size_t nCondPos = 0;
1226 size_t nFieldSelPos = 0;
1227 size_t nQE = i + nOffset;
1228
1229 if (maRefreshExceptQuery.size() < nQE + 1)
1230 maRefreshExceptQuery.resize(nQE + 1, false);
1231
1232 ScQueryEntry& rEntry = theQueryData.GetEntry( nQE);
1233 if ( rEntry.bDoQuery || maRefreshExceptQuery[nQE] )
1234 {
1235 nCondPos = static_cast<size_t>(rEntry.eOp);
1236 if(rEntry.bDoQuery)
1237 nFieldSelPos = GetFieldSelPos( static_cast<SCCOL>(rEntry.nField) );
1238
1239 const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
1240 OUString aQueryStr = rItem.maString.getString();
1241 if (rEntry.IsQueryByEmpty())
1242 {
1243 aValStr = aStrEmpty;
1244 maCondLbArr[i]->set_sensitive(false);
1245 }
1246 else if (rEntry.IsQueryByNonEmpty())
1247 {
1248 aValStr = aStrNotEmpty;
1249 maCondLbArr[i]->set_sensitive(false);
1250 }
1251 else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor())
1252 {
1253 continue;
1254 }
1255 else
1256 {
1257 SetValString(aQueryStr, rItem, aValStr);
1258 maCondLbArr[i]->set_sensitive(true);
1259 }
1260 maFieldLbArr[i]->set_sensitive(true);
1261 maValueEdArr[i]->set_sensitive(true);
1262 maRemoveBtnArr[i]->set_sensitive(true);
1263
1264 if (nOffset==0)
1265 {
1266 if (i<3)
1267 {
1268 if(rEntry.bDoQuery)
1269 maConnLbArr[i+1]->set_sensitive(true);
1270 else
1271 maConnLbArr[i+1]->set_sensitive(false);
1272 size_t nQENext = nQE + 1;
1273 if (maRefreshExceptQuery.size() < nQENext + 1)
1274 maRefreshExceptQuery.resize(nQENext + 1, false);
1275 if (theQueryData.GetEntry(nQENext).bDoQuery || maRefreshExceptQuery[nQENext])
1276 maConnLbArr[i+1]->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(nQENext).eConnect) );
1277 else
1278 maConnLbArr[i+1]->set_active(-1);
1279 }
1280 }
1281 else
1282 {
1283 if(theQueryData.GetEntry( nQE-1).bDoQuery)
1284 maConnLbArr[i]->set_sensitive(true);
1285 else
1286 maConnLbArr[i]->set_sensitive(false);
1287
1288 if (maRefreshExceptQuery.size() < nQE + 1)
1289 maRefreshExceptQuery.resize(nQE + 1, false);
1290 if(rEntry.bDoQuery || maRefreshExceptQuery[nQE])
1291 maConnLbArr[i]->set_active( static_cast<sal_uInt16>(rEntry.eConnect) );
1292 else
1293 maConnLbArr[i]->set_active(-1);
1294 }
1295
1296 }
1297 else
1298 {
1299 if (nOffset==0)
1300 {
1301 if(i<3)
1302 {
1303 maConnLbArr[i+1]->set_active(-1);
1304 maConnLbArr[i+1]->set_sensitive(false);
1305 }
1306 }
1307 else
1308 {
1309 if(theQueryData.GetEntry( nQE-1).bDoQuery)
1310 maConnLbArr[i]->set_sensitive(true);
1311 else
1312 maConnLbArr[i]->set_sensitive(false);
1313 maConnLbArr[i]->set_active(-1);
1314 }
1315 maFieldLbArr[i]->set_sensitive(false);
1316 maCondLbArr[i]->set_sensitive(false);
1317 maValueEdArr[i]->set_sensitive(false);
1318 maRemoveBtnArr[i]->set_sensitive(false);
1319 }
1320 maFieldLbArr[i]->set_active( nFieldSelPos );
1321 maCondLbArr [i]->set_active( nCondPos );
1322 maValueEdArr[i]->set_entry_text( aValStr );
1323 UpdateValueList(i+1);
1324 }
1325 }
1326
SetValString(const OUString & rQueryStr,const ScQueryEntry::Item & rItem,OUString & rValStr)1327 void ScFilterDlg::SetValString( const OUString& rQueryStr, const ScQueryEntry::Item& rItem,
1328 OUString& rValStr )
1329 {
1330 if (rQueryStr.isEmpty())
1331 {
1332 pDoc = pViewData ? &pViewData->GetDocument() : nullptr;
1333 if (rItem.meType == ScQueryEntry::ByValue)
1334 {
1335 if (pDoc)
1336 {
1337 pDoc->GetFormatTable()->GetInputLineString(rItem.mfVal, 0, rValStr);
1338 }
1339 }
1340 else if (rItem.meType == ScQueryEntry::ByDate)
1341 {
1342 if (pDoc)
1343 {
1344 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1345 pFormatter->GetInputLineString(rItem.mfVal,
1346 pFormatter->GetStandardFormat( SvNumFormatType::DATE), rValStr);
1347 }
1348 }
1349 else
1350 {
1351 SAL_WARN( "sc", "ScFilterDlg::SetValString: empty query string, really?");
1352 rValStr = rQueryStr;
1353 }
1354 }
1355 else
1356 {
1357 // XXX NOTE: if not ByString we just assume this has been
1358 // set to a proper string corresponding to the numeric
1359 // value earlier!
1360 rValStr = rQueryStr;
1361 }
1362 }
1363
1364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1365