LibreOffice Module sw (master)  1
SearchResultLocator.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 
11 #include <SearchResultLocator.hxx>
12 #include <node.hxx>
13 #include <drawdoc.hxx>
14 #include <frame.hxx>
15 #include <cntfrm.hxx>
16 #include <viewsh.hxx>
19 
20 #include <tools/XmlWalker.hxx>
21 #include <tools/stream.hxx>
22 
23 #include <boost/property_tree/json_parser.hpp>
24 
25 #include <svx/svdpage.hxx>
26 #include <svx/svdobj.hxx>
27 
28 namespace sw::search
29 {
30 void SearchResultLocator::findOne(LocationResult& rResult, SearchIndexData const& rSearchIndexData)
31 {
32  if (rSearchIndexData.meType == NodeType::WriterNode)
33  {
34  SwNodes const& rNodes = mpDocument->GetNodes();
35  if (rSearchIndexData.mnNodeIndex >= sal_Int32(rNodes.Count()))
36  return;
37  SwNode* pNode = rNodes[rSearchIndexData.mnNodeIndex];
38 
39  auto* pContentNode = pNode->GetContentNode();
41 
42  if (pContentNode && pShell)
43  {
44  const SwFrame* pFrame
45  = pContentNode->getLayoutFrame(pShell->GetLayout(), nullptr, nullptr);
46  SwRect const& rArea = pFrame->getFrameArea();
47 
48  rResult.mbFound = true;
49  rResult.maRectangles.emplace_back(rArea.Left(), rArea.Top(),
50  rArea.Left() + rArea.Width(),
51  rArea.Top() + rArea.Height());
52  }
53  }
54  else if (rSearchIndexData.meType == NodeType::CommonNode)
55  {
57  auto* pModel = rDrawModelAccess.GetDrawModel();
58  for (sal_uInt16 nPage = 0; nPage < pModel->GetPageCount(); ++nPage)
59  {
60  SdrPage* pPage = pModel->GetPage(nPage);
61  for (size_t nObject = 0; nObject < pPage->GetObjCount(); ++nObject)
62  {
63  SdrObject* pObject = pPage->GetObj(nObject);
64  if (pObject)
65  {
66  if (pObject->GetName() == rSearchIndexData.maObjectName)
67  {
68  auto aRect = pObject->GetLogicRect();
69  rResult.mbFound = true;
70  rResult.maRectangles.emplace_back(aRect.Left(), aRect.Top(),
71  aRect.Left() + aRect.GetWidth(),
72  aRect.Top() + aRect.GetHeight());
73  }
74  }
75  }
76  }
77  }
78 }
79 
80 LocationResult SearchResultLocator::find(std::vector<SearchIndexData> const& rSearchIndexDataVector)
81 {
82  LocationResult aResult;
83  for (auto const& rSearchIndexData : rSearchIndexDataVector)
84  findOne(aResult, rSearchIndexData);
85 
86  return aResult;
87 }
88 
93 bool SearchResultLocator::tryParseJSON(const char* pPayload,
94  std::vector<sw::search::SearchIndexData>& rDataVector)
95 {
96  boost::property_tree::ptree aTree;
97  std::stringstream aStream(pPayload);
98  try
99  {
100  boost::property_tree::read_json(aStream, aTree);
101  }
102  catch (const boost::property_tree::json_parser_error& /*exception*/)
103  {
104  return false;
105  }
106 
107  for (const auto& rEachNode : boost::make_iterator_range(aTree.equal_range("")))
108  {
109  auto const& rEach = rEachNode.second;
110 
111  std::string sType = rEach.get<std::string>("node_type", "");
112 
113  auto eNodeType = sw::search::NodeType::Undefined;
114  if (sType == "writer")
116  else if (sType == "common")
118 
119  std::string sJsonObjectName = rEach.get<std::string>("object_name", "");
120 
121  sal_Int32 nIndex = rEach.get<sal_Int32>("index", -1);
122 
123  // Don't add search data elements that don't have valid data
124  if (eNodeType != sw::search::NodeType::Undefined && nIndex >= 0)
125  {
126  OUString sObjectName;
127  if (!sJsonObjectName.empty())
128  {
129  OString sObjectNameOString(sJsonObjectName.c_str());
130  sObjectName = OStringToOUString(sObjectNameOString, RTL_TEXTENCODING_UTF8);
131  }
132 
133  rDataVector.emplace_back(eNodeType, nIndex, sObjectName);
134  }
135  }
136 
137  return true;
138 }
139 
144 bool SearchResultLocator::tryParseXML(const char* pPayload,
145  std::vector<sw::search::SearchIndexData>& rDataVector)
146 {
147  const OString aPayloadString(pPayload);
148 
149  SvMemoryStream aStream(const_cast<char*>(aPayloadString.getStr()), aPayloadString.getLength(),
150  StreamMode::READ);
151 
152  tools::XmlWalker aWalker;
153 
154  if (!aWalker.open(&aStream))
155  return false;
156 
157  if (aWalker.name() != "indexing")
158  return true;
159 
160  aWalker.children();
161  while (aWalker.isValid())
162  {
163  if (aWalker.name() == "paragraph")
164  {
165  OString sType = aWalker.attribute("node_type");
166  OString sIndex = aWalker.attribute("index");
167  OString sObjectName = aWalker.attribute("object_name");
168 
169  if (!sType.isEmpty() && !sIndex.isEmpty())
170  {
172  aData.mnNodeIndex = sIndex.toInt32();
173  auto eNodeType = sw::search::NodeType::Undefined;
174  if (sType == "writer")
176  else if (sType == "common")
178 
179  aData.meType = eNodeType;
180  if (!sObjectName.isEmpty())
181  aData.maObjectName = OStringToOUString(sObjectName, RTL_TEXTENCODING_UTF8);
182  rDataVector.push_back(aData);
183  }
184  }
185  aWalker.next();
186  }
187  aWalker.parent();
188  return true;
189 }
190 
192 {
193  std::vector<sw::search::SearchIndexData> aDataVector;
194 
195  // Try parse the payload as JSON, if not recognised as JSON, try parse
196  // it as XML
197  tryParseJSON(pPayload, aDataVector) || tryParseXML(pPayload, aDataVector);
198 
199  return find(aDataVector);
200 }
201 
202 } // end sw namespace
203 
204 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Base class of the Writer layout elements.
Definition: frame.hxx:315
sal_Int32 nIndex
sal_uLong Count() const
Definition: ndarr.hxx:142
static bool tryParseJSON(const char *pPayload, std::vector< sw::search::SearchIndexData > &rDataVector)
Trying to parse the payload as JSON.
LocationResult find(std::vector< SearchIndexData > const &rSearchIndexDataVector)
void Left(const tools::Long nLeft)
Definition: swrect.hxx:194
SdrObject * GetObj(size_t nNum) const
size_t GetObjCount() const
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
EmbeddedObjectRef * pObject
IDocumentDrawModelAccess const & getIDocumentDrawModelAccess() const
Definition: doc.cxx:155
const SwRect & getFrameArea() const
Definition: frame.hxx:180
void Width(tools::Long nNew)
Definition: swrect.hxx:186
constexpr OUStringLiteral aData
Definition: ww8scan.hxx:48
OptionalString sType
SwContentNode * GetContentNode()
Definition: node.hxx:616
virtual const SwDrawModel * GetDrawModel() const =0
Draw Model and id accessors.
LocationResult findForPayload(const char *pPayload)
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
OUString GetName() const
void findOne(LocationResult &rResult, SearchIndexData const &rSearchIndexData)
static bool tryParseXML(const char *pPayload, std::vector< sw::search::SearchIndexData > &rDataVector)
Trying to parse the payload as XML.
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
SwNodes & GetNodes()
Definition: doc.hxx:409
void Top(const tools::Long nTop)
Definition: swrect.hxx:203
std::vector< basegfx::B2DRange > maRectangles
virtual const tools::Rectangle & GetLogicRect() const
void Height(tools::Long nNew)
Definition: swrect.hxx:190
Base class of the Writer document model elements.
Definition: node.hxx:80