1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sfx2/dispatch.hxx>
22 #include <uiitems.hxx>
23 #include <rangenam.hxx>
24 #include <reffact.hxx>
25 #include <viewdata.hxx>
26 #include <document.hxx>
28 #include <scresid.hxx>
30 #include <foptmgr.hxx>
32 #include <globstr.hrc>
33 #include <strings.hrc>
35 #include <filtdlg.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/weld.hxx>
39 // DEFINE --------------------------------------------------------------------
43 void ERRORBOX(weld::Window
* pParent
, TranslateId rid
)
45 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(pParent
,
46 VclMessageType::Warning
, VclButtonsType::Ok
,
53 ScSpecialFilterDlg::ScSpecialFilterDlg( SfxBindings
* pB
, SfxChildWindow
* pCW
, weld::Window
* pParent
,
54 const SfxItemSet
& rArgSet
)
56 : ScAnyRefDlgController(pB
, pCW
, pParent
, u
"modules/scalc/ui/advancedfilterdialog.ui"_ustr
, u
"AdvancedFilterDialog"_ustr
)
57 , aStrUndefined ( ScResId(SCSTR_UNDEFINED
) )
58 , nWhichQuery ( rArgSet
.GetPool()->GetWhichIDFromSlotID( SID_QUERY
) )
59 , theQueryData ( static_cast<const ScQueryItem
&>(
60 rArgSet
.Get( nWhichQuery
)).GetQueryData() )
63 , bRefInputMode(false)
64 , m_pRefInputEdit(nullptr)
65 , m_xLbFilterArea(m_xBuilder
->weld_combo_box(u
"lbfilterarea"_ustr
))
66 , m_xEdFilterArea(new formula::RefEdit(m_xBuilder
->weld_entry(u
"edfilterarea"_ustr
)))
67 , m_xRbFilterArea(new formula::RefButton(m_xBuilder
->weld_button(u
"rbfilterarea"_ustr
)))
68 , m_xExpander(m_xBuilder
->weld_expander(u
"more"_ustr
))
69 , m_xBtnCase(m_xBuilder
->weld_check_button(u
"case"_ustr
))
70 , m_xBtnRegExp(m_xBuilder
->weld_check_button(u
"regexp"_ustr
))
71 , m_xBtnHeader(m_xBuilder
->weld_check_button(u
"header"_ustr
))
72 , m_xBtnUnique(m_xBuilder
->weld_check_button(u
"unique"_ustr
))
73 , m_xBtnCopyResult(m_xBuilder
->weld_check_button(u
"copyresult"_ustr
))
74 , m_xLbCopyArea(m_xBuilder
->weld_combo_box(u
"lbcopyarea"_ustr
))
75 , m_xEdCopyArea(new formula::RefEdit(m_xBuilder
->weld_entry(u
"edcopyarea"_ustr
)))
76 , m_xRbCopyArea(new formula::RefButton(m_xBuilder
->weld_button(u
"rbcopyarea"_ustr
)))
77 , m_xBtnDestPers(m_xBuilder
->weld_check_button(u
"destpers"_ustr
))
78 , m_xFtDbAreaLabel(m_xBuilder
->weld_label(u
"dbarealabel"_ustr
))
79 , m_xFtDbArea(m_xBuilder
->weld_label(u
"dbarea"_ustr
))
80 , m_xBtnOk(m_xBuilder
->weld_button(u
"ok"_ustr
))
81 , m_xBtnCancel(m_xBuilder
->weld_button(u
"cancel"_ustr
))
82 , m_xFilterFrame(m_xBuilder
->weld_frame(u
"filterframe"_ustr
))
83 , m_xFilterLabel(m_xFilterFrame
->weld_label_widget())
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());
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
);
103 m_xEdFilterArea
->GrabFocus();
106 ScSpecialFilterDlg::~ScSpecialFilterDlg()
113 void ScSpecialFilterDlg::Init( const SfxItemSet
& rArgSet
)
115 const ScQueryItem
& rQueryItem
= static_cast<const ScQueryItem
&>(
116 rArgSet
.Get( nWhichQuery
));
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
) );
123 pViewData
= rQueryItem
.GetViewData();
124 pDoc
= pViewData
? &pViewData
->GetDocument() : nullptr;
126 m_xEdFilterArea
->SetText( OUString() ); // may be overwritten below
128 if ( pViewData
&& pDoc
)
130 if(pDoc
->GetChangeTrack()!=nullptr) m_xBtnCopyResult
->set_sensitive(false);
132 ScRangeName
* pRangeNames
= pDoc
->GetRangeName();
133 m_xLbFilterArea
->clear();
134 m_xLbFilterArea
->append_text(aStrUndefined
);
136 for (const auto& rEntry
: *pRangeNames
)
138 if (!rEntry
.second
->HasType(ScRangeData::Type::Criteria
))
141 OUString aSymbol
= rEntry
.second
->GetSymbol();
142 m_xLbFilterArea
->append(aSymbol
, rEntry
.second
->GetName());
145 // is there a stored source range?
148 if (rQueryItem
.GetAdvancedQuerySource(aAdvSource
))
150 OUString
aRefStr(aAdvSource
.Format(*pDoc
, ScRefFlags::RANGE_ABS_3D
, pDoc
->GetAddressConvention()));
151 m_xEdFilterArea
->SetRefString( aRefStr
);
155 m_xLbFilterArea
->set_active( 0 );
157 // let options be initialized:
159 pOptionsMgr
.reset( new ScFilterOptionsMgr(
166 m_xBtnCopyResult
.get(),
167 m_xBtnDestPers
.get(),
171 m_xFtDbAreaLabel
.get(),
175 // special filter always needs column headers
176 m_xBtnHeader
->set_active(true);
177 m_xBtnHeader
->set_sensitive(false);
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
185 void ScSpecialFilterDlg::Close()
188 pViewData
->GetDocShell()->CancelAutoDBRange();
190 DoClose( ScSpecialFilterDlgWrapper::GetChildWindowId() );
193 // Transfer of a table area selected with the mouse, which is then displayed
194 // as a new selection in the reference edit.
196 void ScSpecialFilterDlg::SetReference( const ScRange
& rRef
, ScDocument
& rDocP
)
198 if ( !(bRefInputMode
&& m_pRefInputEdit
) ) // only possible if in the reference edit mode
201 if ( rRef
.aStart
!= rRef
.aEnd
)
202 RefInputStart( m_pRefInputEdit
);
205 const formula::FormulaGrammar::AddressConvention eConv
= rDocP
.GetAddressConvention();
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
);
212 m_pRefInputEdit
->SetRefString( aRefStr
);
215 void ScSpecialFilterDlg::SetActive()
219 if (m_pRefInputEdit
== m_xEdCopyArea
.get())
221 m_xEdCopyArea
->GrabFocus();
222 m_xEdCopyArea
->GetModifyHdl().Call( *m_xEdCopyArea
);
224 else if (m_pRefInputEdit
== m_xEdFilterArea
.get())
226 m_xEdFilterArea
->GrabFocus();
227 FilterAreaModHdl( *m_xEdFilterArea
);
231 m_xDialog
->grab_focus();
236 ScQueryItem
* ScSpecialFilterDlg::GetOutputItem( const ScQueryParam
& rParam
,
237 const ScRange
& rSource
)
239 pOutItem
.reset(new ScQueryItem( nWhichQuery
, &rParam
));
240 pOutItem
->SetAdvancedQuerySource( &rSource
);
241 return pOutItem
.get();
244 bool ScSpecialFilterDlg::IsRefInputMode() const
246 return bRefInputMode
;
251 IMPL_LINK(ScSpecialFilterDlg
, EndDlgHdl
, weld::Button
&, rBtn
, void)
253 OSL_ENSURE( pDoc
&& pViewData
, "Document or ViewData not found. :-/" );
255 if (&rBtn
== m_xBtnOk
.get() && pDoc
&& pViewData
)
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();
266 if ( m_xBtnCopyResult
->get_active() )
268 sal_Int32 nColonPos
= theCopyStr
.indexOf( ':' );
270 if ( -1 != nColonPos
)
271 theCopyStr
= theCopyStr
.copy( 0, nColonPos
);
273 ScRefFlags nResult
= theAdrCopy
.Parse( theCopyStr
, *pDoc
, eConv
);
275 if ( (nResult
& ScRefFlags::VALID
) == ScRefFlags::ZERO
)
277 if (!m_xExpander
->get_expanded())
278 m_xExpander
->set_expanded(true);
280 ERRORBOX(m_xDialog
.get(), STR_INVALID_TABREF
);
281 m_xEdCopyArea
->GrabFocus();
282 bEditInputOk
= false;
288 ScRefFlags nResult
= ScRange().Parse( theAreaStr
, *pDoc
, eConv
);
290 if ( (nResult
& ScRefFlags::VALID
) == ScRefFlags::ZERO
)
292 ERRORBOX(m_xDialog
.get(), STR_INVALID_TABREF
);
293 m_xEdFilterArea
->GrabFocus();
294 bEditInputOk
= false;
301 * All edit fields contain valid areas. Now try to create
302 * a ScQueryParam from the filter area:
305 ScRefFlags nResult
= theFilterArea
.Parse( theAreaStr
, *pDoc
, eConv
);
307 if ( (nResult
& ScRefFlags::VALID
) == ScRefFlags::VALID
)
309 ScAddress
& rStart
= theFilterArea
.aStart
;
310 ScAddress
& rEnd
= theFilterArea
.aEnd
;
312 if ( m_xBtnCopyResult
->get_active() )
314 theOutParam
.bInplace
= false;
315 theOutParam
.nDestTab
= theAdrCopy
.Tab();
316 theOutParam
.nDestCol
= theAdrCopy
.Col();
317 theOutParam
.nDestRow
= theAdrCopy
.Row();
321 theOutParam
.bInplace
= true;
322 theOutParam
.nDestTab
= 0;
323 theOutParam
.nDestCol
= 0;
324 theOutParam
.nDestRow
= 0;
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
:
331 utl::SearchParam::SearchType::Normal
;
332 theOutParam
.bDuplicate
= !m_xBtnUnique
->get_active();
333 theOutParam
.bDestPers
= m_xBtnDestPers
->get_active();
335 bQueryOk
= pDoc
->CreateQueryParam(ScRange(rStart
,rEnd
), theOutParam
);
341 SetDispatcherLock( false );
343 GetBindings().GetDispatcher()->ExecuteList(FID_FILTER_OK
,
344 SfxCallMode::SLOT
| SfxCallMode::RECORD
,
345 { GetOutputItem(theOutParam
, theFilterArea
) });
350 ERRORBOX(m_xDialog
.get(), STR_INVALID_QUERYAREA
);
351 m_xEdFilterArea
->GrabFocus();
354 else if (&rBtn
== m_xBtnCancel
.get())
356 response(RET_CANCEL
);
360 IMPL_LINK_NOARG(ScSpecialFilterDlg
, RefInputEditHdl
, formula::RefEdit
&, void)
365 IMPL_LINK_NOARG(ScSpecialFilterDlg
, RefInputButtonHdl
, formula::RefButton
&, void)
370 void ScSpecialFilterDlg::RefInputHdl()
372 if (!m_xDialog
->has_toplevel_focus())
375 if( m_xEdCopyArea
->GetWidget()->has_focus() || m_xRbCopyArea
->GetWidget()->has_focus() )
377 m_pRefInputEdit
= m_xEdCopyArea
.get();
378 bRefInputMode
= true;
380 else if( m_xEdFilterArea
->GetWidget()->has_focus() || m_xRbFilterArea
->GetWidget()->has_focus() )
382 m_pRefInputEdit
= m_xEdFilterArea
.get();
383 bRefInputMode
= true;
385 else if( bRefInputMode
)
387 m_pRefInputEdit
= nullptr;
388 bRefInputMode
= false;
392 IMPL_LINK(ScSpecialFilterDlg
, FilterAreaSelHdl
, weld::ComboBox
&, rLb
, void)
394 if (&rLb
== m_xLbFilterArea
.get())
397 const sal_Int32 nSelPos
= m_xLbFilterArea
->get_active();
400 aString
= m_xLbFilterArea
->get_id(nSelPos
);
402 m_xEdFilterArea
->SetText( aString
);
406 IMPL_LINK( ScSpecialFilterDlg
, FilterAreaModHdl
, formula::RefEdit
&, rEd
, void )
408 if (&rEd
!= m_xEdFilterArea
.get())
411 if ( pDoc
&& pViewData
)
413 OUString theCurAreaStr
= rEd
.GetText();
414 ScRefFlags nResult
= ScRange().Parse( theCurAreaStr
, *pDoc
);
416 if ( (nResult
& ScRefFlags::VALID
) == ScRefFlags::VALID
)
418 const sal_Int32 nCount
= m_xLbFilterArea
->get_count();
419 for (sal_Int32 i
= 1; i
< nCount
; ++i
)
421 OUString aStr
= m_xLbFilterArea
->get_id(i
);
422 if (theCurAreaStr
== aStr
)
424 m_xLbFilterArea
->set_active( i
);
428 m_xLbFilterArea
->set_active( 0 );
432 m_xLbFilterArea
->set_active( 0 );
435 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */