LibreOffice Module sc (master) 1
searchresults.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
10#include <o3tl/safeint.hxx>
11#include <searchresults.hxx>
12#include <sfx2/bindings.hxx>
13#include <sfx2/dispatch.hxx>
14#include <sfx2/viewfrm.hxx>
15#include <svx/srchdlg.hxx>
16#include <dociter.hxx>
17#include <document.hxx>
18#include <tabvwsh.hxx>
19#include <strings.hrc>
20#include <sc.hrc>
21#include <scresid.hxx>
22
23namespace sc {
24
26 : SfxDialogController(pParent, "modules/scalc/ui/searchresults.ui", "SearchResultsDialog")
27 , aSkipped(ScResId(SCSTR_SKIPPED))
28 , mpBindings(_pBindings)
29 , mpDoc(nullptr)
30 , mbSorted(false)
31 , mxList(m_xBuilder->weld_tree_view("results"))
32 , mxSearchResults(m_xBuilder->weld_label("lbSearchResults"))
33 , mxShowDialog(m_xBuilder->weld_check_button("cbShow"))
34{
35 mxList->set_size_request(mxList->get_approximate_digit_width() * 50, mxList->get_height_rows(15));
36 mxShowDialog->connect_toggled(LINK(this, SearchResultsDlg, OnShowToggled));
37 std::vector<int> aWidths
38 {
39 o3tl::narrowing<int>(mxList->get_approximate_digit_width() * 10),
40 o3tl::narrowing<int>(mxList->get_approximate_digit_width() * 10)
41 };
42 mxList->set_column_fixed_widths(aWidths);
43 mxList->connect_changed(LINK(this, SearchResultsDlg, ListSelectHdl));
44 mxList->connect_column_clicked(LINK(this, SearchResultsDlg, HeaderBarClick));
45}
46
48{
49 // tdf#133807 if the search dialog is shown then re-present that dialog
50 // when this results dialog is dismissed
52 if (!pViewFrame)
53 return;
54 SfxChildWindow* pChildWindow = pViewFrame->GetChildWindow(
55 SvxSearchDialogWrapper::GetChildWindowId());
56 if (!pChildWindow)
57 return;
58 SvxSearchDialog* pSearchDlg = static_cast<SvxSearchDialog*>(pChildWindow->GetController().get());
59 if (!pSearchDlg)
60 return;
61 pSearchDlg->Present();
62}
63
64namespace
65{
66 class ListWrapper {
67 weld::TreeView& mrList;
68 public:
69 size_t mnCount = 0;
70 static const size_t mnMaximum = 1000;
71 ListWrapper(weld::TreeView& rList)
72 : mrList(rList)
73 {
74 mrList.clear();
75 mrList.freeze();
76 }
77 ~ListWrapper()
78 {
79 mrList.thaw();
80 }
81 void Insert(const OUString &rTabName,
82 const ScAddress &rPos,
84 const OUString &rText)
85 {
86 if (mnCount++ < mnMaximum)
87 {
88 mrList.append_text(rTabName);
89 int nPos = mrList.n_children() - 1;
90 mrList.set_text(nPos, rPos.Format(ScRefFlags::ADDR_ABS,
91 nullptr, eConvention), 1);
92 mrList.set_text(nPos, rText, 2);
93 }
94 }
95 };
96}
97
98void SearchResultsDlg::FillResults( ScDocument& rDoc, const ScRangeList &rMatchedRanges, bool bCellNotes,
99 bool bEmptyCells, bool bMatchedRangesWereClamped )
100{
101 ListWrapper aList(*mxList);
102 std::vector<OUString> aTabNames = rDoc.GetAllTableNames();
103 SCTAB nTabCount = aTabNames.size();
104
105 // tdf#92160 - too many results blow the widget's mind
106 size_t nMatchMax = rMatchedRanges.size();
107 if (nMatchMax > ListWrapper::mnMaximum)
108 nMatchMax = ListWrapper::mnMaximum;
109
110 if (bCellNotes || bEmptyCells)
111 {
112 for (size_t i = 0, n = nMatchMax; i < n; ++i)
113 {
114 ScRange const & rRange( rMatchedRanges[i] );
115 // Bear in mind that mostly the range is one address position
116 // or a column or a row joined.
117 ScAddress aPos( rRange.aStart );
118 for ( ; aPos.Tab() <= rRange.aEnd.Tab(); aPos.IncTab())
119 {
120 if (aPos.Tab() >= nTabCount)
121 break; // can this even happen? we just searched on existing sheets ...
122 for (aPos.SetCol( rRange.aStart.Col()); aPos.Col() <= rRange.aEnd.Col(); aPos.IncCol())
123 {
124 for (aPos.SetRow( rRange.aStart.Row()); aPos.Row() <= rRange.aEnd.Row(); aPos.IncRow())
125 {
126 if (bCellNotes)
127 {
128 const ScPostIt* pNote = rDoc.GetNote( aPos);
129 if (pNote)
130 aList.Insert(aTabNames[aPos.Tab()], aPos,
132 pNote->GetText());
133 }
134 else // bEmptyCells
135 {
136 aList.Insert(aTabNames[aPos.Tab()], aPos,
138 rDoc.GetString(aPos));
139 }
140 }
141 }
142 }
143 }
144 }
145 else
146 {
147 for (size_t i = 0, n = nMatchMax; i < n; ++i)
148 {
149 ScCellIterator aIter(rDoc, rMatchedRanges[i]);
150 for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
151 {
152 const ScAddress& aPos = aIter.GetPos();
153 if (aPos.Tab() >= nTabCount)
154 // Out-of-bound sheet index.
155 continue;
156
157 aList.Insert(aTabNames[aPos.Tab()], aPos,
159 rDoc.GetString(aPos));
160 }
161 }
162 }
163
164 OUString aSearchResultsMsg;
165 if (bMatchedRangesWereClamped)
166 {
167 aSearchResultsMsg = ScResId(SCSTR_RESULTS_CLAMPED);
168 aSearchResultsMsg = aSearchResultsMsg.replaceFirst("%1", OUString::number(1000));
169 }
170 else
171 {
172 OUString aTotal(ScResId(SCSTR_TOTAL, aList.mnCount));
173 aSearchResultsMsg = aTotal.replaceFirst("%1", OUString::number(aList.mnCount));
174 if (aList.mnCount > ListWrapper::mnMaximum)
175 aSearchResultsMsg += " " + ScGlobal::ReplaceOrAppend( aSkipped, u"%1", OUString::number( ListWrapper::mnMaximum ) );
176 }
177 mxSearchResults->set_label(aSearchResultsMsg);
178
179 mpDoc = &rDoc;
180}
181
183{
184 if (mpBindings)
185 {
186 // Remove this dialog from the view frame after the dialog gets
187 // dismissed, else it would keep popping up endlessly!
188 SfxDispatcher* pDispacher = mpBindings ->GetDispatcher();
189 SfxBoolItem aItem(SID_SEARCH_RESULTS_DIALOG, false);
190 if (pDispacher)
191 {
192 pDispacher->ExecuteList(SID_SEARCH_RESULTS_DIALOG,
193 SfxCallMode::SYNCHRON | SfxCallMode::RECORD, { &aItem });
194 }
195 }
196
198}
199
200IMPL_LINK(SearchResultsDlg, HeaderBarClick, int, nColumn, void)
201{
202 if (!mbSorted)
203 {
204 mxList->make_sorted();
205 mbSorted = true;
206 }
207
208 bool bSortAtoZ = mxList->get_sort_order();
209
210 //set new arrow positions in headerbar
211 if (nColumn == mxList->get_sort_column())
212 {
213 bSortAtoZ = !bSortAtoZ;
214 mxList->set_sort_order(bSortAtoZ);
215 }
216 else
217 {
218 int nOldSortColumn = mxList->get_sort_column();
219 if (nOldSortColumn != -1)
220 mxList->set_sort_indicator(TRISTATE_INDET, nOldSortColumn);
221 mxList->set_sort_column(nColumn);
222 }
223
224 if (nColumn != -1)
225 {
226 //sort lists
227 mxList->set_sort_indicator(bSortAtoZ ? TRISTATE_TRUE : TRISTATE_FALSE, nColumn);
228 }
229}
230
232{
233 if (!mpDoc)
234 return;
235
236 int nEntry = mxList->get_selected_index();
237 OUString aTabStr = mxList->get_text(nEntry, 0);
238 OUString aPosStr = mxList->get_text(nEntry, 1);
239
240 SCTAB nTab = -1;
241 if (!mpDoc->GetTable(aTabStr, nTab))
242 // No sheet with specified name.
243 return;
244
245 ScAddress aPos;
246 ScRefFlags nRes = aPos.Parse(aPosStr, *mpDoc, mpDoc->GetAddressConvention());
247 if (!(nRes & ScRefFlags::VALID))
248 // Invalid address string.
249 return;
250
251 // Jump to the cell.
253 pScViewShell->SetTabNo(nTab);
254 pScViewShell->SetCursor(aPos.Col(), aPos.Row());
255 pScViewShell->AlignToCursor(aPos.Col(), aPos.Row(), SC_FOLLOW_JUMP);
256}
257
258IMPL_STATIC_LINK( SearchResultsDlg, OnShowToggled, weld::Toggleable&, rButton, void )
259{
261 ScViewOptions aViewOpt( pScViewShell->GetViewData().GetOptions() );
262 aViewOpt.SetOption( VOPT_SUMMARY, rButton.get_active() );
263 pScViewShell->GetViewData().SetOptions( aViewOpt );
264}
265
267 vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo* /*pInfo*/)
268 : SfxChildWindow(_pParent, nId)
269 , m_xDialog(std::make_shared<SearchResultsDlg>(pBindings, _pParent->GetFrameWeld()))
270{
272}
273
275
277{
279 aInfo.bVisible = false;
280 return aInfo;
281}
282
284
285}
286
287/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ScRefFlags
Definition: address.hxx:158
Reference< XExecutableDialog > m_xDialog
void IncTab(SCTAB nDelta=1)
Definition: address.hxx:320
SCTAB Tab() const
Definition: address.hxx:283
void SetCol(SCCOL nColP)
Definition: address.hxx:291
SC_DLLPUBLIC void Format(OStringBuffer &r, ScRefFlags nFlags, const ScDocument *pDocument=nullptr, const Details &rDetails=detailsOOOa1) const
Definition: address.cxx:2074
void IncCol(SCCOL nDelta=1)
Definition: address.hxx:316
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
SCROW Row() const
Definition: address.hxx:274
void SetRow(SCROW nRowP)
Definition: address.hxx:287
void IncRow(SCROW nDelta=1)
Definition: address.hxx:312
SCCOL Col() const
Definition: address.hxx:279
Walk through all cells in an area.
Definition: dociter.hxx:206
const ScAddress & GetPos() const
Definition: dociter.hxx:231
SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const
Definition: documen3.cxx:492
SC_DLLPUBLIC std::vector< OUString > GetAllTableNames() const
Definition: document.cxx:270
SC_DLLPUBLIC ScPostIt * GetNote(const ScAddress &rPos)
Definition: document.cxx:6587
SC_DLLPUBLIC OUString GetString(SCCOL nCol, SCROW nRow, SCTAB nTab, const ScInterpreterContext *pContext=nullptr) const
Definition: document.cxx:3505
static SC_DLLPUBLIC OUString ReplaceOrAppend(const OUString &rString, std::u16string_view rPlaceholder, const OUString &rReplacement)
Replaces the first occurrence of rPlaceholder in rString with rReplacement, or if rPlaceholder is not...
Definition: global.cxx:1147
Additional class containing cell annotation data.
Definition: postit.hxx:58
OUString GetText() const
Returns the caption text of this note.
Definition: postit.cxx:527
size_t size() const
Definition: rangelst.hxx:89
ScAddress aEnd
Definition: address.hxx:498
ScAddress aStart
Definition: address.hxx:497
static ScTabViewShell * GetActiveViewShell()
Definition: tabvwsh4.cxx:1076
void AlignToCursor(SCCOL nCurX, SCROW nCurY, ScFollowMode eMode, const ScSplitPos *pWhich=nullptr)
Definition: tabview3.cxx:917
ScViewData & GetViewData()
Definition: tabview.hxx:344
SC_DLLPUBLIC void SetCursor(SCCOL nPosX, SCROW nPosY, bool bNew=false)
Definition: tabview3.cxx:363
SC_DLLPUBLIC void SetTabNo(SCTAB nTab, bool bNew=false, bool bExtendSelection=false, bool bSameTabButMoved=false)
Definition: tabview3.cxx:1819
void SetOptions(const ScViewOptions &rOpt)
Definition: viewdata.cxx:3982
const ScViewOptions & GetOptions() const
Definition: viewdata.hxx:554
void SetOption(ScViewOption eOpt, bool bNew)
Definition: viewopti.hxx:85
SfxDispatcher * GetDispatcher() const
void SetController(std::shared_ptr< SfxDialogController > controller)
std::shared_ptr< SfxDialogController > & GetController()
virtual SfxChildWinInfo GetInfo() const
virtual void Close()
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 * >())
SfxViewFrame * GetFrame() const
SfxChildWindow * GetChildWindow(sal_uInt16)
std::shared_ptr< SearchResultsDlg > m_xDialog
virtual ~SearchResultsDlgWrapper() override
SearchResultsDlgWrapper(vcl::Window *_pParent, sal_uInt16 nId, SfxBindings *pBindings, SfxChildWinInfo *pInfo)
void FillResults(ScDocument &rDoc, const ScRangeList &rMatchedRanges, bool bCellNotes, bool bEmptyCells, bool bMatchedRangesWereClamped)
virtual void Close() override
SfxBindings * mpBindings
virtual ~SearchResultsDlg() override
std::unique_ptr< weld::Label > mxSearchResults
SearchResultsDlg(SfxBindings *_pBindings, weld::Window *pParent)
std::unique_ptr< weld::TreeView > mxList
std::unique_ptr< weld::CheckButton > mxShowDialog
virtual void set_text(int row, const OUString &rText, int col=-1)=0
void append_text(const OUString &rStr)
virtual int n_children() const=0
virtual void clear()=0
virtual void freeze()=0
virtual void thaw()=0
weld::Window * GetFrameWeld(const SfxFrame *pFrame)
virtual void Insert(SotClipboardFormatId nFormat, const OUString &rFormatName) override
std::size_t mnCount
float u
TRISTATE_FALSE
TRISTATE_INDET
TRISTATE_TRUE
sal_Int64 n
sal_uInt16 nPos
int i
std::shared_ptr< T > make_shared(Args &&... args)
CAUTION! The following defines must be in the same namespace as the respective type.
Definition: broadcast.cxx:15
IMPL_LINK_NOARG(SharedStringPoolPurge, timerHandler, Timer *, void)
IMPL_STATIC_LINK(SearchResultsDlg, OnShowToggled, weld::Toggleable &, rButton, void)
IMPL_LINK(SearchResultsDlg, HeaderBarClick, int, nColumn, void)
SFX_IMPL_CHILDWINDOW_WITHID(SearchResultsDlgWrapper, SID_SEARCH_RESULTS_DIALOG)
sal_Int16 nId
OUString ScResId(TranslateId aId)
Definition: scdll.cxx:90
sal_Int16 SCTAB
Definition: types.hxx:22
@ SC_FOLLOW_JUMP
Definition: viewdata.hxx:52
@ VOPT_SUMMARY
Definition: viewopti.hxx:47