LibreOffice Module sc (master)  1
filtdlg.cxx
Go to the documentation of this file.
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 
47  mnHeaderPos(INVALID_HEADER_POS) {}
48 
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 
115 {
116  pOptionsMgr.reset();
117  pOutItem.reset();
118 
119  // Hack: RefInput control
120  pTimer->Stop();
121  pTimer.reset();
122 }
123 
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:
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());
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());
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());
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());
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 
346 {
347  if (pViewData)
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 
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 
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 
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 
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();
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
470 
472  ScFilterEntries aHdrColl;
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)
485  else
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 
512 {
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 
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 
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 
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();
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 
620 {
621  return bRefInputMode;
622 }
623 
624 // Handler:
625 
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 
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 
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 
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 
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 
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 
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;
1109  rItem.mbFormattedValue = true;
1110  }
1111 
1112  const sal_Int32 nField = pLbField->get_active();
1113  rEntry.nField = nField ? (theQueryData.nCol1 +
1114  static_cast<SCCOL>(nField) - 1) : static_cast<SCCOL>(0);
1115 
1116  ScQueryOp eOp = static_cast<ScQueryOp>(pLbCond->get_active());
1117  rEntry.eOp = eOp;
1118  if (maHasDates[nQE] && !bByEmptyOrNotByEmpty)
1119  rItem.meType = ScQueryEntry::ByDate;
1120 }
1121 
1122 IMPL_LINK( ScFilterDlg, BtnRemoveHdl, weld::Button&, rBtn, void )
1123 {
1124  // Calculate the row to delete
1125  sal_uInt16 nOffset = GetSliderPos();
1126  int nButtonIndex = 0;
1127  if ( &rBtn == m_xBtnRemove2.get() )
1128  nButtonIndex = 1;
1129  if ( &rBtn == m_xBtnRemove3.get() )
1130  nButtonIndex = 2;
1131  if ( &rBtn == m_xBtnRemove4.get() )
1132  nButtonIndex = 3;
1133  SCSIZE nRowToDelete = nOffset + nButtonIndex;
1134 
1135  // Check that the index is sensible
1136  SCSIZE nCount = theQueryData.GetEntryCount();
1137  if (nRowToDelete >= nCount)
1138  {
1139  SAL_WARN( "sc", "ScFilterDlg::BtnRemoveHdl: could not delete row - invalid index.");
1140  return;
1141  }
1142 
1143  // Resize maRefreshExceptQuery
1144  if (maRefreshExceptQuery.size() < nCount + 1)
1145  maRefreshExceptQuery.resize(nCount + 1, false);
1146 
1147  // Move all the subsequent rows back one position;
1148  // also find the last row, which we will delete
1149  SCSIZE nRowToClear = nCount-1;
1150  for (SCSIZE i = nRowToDelete; i < nCount-1; ++i)
1151  {
1152  if (theQueryData.GetEntry(i+1).bDoQuery)
1153  {
1154  theQueryData.GetEntry(i) = theQueryData.GetEntry(i+1);
1155  }
1156  else
1157  {
1158  nRowToClear = i;
1159  break;
1160  }
1161  }
1162 
1163  // If the next row is being edited, but not confirmed, move it back
1164  // one position
1165  if (nRowToClear < nCount-1 && maRefreshExceptQuery[nRowToClear+1])
1166  {
1167  theQueryData.GetEntry(nRowToClear) = theQueryData.GetEntry(nRowToClear+1);
1168  maRefreshExceptQuery[nRowToClear] = true;
1169  maRefreshExceptQuery[nRowToClear+1] = false;
1170  }
1171  else
1172  {
1173  // Remove the very last one, since everything has moved back
1174  theQueryData.GetEntry(nRowToClear).bDoQuery = false;
1175  theQueryData.GetEntry(nRowToClear).nField = static_cast<SCCOL>(0);
1176  maRefreshExceptQuery[nRowToClear] = false;
1177  }
1178 
1179  // Always enable the very first row
1180  if (!theQueryData.GetEntry(0).bDoQuery)
1181  {
1182  maRefreshExceptQuery[0] = true;
1183  }
1184 
1185  // Refresh the UI
1186  RefreshEditRow( nOffset );
1187 
1188  // Special handling if the very first row was cleared
1189  if (!theQueryData.GetEntry(0).bDoQuery)
1190  {
1191  m_xLbConnect1->set_active(-1);
1192  m_xLbField1->set_active(0);
1193  m_xLbField1->set_sensitive(true);
1194  m_xLbCond1->set_active(0);
1195  m_xLbCond1->set_sensitive(true);
1196  ClearValueList(1);
1197  }
1198 }
1199 
1201 {
1202  SliderMoved();
1203 }
1204 
1206 {
1207  size_t nOffset = GetSliderPos();
1208  RefreshEditRow( nOffset);
1209 }
1210 
1212 {
1213  return static_cast<size_t>(m_xScrollBar->vadjustment_get_value());
1214 }
1215 
1216 void ScFilterDlg::RefreshEditRow( size_t nOffset )
1217 {
1218  if (nOffset==0)
1219  maConnLbArr[0]->hide();
1220  else
1221  maConnLbArr[0]->show();
1222 
1223  for (size_t i = 0; i < QUERY_ENTRY_COUNT; ++i)
1224  {
1225  OUString aValStr;
1226  size_t nCondPos = 0;
1227  size_t nFieldSelPos = 0;
1228  size_t nQE = i + nOffset;
1229 
1230  if (maRefreshExceptQuery.size() < nQE + 1)
1231  maRefreshExceptQuery.resize(nQE + 1, false);
1232 
1233  ScQueryEntry& rEntry = theQueryData.GetEntry( nQE);
1234  if ( rEntry.bDoQuery || maRefreshExceptQuery[nQE] )
1235  {
1236  nCondPos = static_cast<size_t>(rEntry.eOp);
1237  if(rEntry.bDoQuery)
1238  nFieldSelPos = GetFieldSelPos( static_cast<SCCOL>(rEntry.nField) );
1239 
1240  const ScQueryEntry::Item& rItem = rEntry.GetQueryItem();
1241  OUString aQueryStr = rItem.maString.getString();
1242  if (rEntry.IsQueryByEmpty())
1243  {
1244  aValStr = aStrEmpty;
1245  maCondLbArr[i]->set_sensitive(false);
1246  }
1247  else if (rEntry.IsQueryByNonEmpty())
1248  {
1249  aValStr = aStrNotEmpty;
1250  maCondLbArr[i]->set_sensitive(false);
1251  }
1252  else if (rEntry.IsQueryByTextColor() || rEntry.IsQueryByBackgroundColor())
1253  {
1254  continue;
1255  }
1256  else
1257  {
1258  SetValString(aQueryStr, rItem, aValStr);
1259  maCondLbArr[i]->set_sensitive(true);
1260  }
1261  maFieldLbArr[i]->set_sensitive(true);
1262  maValueEdArr[i]->set_sensitive(true);
1263  maRemoveBtnArr[i]->set_sensitive(true);
1264 
1265  if (nOffset==0)
1266  {
1267  if (i<3)
1268  {
1269  if(rEntry.bDoQuery)
1270  maConnLbArr[i+1]->set_sensitive(true);
1271  else
1272  maConnLbArr[i+1]->set_sensitive(false);
1273  size_t nQENext = nQE + 1;
1274  if (maRefreshExceptQuery.size() < nQENext + 1)
1275  maRefreshExceptQuery.resize(nQENext + 1, false);
1276  if (theQueryData.GetEntry(nQENext).bDoQuery || maRefreshExceptQuery[nQENext])
1277  maConnLbArr[i+1]->set_active( static_cast<sal_uInt16>(theQueryData.GetEntry(nQENext).eConnect) );
1278  else
1279  maConnLbArr[i+1]->set_active(-1);
1280  }
1281  }
1282  else
1283  {
1284  if(theQueryData.GetEntry( nQE-1).bDoQuery)
1285  maConnLbArr[i]->set_sensitive(true);
1286  else
1287  maConnLbArr[i]->set_sensitive(false);
1288 
1289  if (maRefreshExceptQuery.size() < nQE + 1)
1290  maRefreshExceptQuery.resize(nQE + 1, false);
1291  if(rEntry.bDoQuery || maRefreshExceptQuery[nQE])
1292  maConnLbArr[i]->set_active( static_cast<sal_uInt16>(rEntry.eConnect) );
1293  else
1294  maConnLbArr[i]->set_active(-1);
1295  }
1296 
1297  }
1298  else
1299  {
1300  if (nOffset==0)
1301  {
1302  if(i<3)
1303  {
1304  maConnLbArr[i+1]->set_active(-1);
1305  maConnLbArr[i+1]->set_sensitive(false);
1306  }
1307  }
1308  else
1309  {
1310  if(theQueryData.GetEntry( nQE-1).bDoQuery)
1311  maConnLbArr[i]->set_sensitive(true);
1312  else
1313  maConnLbArr[i]->set_sensitive(false);
1314  maConnLbArr[i]->set_active(-1);
1315  }
1316  maFieldLbArr[i]->set_sensitive(false);
1317  maCondLbArr[i]->set_sensitive(false);
1318  maValueEdArr[i]->set_sensitive(false);
1319  maRemoveBtnArr[i]->set_sensitive(false);
1320  }
1321  maFieldLbArr[i]->set_active( nFieldSelPos );
1322  maCondLbArr [i]->set_active( nCondPos );
1323  maValueEdArr[i]->set_entry_text( aValStr );
1324  UpdateValueList(i+1);
1325  }
1326 }
1327 
1328 void ScFilterDlg::SetValString( const OUString& rQueryStr, const ScQueryEntry::Item& rItem,
1329  OUString& rValStr )
1330 {
1331  if (rQueryStr.isEmpty())
1332  {
1333  pDoc = pViewData ? &pViewData->GetDocument() : nullptr;
1334  if (rItem.meType == ScQueryEntry::ByValue)
1335  {
1336  if (pDoc)
1337  {
1338  pDoc->GetFormatTable()->GetInputLineString(rItem.mfVal, 0, rValStr);
1339  }
1340  }
1341  else if (rItem.meType == ScQueryEntry::ByDate)
1342  {
1343  if (pDoc)
1344  {
1345  SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1346  pFormatter->GetInputLineString(rItem.mfVal,
1347  pFormatter->GetStandardFormat( SvNumFormatType::DATE), rValStr);
1348  }
1349  }
1350  else
1351  {
1352  SAL_WARN( "sc", "ScFilterDlg::SetValString: empty query string, really?");
1353  rValStr = rQueryStr;
1354  }
1355  }
1356  else
1357  {
1358  // XXX NOTE: if not ByString we just assume this has been
1359  // set to a proper string corresponding to the numeric
1360  // value earlier!
1361  rValStr = rQueryStr;
1362  }
1363 }
1364 
1365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< weld::Button > m_xBtnRemove2
Definition: filtdlg.hxx:108
size_t GetSliderPos() const
Definition: filtdlg.cxx:1211
bool IsQueryByBackgroundColor() const
Definition: queryentry.cxx:152
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2116
static SC_DLLPUBLIC OUString ReplaceOrAppend(const OUString &rString, std::u16string_view rPlaceholder, const OUString &rReplacement)
Replaces the first occurrence of rPlaceholder in rString with rReplacement, or if rPlaceholder is not...
Definition: global.cxx:1068
void UpdateValueList(size_t nList)
Definition: filtdlg.cxx:425
virtual ~ScFilterDlg() override
Definition: filtdlg.cxx:114
void SetQueryByEmpty()
Definition: queryentry.cxx:76
std::unique_ptr< weld::ComboBox > m_xEdVal3
Definition: filtdlg.hxx:113
OUString getString() const
ScAddress aStart
Definition: address.hxx:499
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:353
std::unique_ptr< weld::ComboBox > m_xLbCond2
Definition: filtdlg.hxx:106
std::unique_ptr< weld::ScrolledWindow > m_xScrollBar
Definition: filtdlg.hxx:123
#define EMPTY_OUSTRING
Definition: global.hxx:213
SCTAB nSrcTab
Definition: filtdlg.hxx:81
SCROW Row() const
Definition: address.hxx:261
bool bRefInputMode
Definition: filtdlg.hxx:91
const Item & GetQueryItem() const
Definition: queryentry.hxx:85
void SetValString(const OUString &rQueryStr, const ScQueryEntry::Item &rItem, OUString &rValStr)
Definition: filtdlg.cxx:1328
void insert_text(int pos, const OUString &rStr)
std::unique_ptr< ScFilterOptionsMgr > pOptionsMgr
Definition: filtdlg.hxx:74
std::unique_ptr< weld::ComboBox > m_xEdVal1
Definition: filtdlg.hxx:101
virtual OUString get_text(int pos) const =0
ScDocument * pDoc
Definition: filtdlg.hxx:80
std::unique_ptr< weld::CheckButton > m_xBtnDestPers
Definition: filtdlg.hxx:138
std::unique_ptr< formula::RefEdit > m_xEdCopyArea
Definition: filtdlg.hxx:136
void ScColToAlpha(OUStringBuffer &rBuf, SCCOL nCol)
append alpha representation of column to buffer
Definition: address.cxx:1926
std::vector< ScTypedStrData >::iterator begin()
ScViewData * GetViewData() const
Definition: uiitems.hxx:162
std::vector< ScTypedStrData >::iterator end()
SCTAB GetTabNo() const
Definition: viewdata.hxx:394
std::vector< weld::ComboBox * > maValueEdArr
Definition: filtdlg.hxx:83
SCCOLROW nField
Definition: queryentry.hxx:61
ScAddress aEnd
Definition: address.hxx:500
ScDocument & GetDocument() const
Definition: viewdata.hxx:379
virtual void SetActive() override
Definition: filtdlg.cxx:367
bool IsQueryByEmpty() const
Definition: queryentry.cxx:86
virtual int get_active() const =0
virtual void Close() override
Definition: filtdlg.cxx:345
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:494
std::unique_ptr< formula::RefButton > m_xRbCopyArea
Definition: filtdlg.hxx:137
std::unique_ptr< weld::CheckButton > m_xBtnCopyResult
Definition: filtdlg.hxx:134
virtual int get_count() const =0
ScQueryParam theQueryData
Definition: filtdlg.hxx:77
std::unique_ptr< weld::ComboBox > m_xLbConnect1
Definition: filtdlg.hxx:98
std::vector< weld::ComboBox * > maFieldLbArr
Definition: filtdlg.hxx:84
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
Definition: filtdlg.cxx:356
std::deque< bool > maHasDates
Definition: filtdlg.hxx:89
std::unique_ptr< weld::ComboBox > m_xLbConnect4
Definition: filtdlg.hxx:116
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:44
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
IMPL_LINK_NOARG(ScFilterDlg, MoreExpandedHdl, weld::Expander &, void)
Definition: filtdlg.cxx:722
std::unique_ptr< weld::ComboBox > m_xLbCopyArea
Definition: filtdlg.hxx:135
int nCount
SC_DLLPUBLIC OUString GetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScInterpreterContext *pContext=nullptr) const
Definition: document.cxx:3517
SC_DLLPUBLIC const ScQueryEntry & GetEntry(SCSIZE n) const
Definition: queryparam.cxx:124
void push_back(const ScTypedStrData &r)
SCTAB Tab() const
Definition: address.hxx:270
std::unique_ptr< weld::Button > m_xBtnRemove3
Definition: filtdlg.hxx:114
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2403
void RefreshEditRow(size_t nOffset)
Definition: filtdlg.cxx:1216
IMPL_LINK(ScFilterDlg, BtnClearHdl, weld::Button &, rBtn, void)
Definition: filtdlg.cxx:626
virtual bool IsRefInputMode() const override
Definition: filtdlg.cxx:619
const OUString aStrColumn
Definition: filtdlg.hxx:72
void set_active_text(const OUString &rStr)
SC_DLLPUBLIC SvNumberFormatter * GetFormatTable() const
Definition: documen2.cxx:440
ScFilterEntries maFilterEntries
Definition: filtdlg.hxx:42
std::unique_ptr< weld::CheckButton > m_xBtnRegExp
Definition: filtdlg.hxx:131
std::unique_ptr< weld::ComboBox > m_xLbCond3
Definition: filtdlg.hxx:112
int i
bool IsQueryByNonEmpty() const
Definition: queryentry.cxx:108
sal_Int16 SCCOL
Definition: types.hxx:21
std::unique_ptr< weld::ComboBox > m_xLbField4
Definition: filtdlg.hxx:117
virtual void insert_vector(const std::vector< weld::ComboBoxEntry > &rItems, bool bKeepExisting)=0
std::unique_ptr< Timer > pTimer
Definition: filtdlg.hxx:96
const OUString aStrUndefined
Definition: filtdlg.hxx:67
const OUString aStrEmpty
Definition: filtdlg.hxx:70
std::unique_ptr< weld::Label > m_xFtDbAreaLabel
Definition: filtdlg.hxx:139
std::unique_ptr< weld::ComboBox > m_xLbConnect3
Definition: filtdlg.hxx:110
float u
void GetInputLineString(const double &fOutNumber, sal_uInt32 nFIndex, OUString &rOutString, bool bFiltering=false)
std::unique_ptr< weld::ComboBox > m_xLbField2
Definition: filtdlg.hxx:105
std::unique_ptr< weld::ComboBox > m_xLbField3
Definition: filtdlg.hxx:111
virtual void RefInputDone(bool bForced=false) override
Definition: anyrefdg.cxx:756
void UpdateHdrInValueList(size_t nList)
Definition: filtdlg.cxx:511
ScQueryItem * GetOutputItem()
Definition: filtdlg.cxx:577
virtual void clear()=0
std::vector< weld::Button * > maRemoveBtnArr
Definition: filtdlg.hxx:87
std::unique_ptr< weld::Widget > m_xContents
Definition: filtdlg.hxx:122
const OUString aStrNone
Definition: filtdlg.hxx:68
svl::SharedString maString
Definition: queryentry.hxx:49
SCCOL Col() const
Definition: address.hxx:266
std::unique_ptr< weld::Button > m_xBtnClear
Definition: filtdlg.hxx:126
SC_DLLPUBLIC void GetFilterEntriesArea(SCCOL nCol, SCROW nStartRow, SCROW nEndRow, SCTAB nTab, bool bCaseSens, ScFilterEntries &rFilterEntries)
Entries for Filter dialog.
Definition: documen3.cxx:1603
std::unique_ptr< weld::ComboBox > m_xLbField1
Definition: filtdlg.hxx:99
bool IsQueryByTextColor() const
Definition: queryentry.cxx:131
sal_Int32 SCROW
Definition: types.hxx:17
OUString ScResId(std::string_view aId)
Definition: scdll.cxx:89
std::unique_ptr< weld::CheckButton > m_xBtnCase
Definition: filtdlg.hxx:130
std::unique_ptr< weld::ComboBox > m_xLbConnect2
Definition: filtdlg.hxx:104
const sal_uInt16 nWhichQuery
Definition: filtdlg.hxx:76
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
#define GetWhich(nSlot)
sal_uInt32 GetStandardFormat(SvNumFormatType eType, LanguageType eLnge=LANGUAGE_DONTKNOW)
RET_OK
Reference< XExecutableDialog > m_xDialog
std::unique_ptr< weld::ComboBox > m_xEdVal2
Definition: filtdlg.hxx:107
ScFilterDlg(SfxBindings *pB, SfxChildWindow *pCW, weld::Window *pParent, const SfxItemSet &rArgSet)
Definition: filtdlg.cxx:49
#define QUERY_ENTRY_COUNT
Definition: filtdlg.cxx:43
std::deque< bool > maRefreshExceptQuery
Definition: filtdlg.hxx:90
ScQueryConnect eConnect
Definition: queryentry.hxx:63
std::unique_ptr< weld::ComboBox > m_xLbCond4
Definition: filtdlg.hxx:118
void ClearValueList(size_t nList)
Definition: filtdlg.cxx:557
ScQueryOp
Definition: global.hxx:818
void CancelAutoDBRange()
Definition: docsh5.cxx:368
std::unique_ptr< weld::Button > m_xBtnRemove1
Definition: filtdlg.hxx:102
std::unique_ptr< weld::ComboBox > m_xLbCond1
Definition: filtdlg.hxx:100
ScXMLEditAttributeMap::Entry const aEntries[]
ScViewData * pViewData
Definition: filtdlg.hxx:79
#define SAL_WARN(area, stream)
virtual void remove(int pos)=0
SVXCORE_DLLPUBLIC MSO_SPT Get(const OUString &)
void append_text(const OUString &rStr)
std::unique_ptr< weld::Button > m_xBtnOk
Definition: filtdlg.hxx:127
std::vector< weld::ComboBox * > maConnLbArr
Definition: filtdlg.hxx:86
const OUString aStrNotEmpty
Definition: filtdlg.hxx:71
size_t GetFieldSelPos(SCCOL nField)
Definition: filtdlg.cxx:569
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument &, const Details &rDetails=detailsOOOa1, ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, sal_Int32 *pSheetEndPos=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1548
std::unique_ptr< weld::Expander > m_xExpander
Definition: filtdlg.hxx:124
std::unique_ptr< ScQueryItem > pOutItem
Definition: filtdlg.hxx:78
void FillFieldLists()
Definition: filtdlg.cxx:380
void Init(const SfxItemSet &rArgSet)
Definition: filtdlg.cxx:124
ScRefFlags
Definition: address.hxx:144
ScTypedStrData & front()
bool empty() const
std::unique_ptr< weld::Button > m_xBtnRemove4
Definition: filtdlg.hxx:120
std::vector< weld::ComboBox * > maCondLbArr
Definition: filtdlg.hxx:85
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:695
std::unique_ptr< weld::Label > m_xFtDbArea
Definition: filtdlg.hxx:140
ScQueryOp eOp
Definition: queryentry.hxx:62
std::unique_ptr< weld::CheckButton > m_xBtnUnique
Definition: filtdlg.hxx:133
const OUString & GetString() const
EntryListsMap m_EntryLists
Definition: filtdlg.hxx:93
std::unique_ptr< weld::Button > m_xBtnCancel
Definition: filtdlg.hxx:128
virtual void set_entry_text(const OUString &rStr)=0
Each instance of this struct represents a single filtering criteria.
Definition: queryentry.hxx:33
void SetQueryByNonEmpty()
Definition: queryentry.cxx:98
#define INVALID_HEADER_POS
Definition: filtdlg.cxx:44
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
utl::SearchParam::SearchType eSearchType
Definition: queryparam.hxx:43
void SliderMoved()
Definition: filtdlg.cxx:1205
sal_uInt16 nPos
virtual void set_sensitive(bool sensitive)=0
sal_Int16 SCTAB
Definition: types.hxx:22
std::unique_ptr< weld::CheckButton > m_xBtnHeader
Definition: filtdlg.hxx:132
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:726
virtual OUString get_active_text() const =0
SCCOL GetCurX() const
Definition: viewdata.hxx:400
ScQueryConnect
Definition: global.hxx:838
std::unique_ptr< weld::ComboBox > m_xEdVal4
Definition: filtdlg.hxx:119