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