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( 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 = rEntry.second->GetSymbol();
142  m_xLbFilterArea->append(aSymbol, rEntry.second->GetName());
143  }
144 
145  // is there a stored source range?
146 
147  ScRange aAdvSource;
148  if (rQueryItem.GetAdvancedQuerySource(aAdvSource))
149  {
150  OUString aRefStr(aAdvSource.Format(*pDoc, ScRefFlags::RANGE_ABS_3D, pDoc->GetAddressConvention()));
151  m_xEdFilterArea->SetRefString( aRefStr );
152  }
153  }
154 
155  m_xLbFilterArea->set_active( 0 );
156 
157  // let options be initialized:
158 
159  pOptionsMgr.reset( new ScFilterOptionsMgr(
160  pViewData,
161  theQueryData,
162  m_xBtnCase.get(),
163  m_xBtnRegExp.get(),
164  m_xBtnHeader.get(),
165  m_xBtnUnique.get(),
166  m_xBtnCopyResult.get(),
167  m_xBtnDestPers.get(),
168  m_xLbCopyArea.get(),
169  m_xEdCopyArea.get(),
170  m_xRbCopyArea.get(),
171  m_xFtDbAreaLabel.get(),
172  m_xFtDbArea.get(),
173  aStrUndefined ) );
174 
175  // special filter always needs column headers
176  m_xBtnHeader->set_active(true);
177  m_xBtnHeader->set_sensitive(false);
178 
179  // turn on modal mode
180  // SetDispatcherLock( true );
181  //@BugID 54702 enable/disable in base class only
182  //SFX_APPWINDOW->Disable(false); //! general method in ScAnyRefDlg
183 }
184 
186 {
187  if (pViewData)
189 
190  DoClose( ScSpecialFilterDlgWrapper::GetChildWindowId() );
191 }
192 
193 // Transfer of a table area selected with the mouse, which is then displayed
194 // as a new selection in the reference edit.
195 
197 {
198  if ( !(bRefInputMode && m_pRefInputEdit) ) // only possible if in the reference edit mode
199  return;
200 
201  if ( rRef.aStart != rRef.aEnd )
203 
204  OUString aRefStr;
206 
207  if (m_pRefInputEdit == m_xEdCopyArea.get())
208  aRefStr = rRef.aStart.Format(ScRefFlags::ADDR_ABS_3D, &rDocP, eConv);
209  else if (m_pRefInputEdit == m_xEdFilterArea.get())
210  aRefStr = rRef.Format(rDocP, ScRefFlags::RANGE_ABS_3D, eConv);
211 
212  m_pRefInputEdit->SetRefString( aRefStr );
213 }
214 
216 {
217  if ( bRefInputMode )
218  {
219  if (m_pRefInputEdit == m_xEdCopyArea.get())
220  {
221  m_xEdCopyArea->GrabFocus();
222  m_xEdCopyArea->GetModifyHdl().Call( *m_xEdCopyArea );
223  }
224  else if (m_pRefInputEdit == m_xEdFilterArea.get())
225  {
226  m_xEdFilterArea->GrabFocus();
227  FilterAreaModHdl( *m_xEdFilterArea );
228  }
229  }
230  else
231  m_xDialog->grab_focus();
232 
233  RefInputDone();
234 }
235 
237  const ScRange& rSource )
238 {
239  pOutItem.reset(new ScQueryItem( nWhichQuery, &rParam ));
240  pOutItem->SetAdvancedQuerySource( &rSource );
241  return pOutItem.get();
242 }
243 
245 {
246  return bRefInputMode;
247 }
248 
249 // Handler:
250 
251 IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button&, rBtn, void)
252 {
253  OSL_ENSURE( pDoc && pViewData, "Document or ViewData not found. :-/" );
254 
255  if (&rBtn == m_xBtnOk.get() && pDoc && pViewData)
256  {
257  OUString theCopyStr( m_xEdCopyArea->GetText() );
258  OUString theAreaStr( m_xEdFilterArea->GetText() );
259  ScQueryParam theOutParam( theQueryData );
260  ScAddress theAdrCopy;
261  bool bEditInputOk = true;
262  bool bQueryOk = false;
263  ScRange theFilterArea;
264  const formula::FormulaGrammar::AddressConvention eConv = pDoc->GetAddressConvention();
265 
266  if ( m_xBtnCopyResult->get_active() )
267  {
268  sal_Int32 nColonPos = theCopyStr.indexOf( ':' );
269 
270  if ( -1 != nColonPos )
271  theCopyStr = theCopyStr.copy( 0, nColonPos );
272 
273  ScRefFlags nResult = theAdrCopy.Parse( theCopyStr, *pDoc, eConv );
274 
275  if ( (nResult & ScRefFlags::VALID) == ScRefFlags::ZERO )
276  {
277  if (!m_xExpander->get_expanded())
278  m_xExpander->set_expanded(true);
279 
280  ERRORBOX(m_xDialog.get(), STR_INVALID_TABREF);
281  m_xEdCopyArea->GrabFocus();
282  bEditInputOk = false;
283  }
284  }
285 
286  if ( bEditInputOk )
287  {
288  ScRefFlags nResult = ScRange().Parse( theAreaStr, *pDoc, eConv );
289 
290  if ( (nResult & ScRefFlags::VALID) == ScRefFlags::ZERO )
291  {
292  ERRORBOX(m_xDialog.get(), STR_INVALID_TABREF);
293  m_xEdFilterArea->GrabFocus();
294  bEditInputOk = false;
295  }
296  }
297 
298  if ( bEditInputOk )
299  {
300  /*
301  * All edit fields contain valid areas. Now try to create
302  * a ScQueryParam from the filter area:
303  */
304 
305  ScRefFlags nResult = theFilterArea.Parse( theAreaStr, *pDoc, eConv );
306 
307  if ( (nResult & ScRefFlags::VALID) == ScRefFlags::VALID )
308  {
309  ScAddress& rStart = theFilterArea.aStart;
310  ScAddress& rEnd = theFilterArea.aEnd;
311 
312  if ( m_xBtnCopyResult->get_active() )
313  {
314  theOutParam.bInplace = false;
315  theOutParam.nDestTab = theAdrCopy.Tab();
316  theOutParam.nDestCol = theAdrCopy.Col();
317  theOutParam.nDestRow = theAdrCopy.Row();
318  }
319  else
320  {
321  theOutParam.bInplace = true;
322  theOutParam.nDestTab = 0;
323  theOutParam.nDestCol = 0;
324  theOutParam.nDestRow = 0;
325  }
326 
327  theOutParam.bHasHeader = m_xBtnHeader->get_active();
328  theOutParam.bByRow = true;
329  theOutParam.bCaseSens = m_xBtnCase->get_active();
330  theOutParam.eSearchType = m_xBtnRegExp->get_active() ? utl::SearchParam::SearchType::Regexp :
332  theOutParam.bDuplicate = !m_xBtnUnique->get_active();
333  theOutParam.bDestPers = m_xBtnDestPers->get_active();
334 
335  bQueryOk = pDoc->CreateQueryParam(ScRange(rStart,rEnd), theOutParam);
336  }
337  }
338 
339  if ( bQueryOk )
340  {
341  SetDispatcherLock( false );
342  SwitchToDocument();
343  GetBindings().GetDispatcher()->ExecuteList(FID_FILTER_OK,
344  SfxCallMode::SLOT | SfxCallMode::RECORD,
345  { GetOutputItem(theOutParam, theFilterArea) });
346  response(RET_OK);
347  }
348  else
349  {
350  ERRORBOX(m_xDialog.get(), STR_INVALID_QUERYAREA);
351  m_xEdFilterArea->GrabFocus();
352  }
353  }
354  else if (&rBtn == m_xBtnCancel.get())
355  {
356  response(RET_CANCEL);
357  }
358 }
359 
361 {
362  RefInputHdl();
363 }
364 
366 {
367  RefInputHdl();
368 }
369 
371 {
372  if (!m_xDialog->has_toplevel_focus())
373  return;
374 
375  if( m_xEdCopyArea->GetWidget()->has_focus() || m_xRbCopyArea->GetWidget()->has_focus() )
376  {
378  bRefInputMode = true;
379  }
380  else if( m_xEdFilterArea->GetWidget()->has_focus() || m_xRbFilterArea->GetWidget()->has_focus() )
381  {
383  bRefInputMode = true;
384  }
385  else if( bRefInputMode )
386  {
387  m_pRefInputEdit = nullptr;
388  bRefInputMode = false;
389  }
390 }
391 
392 IMPL_LINK(ScSpecialFilterDlg, FilterAreaSelHdl, weld::ComboBox&, rLb, void)
393 {
394  if (&rLb == m_xLbFilterArea.get())
395  {
396  OUString aString;
397  const sal_Int32 nSelPos = m_xLbFilterArea->get_active();
398 
399  if ( nSelPos > 0 )
400  aString = m_xLbFilterArea->get_id(nSelPos);
401 
402  m_xEdFilterArea->SetText( aString );
403  }
404 }
405 
406 IMPL_LINK( ScSpecialFilterDlg, FilterAreaModHdl, formula::RefEdit&, rEd, void )
407 {
408  if (&rEd != m_xEdFilterArea.get())
409  return;
410 
411  if ( pDoc && pViewData )
412  {
413  OUString theCurAreaStr = rEd.GetText();
414  ScRefFlags nResult = ScRange().Parse( theCurAreaStr, *pDoc );
415 
416  if ( (nResult & ScRefFlags::VALID) == ScRefFlags::VALID )
417  {
418  const sal_Int32 nCount = m_xLbFilterArea->get_count();
419  for (sal_Int32 i = 1; i < nCount; ++i)
420  {
421  OUString aStr = m_xLbFilterArea->get_id(i);
422  if (theCurAreaStr == aStr)
423  {
424  m_xLbFilterArea->set_active( i );
425  return;
426  }
427  }
428  m_xLbFilterArea->set_active( 0 );
429  }
430  }
431  else
432  m_xLbFilterArea->set_active( 0 );
433 }
434 
435 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::unique_ptr< weld::CheckButton > m_xBtnUnique
Definition: filtdlg.hxx:213
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2074
const SfxPoolItem * ExecuteList(sal_uInt16 nSlot, SfxCallMode nCall, std::initializer_list< SfxPoolItem const * > args, std::initializer_list< SfxPoolItem const * > internalargs=std::initializer_list< SfxPoolItem const * >())
std::unique_ptr< weld::CheckButton > m_xBtnDestPers
Definition: filtdlg.hxx:218
ScAddress aStart
Definition: address.hxx:497
ScDocShell * GetDocShell() const
Definition: viewdata.hxx:354
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
SCROW Row() const
Definition: address.hxx:274
std::unique_ptr< formula::RefButton > m_xRbFilterArea
Definition: filtdlg.hxx:207
std::unique_ptr< weld::Label > m_xFtDbAreaLabel
Definition: filtdlg.hxx:219
std::unique_ptr< weld::CheckButton > m_xBtnRegExp
Definition: filtdlg.hxx:211
std::unique_ptr< formula::RefEdit > m_xEdCopyArea
Definition: filtdlg.hxx:216
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:206
ScQueryItem * GetOutputItem(const ScQueryParam &rParam, const ScRange &rSource)
Definition: sfiltdlg.cxx:236
ScAddress aEnd
Definition: address.hxx:498
std::unique_ptr< weld::CheckButton > m_xBtnHeader
Definition: filtdlg.hxx:212
ScDocument & GetDocument() const
Definition: viewdata.hxx:380
virtual SfxBindings & GetBindings() override
RET_CANCEL
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:494
std::unique_ptr< weld::Button > m_xBtnCancel
Definition: filtdlg.hxx:223
ScDocument * pDoc
Definition: filtdlg.hxx:199
IMPL_LINK(ScSpecialFilterDlg, EndDlgHdl, weld::Button &, rBtn, void)
Definition: sfiltdlg.cxx:251
std::unique_ptr< weld::Label > m_xFtDbArea
Definition: filtdlg.hxx:220
int nCount
std::unique_ptr< ScQueryItem > pOutItem
Definition: filtdlg.hxx:197
SCTAB Tab() const
Definition: address.hxx:283
std::unique_ptr< formula::RefButton > m_xRbCopyArea
Definition: filtdlg.hxx:217
std::unique_ptr< weld::CheckButton > m_xBtnCopyResult
Definition: filtdlg.hxx:214
ScChangeTrack * GetChangeTrack() const
Definition: document.hxx:2485
void SetRefString(const OUString &rStr)
std::unique_ptr< weld::ComboBox > m_xLbCopyArea
Definition: filtdlg.hxx:215
int i
virtual void SetReference(const ScRange &rRef, ScDocument &rDoc) override
Definition: sfiltdlg.cxx:196
formula::RefEdit * m_pRefInputEdit
Definition: filtdlg.hxx:203
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:2170
virtual void RefInputDone(bool bForced=false) override
Definition: anyrefdg.cxx:779
std::unique_ptr< ScFilterOptionsMgr > pOptionsMgr
Definition: filtdlg.hxx:193
ScViewData * pViewData
Definition: filtdlg.hxx:198
virtual void SetActive() override
Definition: sfiltdlg.cxx:215
bool GetAdvancedQuerySource(ScRange &rSource) const
Definition: uiitems.cxx:219
SCCOL Col() const
Definition: address.hxx:279
const sal_uInt16 nWhichQuery
Definition: filtdlg.hxx:195
IMPL_LINK_NOARG(ScSpecialFilterDlg, RefInputEditHdl, formula::RefEdit &, void)
Definition: sfiltdlg.cxx:360
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
std::unique_ptr< weld::Label > m_xFilterLabel
Definition: filtdlg.hxx:226
#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:1700
Reference< XExecutableDialog > m_xDialog
std::unique_ptr< weld::CheckButton > m_xBtnCase
Definition: filtdlg.hxx:210
void Init(const SfxItemSet &rArgSet)
Definition: sfiltdlg.cxx:113
void CancelAutoDBRange()
Definition: docsh5.cxx:368
const OUString aStrUndefined
Definition: filtdlg.hxx:191
std::unique_ptr< weld::Button > m_xBtnOk
Definition: filtdlg.hxx:222
SfxDispatcher * GetDispatcher() const
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:185
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:1537
ScRefFlags
Definition: address.hxx:157
virtual bool IsRefInputMode() const override
Definition: sfiltdlg.cxx:244
const ScQueryParam theQueryData
Definition: filtdlg.hxx:196
virtual ~ScSpecialFilterDlg() override
Definition: sfiltdlg.cxx:106
bool DoClose(sal_uInt16 nId)
Definition: anyrefdg.cxx:718
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:205
virtual void RefInputStart(formula::RefEdit *pEdit, formula::RefButton *pButton=nullptr) override
Definition: anyrefdg.cxx:749
bool m_bDetectedRangeSegmentation false