LibreOffice Module sc (master)  1
sfiltdlg.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 
22 #include <uiitems.hxx>
23 #include <rangenam.hxx>
24 #include <reffact.hxx>
25 #include <viewdata.hxx>
26 #include <document.hxx>
27 #include <docsh.hxx>
28 #include <scresid.hxx>
29 
30 #include <foptmgr.hxx>
31 
32 #include <globstr.hrc>
33 #include <strings.hrc>
34 
35 #include <filtdlg.hxx>
36 #include <vcl/idle.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/weld.hxx>
39 
40 // DEFINE --------------------------------------------------------------------
41 
42 namespace
43 {
44  void ERRORBOX(weld::Window* pParent, const char* rid)
45  {
46  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
47  VclMessageType::Warning, VclButtonsType::Ok,
48  ScResId(rid)));
49  xBox->run();
50  }
51 }
52 
53 
55  const SfxItemSet& rArgSet )
56 
57  : ScAnyRefDlgController(pB, pCW, pParent, "modules/scalc/ui/advancedfilterdialog.ui", "AdvancedFilterDialog")
58  , aStrUndefined ( ScResId(SCSTR_UNDEFINED) )
59  , nWhichQuery ( rArgSet.GetPool()->GetWhich( SID_QUERY ) )
60  , theQueryData ( static_cast<const ScQueryItem&>(
61  rArgSet.Get( nWhichQuery )).GetQueryData() )
62  , pViewData(nullptr)
63  , pDoc(nullptr)
64  , bRefInputMode(false)
65  , m_pRefInputEdit(nullptr)
66  , m_xLbFilterArea(m_xBuilder->weld_combo_box("lbfilterarea"))
67  , m_xEdFilterArea(new formula::RefEdit(m_xBuilder->weld_entry("edfilterarea")))
68  , m_xRbFilterArea(new formula::RefButton(m_xBuilder->weld_button("rbfilterarea")))
69  , m_xExpander(m_xBuilder->weld_expander("more"))
70  , m_xBtnCase(m_xBuilder->weld_check_button("case"))
71  , m_xBtnRegExp(m_xBuilder->weld_check_button("regexp"))
72  , m_xBtnHeader(m_xBuilder->weld_check_button("header"))
73  , m_xBtnUnique(m_xBuilder->weld_check_button("unique"))
74  , m_xBtnCopyResult(m_xBuilder->weld_check_button("copyresult"))
75  , m_xLbCopyArea(m_xBuilder->weld_combo_box("lbcopyarea"))
76  , m_xEdCopyArea(new formula::RefEdit(m_xBuilder->weld_entry("edcopyarea")))
77  , m_xRbCopyArea(new formula::RefButton(m_xBuilder->weld_button("rbcopyarea")))
78  , m_xBtnDestPers(m_xBuilder->weld_check_button("destpers"))
79  , m_xFtDbAreaLabel(m_xBuilder->weld_label("dbarealabel"))
80  , m_xFtDbArea(m_xBuilder->weld_label("dbarea"))
81  , m_xBtnOk(m_xBuilder->weld_button("ok"))
82  , m_xBtnCancel(m_xBuilder->weld_button("cancel"))
83  , m_xFilterFrame(m_xBuilder->weld_frame("filterframe"))
84  , m_xFilterLabel(m_xFilterFrame->weld_label_widget())
85 {
86  m_xEdFilterArea->SetReferences(this, m_xFilterLabel.get());
87  m_xRbFilterArea->SetReferences(this, m_xEdFilterArea.get());
88  m_xEdCopyArea->SetReferences(this, m_xFtDbAreaLabel.get());
89  m_xRbCopyArea->SetReferences(this, m_xEdCopyArea.get());
90 
91  Init( rArgSet );
92 
93  Link<formula::RefEdit&, void> aLinkEdit = LINK(this, ScSpecialFilterDlg, RefInputEditHdl);
94  Link<formula::RefButton&, void> aLinkButton = LINK(this, ScSpecialFilterDlg, RefInputButtonHdl);
95  m_xEdCopyArea->SetGetFocusHdl(aLinkEdit);
96  m_xRbCopyArea->SetGetFocusHdl(aLinkButton);
97  m_xEdFilterArea->SetGetFocusHdl(aLinkEdit);
98  m_xRbFilterArea->SetGetFocusHdl(aLinkButton);
99  m_xEdCopyArea->SetLoseFocusHdl(aLinkEdit);
100  m_xRbCopyArea->SetLoseFocusHdl(aLinkButton);
101  m_xEdFilterArea->SetLoseFocusHdl(aLinkEdit);
102  m_xRbFilterArea->SetLoseFocusHdl(aLinkButton);
103 
104  m_xEdFilterArea->GrabFocus();
105 }
106 
108 {
109  pOptionsMgr.reset();
110 
111  pOutItem.reset();
112 }
113 
114 void ScSpecialFilterDlg::Init( const SfxItemSet& rArgSet )
115 {
116  const ScQueryItem& rQueryItem = static_cast<const ScQueryItem&>(
117  rArgSet.Get( nWhichQuery ));
118 
119  m_xBtnOk->connect_clicked( LINK( this, ScSpecialFilterDlg, EndDlgHdl ) );
120  m_xBtnCancel->connect_clicked( LINK( this, ScSpecialFilterDlg, EndDlgHdl ) );
121  m_xLbFilterArea->connect_changed( LINK( this, ScSpecialFilterDlg, FilterAreaSelHdl ) );
122  m_xEdFilterArea->SetModifyHdl ( LINK( this, ScSpecialFilterDlg, FilterAreaModHdl ) );
123 
124  pViewData = rQueryItem.GetViewData();
125  pDoc = pViewData ? &pViewData->GetDocument() : nullptr;
126 
127  m_xEdFilterArea->SetText( EMPTY_OUSTRING ); // may be overwritten below
128 
129  if ( pViewData && pDoc )
130  {
131  if(pDoc->GetChangeTrack()!=nullptr) m_xBtnCopyResult->set_sensitive(false);
132 
133  ScRangeName* pRangeNames = pDoc->GetRangeName();
134  m_xLbFilterArea->clear();
135  m_xLbFilterArea->append_text(aStrUndefined);
136 
137  for (const auto& rEntry : *pRangeNames)
138  {
139  if (!rEntry.second->HasType(ScRangeData::Type::Criteria))
140  continue;
141 
142  OUString aSymbol;
143  rEntry.second->GetSymbol(aSymbol);
144  m_xLbFilterArea->append(aSymbol, rEntry.second->GetName());
145  }
146 
147  // is there a stored source range?
148 
149  ScRange aAdvSource;
150  if (rQueryItem.GetAdvancedQuerySource(aAdvSource))
151  {
152  OUString aRefStr(aAdvSource.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, pDoc->GetAddressConvention()));
153  m_xEdFilterArea->SetRefString( aRefStr );
154  }
155  }
156 
157  m_xLbFilterArea->set_active( 0 );
158 
159  // let options be initialized:
160 
161  pOptionsMgr.reset( new ScFilterOptionsMgr(
162  pViewData,
163  theQueryData,
164  m_xBtnCase.get(),
165  m_xBtnRegExp.get(),
166  m_xBtnHeader.get(),
167  m_xBtnUnique.get(),
168  m_xBtnCopyResult.get(),
169  m_xBtnDestPers.get(),
170  m_xLbCopyArea.get(),
171  m_xEdCopyArea.get(),
172  m_xRbCopyArea.get(),
173  m_xFtDbAreaLabel.get(),
174  m_xFtDbArea.get(),
175  aStrUndefined ) );
176 
177  // special filter always needs column headers
178  m_xBtnHeader->set_active(true);
179  m_xBtnHeader->set_sensitive(false);
180 
181  // turn on modal mode
182  // SetDispatcherLock( true );
183  //@BugID 54702 enable/disable in base class only
184  //SFX_APPWINDOW->Disable(false); //! general method in ScAnyRefDlg
185 }
186 
188 {
189  if (pViewData)
191 
192  DoClose( ScSpecialFilterDlgWrapper::GetChildWindowId() );
193 }
194 
195 // Transfer of a table area selected with the mouse, which is then displayed
196 // as a new selection in the reference edit.
197 
199 {
200  if ( !(bRefInputMode && m_pRefInputEdit) ) // only possible if in the reference edit mode
201  return;
202 
203  if ( rRef.aStart != rRef.aEnd )
205 
206  OUString aRefStr;
208 
209  if (m_pRefInputEdit == m_xEdCopyArea.get())
210  aRefStr = rRef.aStart.Format(ScRefFlags::ADDR_ABS_3D, &rDocP, eConv);
211  else if (m_pRefInputEdit == m_xEdFilterArea.get())
212  aRefStr = rRef.Format(rDocP, ScRefFlags::RANGE_ABS_3D, eConv);
213 
214  m_pRefInputEdit->SetRefString( aRefStr );
215 }
216 
218 {
219  if ( bRefInputMode )
220  {
221  if (m_pRefInputEdit == m_xEdCopyArea.get())
222  {
223  m_xEdCopyArea->GrabFocus();
224  m_xEdCopyArea->GetModifyHdl().Call( *m_xEdCopyArea );
225  }
226  else if (m_pRefInputEdit == m_xEdFilterArea.get())
227  {
228  m_xEdFilterArea->GrabFocus();
229  FilterAreaModHdl( *m_xEdFilterArea );
230  }
231  }
232  else
233  m_xDialog->grab_focus();
234 
235  RefInputDone();
236 }
237 
239  const ScRange& rSource )
240 {
241  pOutItem.reset(new ScQueryItem( nWhichQuery, &rParam ));
242  pOutItem->SetAdvancedQuerySource( &rSource );
243  return pOutItem.get();
244 }
245 
247 {
248  return bRefInputMode;
249 }
250 
251 // Handler:
252 
253 IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button&, rBtn, void)
254 {
255  OSL_ENSURE( pDoc && pViewData, "Document or ViewData not found. :-/" );
256 
257  if (&rBtn == m_xBtnOk.get() && pDoc && pViewData)
258  {
259  OUString theCopyStr( m_xEdCopyArea->GetText() );
260  OUString theAreaStr( m_xEdFilterArea->GetText() );
261  ScQueryParam theOutParam( theQueryData );
262  ScAddress theAdrCopy;
263  bool bEditInputOk = true;
264  bool bQueryOk = false;
265  ScRange theFilterArea;
266  const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
267 
268  if ( m_xBtnCopyResult->get_active() )
269  {
270  sal_Int32 nColonPos = theCopyStr.indexOf( ':' );
271 
272  if ( -1 != nColonPos )
273  theCopyStr = theCopyStr.copy( 0, nColonPos );
274 
275  ScRefFlags nResult = theAdrCopy.Parse( theCopyStr, *pDoc, eConv );
276 
277  if ( (nResult & ScRefFlags::VALID) == ScRefFlags::ZERO )
278  {
279  if (!m_xExpander->get_expanded())
280  m_xExpander->set_expanded(true);
281 
282  ERRORBOX(m_xDialog.get(), STR_INVALID_TABREF);
283  m_xEdCopyArea->GrabFocus();
284  bEditInputOk = false;
285  }
286  }
287 
288  if ( bEditInputOk )
289  {
290  ScRefFlags nResult = ScRange().Parse( theAreaStr, *pDoc, eConv );
291 
292  if ( (nResult & ScRefFlags::VALID) == ScRefFlags::ZERO )
293  {
294  ERRORBOX(m_xDialog.get(), STR_INVALID_TABREF);
295  m_xEdFilterArea->GrabFocus();
296  bEditInputOk = false;
297  }
298  }
299 
300  if ( bEditInputOk )
301  {
302  /*
303  * All edit fields contain valid areas. Now try to create
304  * a ScQueryParam from the filter area:
305  */
306 
307  ScRefFlags nResult = theFilterArea.Parse( theAreaStr, *pDoc, eConv );
308 
309  if ( (nResult & ScRefFlags::VALID) == ScRefFlags::VALID )
310  {
311  ScAddress& rStart = theFilterArea.aStart;
312  ScAddress& rEnd = theFilterArea.aEnd;
313 
314  if ( m_xBtnCopyResult->get_active() )
315  {
316  theOutParam.bInplace = false;
317  theOutParam.nDestTab = theAdrCopy.Tab();
318  theOutParam.nDestCol = theAdrCopy.Col();
319  theOutParam.nDestRow = theAdrCopy.Row();
320  }
321  else
322  {
323  theOutParam.bInplace = true;
324  theOutParam.nDestTab = 0;
325  theOutParam.nDestCol = 0;
326  theOutParam.nDestRow = 0;
327  }
328 
329  theOutParam.bHasHeader = m_xBtnHeader->get_active();
330  theOutParam.bByRow = true;
331  theOutParam.bCaseSens = m_xBtnCase->get_active();
332  theOutParam.eSearchType = m_xBtnRegExp->get_active() ? utl::SearchParam::SearchType::Regexp :
334  theOutParam.bDuplicate = !m_xBtnUnique->get_active();
335  theOutParam.bDestPers = m_xBtnDestPers->get_active();
336 
337  bQueryOk = pDoc->CreateQueryParam(ScRange(rStart,rEnd), theOutParam);
338  }
339  }
340 
341  if ( bQueryOk )
342  {
343  SetDispatcherLock( false );
344  SwitchToDocument();
345  GetBindings().GetDispatcher()->ExecuteList(FID_FILTER_OK,
346  SfxCallMode::SLOT | SfxCallMode::RECORD,
347  { GetOutputItem(theOutParam, theFilterArea) });
348  response(RET_OK);
349  }
350  else
351  {
352  ERRORBOX(m_xDialog.get(), STR_INVALID_QUERYAREA);
353  m_xEdFilterArea->GrabFocus();
354  }
355  }
356  else if (&rBtn == m_xBtnCancel.get())
357  {
358  response(RET_CANCEL);
359  }
360 }
361 
363 {
364  RefInputHdl();
365 }
366 
368 {
369  RefInputHdl();
370 }
371 
373 {
374  if (!m_xDialog->has_toplevel_focus())
375  return;
376 
377  if( m_xEdCopyArea->GetWidget()->has_focus() || m_xRbCopyArea->GetWidget()->has_focus() )
378  {
380  bRefInputMode = true;
381  }
382  else if( m_xEdFilterArea->GetWidget()->has_focus() || m_xRbFilterArea->GetWidget()->has_focus() )
383  {
385  bRefInputMode = true;
386  }
387  else if( bRefInputMode )
388  {
389  m_pRefInputEdit = nullptr;
390  bRefInputMode = false;
391  }
392 }
393 
394 IMPL_LINK(ScSpecialFilterDlg, FilterAreaSelHdl, weld::ComboBox&, rLb, void)
395 {
396  if (&rLb == m_xLbFilterArea.get())
397  {
398  OUString aString;
399  const sal_Int32 nSelPos = m_xLbFilterArea->get_active();
400 
401  if ( nSelPos > 0 )
402  aString = m_xLbFilterArea->get_id(nSelPos);
403 
404  m_xEdFilterArea->SetText( aString );
405  }
406 }
407 
408 IMPL_LINK( ScSpecialFilterDlg, FilterAreaModHdl, formula::RefEdit&, rEd, void )
409 {
410  if (&rEd != m_xEdFilterArea.get())
411  return;
412 
413  if ( pDoc && pViewData )
414  {
415  OUString theCurAreaStr = rEd.GetText();
416  ScRefFlags nResult = ScRange().Parse( theCurAreaStr, *pDoc );
417 
418  if ( (nResult & ScRefFlags::VALID) == ScRefFlags::VALID )
419  {
420  const sal_Int32 nCount = m_xLbFilterArea->get_count();
421  for (sal_Int32 i = 1; i < nCount; ++i)
422  {
423  OUString aStr = m_xLbFilterArea->get_id(i);
424  if (theCurAreaStr == aStr)
425  {
426  m_xLbFilterArea->set_active( i );
427  return;
428  }
429  }
430  m_xLbFilterArea->set_active( 0 );
431  }
432  }
433  else
434  m_xLbFilterArea->set_active( 0 );
435 }
436 
437 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< weld::CheckButton > m_xBtnUnique
Definition: filtdlg.hxx:206
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2107
std::unique_ptr< weld::CheckButton > m_xBtnDestPers
Definition: filtdlg.hxx:211
ScAddress aStart
Definition: address.hxx:500
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
#define EMPTY_OUSTRING
Definition: global.hxx:215
SCROW Row() const
Definition: address.hxx:262
std::unique_ptr< formula::RefButton > m_xRbFilterArea
Definition: filtdlg.hxx:200
std::unique_ptr< weld::Label > m_xFtDbAreaLabel
Definition: filtdlg.hxx:212
std::unique_ptr< weld::CheckButton > m_xBtnRegExp
Definition: filtdlg.hxx:204
std::unique_ptr< formula::RefEdit > m_xEdCopyArea
Definition: filtdlg.hxx:209
SC_DLLPUBLIC ScRangeName * GetRangeName(SCTAB nTab) const
Definition: documen3.cxx:168
ScViewData * GetViewData() const
Definition: uiitems.hxx:163
std::unique_ptr< formula::RefEdit > m_xEdFilterArea
Definition: filtdlg.hxx:199
ScQueryItem * GetOutputItem(const ScQueryParam &rParam, const ScRange &rSource)
Definition: sfiltdlg.cxx:238
ScAddress aEnd
Definition: address.hxx:501
std::unique_ptr< weld::CheckButton > m_xBtnHeader
Definition: filtdlg.hxx:205
ScDocument & GetDocument() const
Definition: viewdata.hxx:380
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:489
std::unique_ptr< weld::Button > m_xBtnCancel
Definition: filtdlg.hxx:216
ScDocument * pDoc
Definition: filtdlg.hxx:192
IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button &, rBtn, void)
Definition: sfiltdlg.cxx:253
std::unique_ptr< weld::Label > m_xFtDbArea
Definition: filtdlg.hxx:213
int nCount
std::unique_ptr< ScQueryItem > pOutItem
Definition: filtdlg.hxx:190
SCTAB Tab() const
Definition: address.hxx:271
std::unique_ptr< formula::RefButton > m_xRbCopyArea
Definition: filtdlg.hxx:210
std::unique_ptr< weld::CheckButton > m_xBtnCopyResult
Definition: filtdlg.hxx:207
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2392
void SetRefString(const OUString &rStr)
std::unique_ptr< weld::ComboBox > m_xLbCopyArea
Definition: filtdlg.hxx:208
int i
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
Definition: sfiltdlg.cxx:198
formula::RefEdit * m_pRefInputEdit
Definition: filtdlg.hxx:196
SC_DLLPUBLIC OUString Format(const ScDocument &rDocument, ScRefFlags nFlags=ScRefFlags::ZERO, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, bool bFullAddressNotation=false) const
Returns string with formatted cell range from aStart to aEnd, according to provided address conventio...
Definition: address.cxx:2203
OUString ScResId(const char *pId)
Definition: scdll.cxx:95
virtual void RefInputDone(bool bForced=false) override
Definition: anyrefdg.cxx:755
std::unique_ptr< ScFilterOptionsMgr > pOptionsMgr
Definition: filtdlg.hxx:186
ScViewData * pViewData
Definition: filtdlg.hxx:191
virtual void SetActive() override
Definition: sfiltdlg.cxx:217
bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: uiitems.cxx:219
SCCOL Col() const
Definition: address.hxx:267
const sal_uInt16 nWhichQuery
Definition: filtdlg.hxx:188
IMPL_LINK_NOARG(ScSpecialFilterDlg, RefInputEditHdl, formula::RefEdit &, void)
Definition: sfiltdlg.cxx:362
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
std::unique_ptr< weld::Label > m_xFilterLabel
Definition: filtdlg.hxx:219
#define GetWhich(nSlot)
RET_OK
SC_DLLPUBLIC ScRefFlags Parse(const OUString &, const ScDocument &, const ScAddress::Details &rDetails=ScAddress::detailsOOOa1, ScAddress::ExternalInfo *pExtInfo=nullptr, const css::uno::Sequence< css::sheet::ExternalLinkInfo > *pExternalLinks=nullptr, const OUString *pErrRef=nullptr)
Definition: address.cxx:1733
Reference< XExecutableDialog > m_xDialog
std::unique_ptr< weld::CheckButton > m_xBtnCase
Definition: filtdlg.hxx:203
void Init(const SfxItemSet &rArgSet)
Definition: sfiltdlg.cxx:114
void CancelAutoDBRange()
Definition: docsh5.cxx:369
const OUString aStrUndefined
Definition: filtdlg.hxx:184
std::unique_ptr< weld::Button > m_xBtnOk
Definition: filtdlg.hxx:215
ScSpecialFilterDlg(SfxBindings *pB, SfxChildWindow *pCW, weld::Window *pParent, const SfxItemSet &rArgSet)
Definition: sfiltdlg.cxx:54
SVXCORE_DLLPUBLIC MSO_SPT Get(const OUString &)
virtual void Close() override
Definition: sfiltdlg.cxx:187
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
ScRefFlags
Definition: address.hxx:145
virtual bool IsRefInputMode() const override
Definition: sfiltdlg.cxx:246
const ScQueryParam theQueryData
Definition: filtdlg.hxx:189
virtual ~ScSpecialFilterDlg() override
Definition: sfiltdlg.cxx:107
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:694
aStr
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, bool bMobile=false)
std::unique_ptr< weld::ComboBox > m_xLbFilterArea
Definition: filtdlg.hxx:198
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:725