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