LibreOffice Module sw (master)  1
gloslst.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 <tools/urlobj.hxx>
21 #include <vcl/weld.hxx>
22 #include <svl/fstathelper.hxx>
23 #include <unotools/pathoptions.hxx>
25 #include <swtypes.hxx>
26 #include <swmodule.hxx>
27 #include <shellio.hxx>
28 #include <initui.hxx>
29 #include <glosdoc.hxx>
30 #include <gloslst.hxx>
31 #include <swunohelper.hxx>
32 #include <view.hxx>
33 
34 #include <vector>
35 
36 #define STRING_DELIM char(0x0A)
37 #define GLOS_TIMEOUT 30000 // update every 30 seconds
38 #define FIND_MAX_GLOS 20
39 
41 {
42  OUString sGroup;
43  OUString sBlock;
44  OUString sShort;
45 };
46 
48 {
49  std::unique_ptr<weld::Button> m_xOk;
50  std::unique_ptr<weld::TreeView> m_xListLB;
51 
52  DECL_LINK(DoubleClickHdl, weld::TreeView&, void);
53  DECL_LINK(SelectHdl, weld::TreeView&, void);
54 
55 public:
56  explicit SwGlossDecideDlg(weld::Window* pParent);
57 
59 };
60 
62  : GenericDialogController(pParent, "modules/swriter/ui/selectautotextdialog.ui", "SelectAutoTextDialog")
63  , m_xOk(m_xBuilder->weld_button("ok"))
64  , m_xListLB(m_xBuilder->weld_tree_view("treeview"))
65 {
66  m_xListLB->set_size_request(m_xListLB->get_approximate_digit_width() * 32,
67  m_xListLB->get_height_rows(8));
68  m_xListLB->connect_row_activated(LINK(this, SwGlossDecideDlg, DoubleClickHdl));
69  m_xListLB->connect_changed(LINK(this, SwGlossDecideDlg, SelectHdl));
70 }
71 
73 {
74  m_xDialog->response(RET_OK);
75 }
76 
78 {
79  m_xOk->set_sensitive(m_xListLB->get_selected_index() != -1);
80 }
81 
83  bFilled(false)
84 {
85  SvtPathOptions aPathOpt;
86  sPath = aPathOpt.GetAutoTextPath();
88 }
89 
91 {
92  ClearGroups();
93 }
94 
95 // If the GroupName is already known, then only rShortName
96 // will be filled. Otherwise also rGroupName will be set and
97 // on demand asked for the right group.
98 
99 bool SwGlossaryList::GetShortName(const OUString& rLongName,
100  OUString& rShortName, OUString& rGroupName )
101 {
102  if(!bFilled)
103  Update();
104 
105  std::vector<TripleString> aTripleStrings;
106 
107  size_t nCount = aGroupArr.size();
108  for(size_t i = 0; i < nCount; i++ )
109  {
110  AutoTextGroup* pGroup = aGroupArr[i].get();
111  if(!rGroupName.isEmpty() && rGroupName != pGroup->sName)
112  continue;
113 
114  sal_Int32 nPosLong = 0;
115  for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
116  {
117  const OUString sLong = pGroup->sLongNames.getToken(0, STRING_DELIM, nPosLong);
118  if(rLongName != sLong)
119  continue;
120 
121  TripleString aTriple;
122  aTriple.sGroup = pGroup->sName;
123  aTriple.sBlock = sLong;
124  aTriple.sShort = pGroup->sShortNames.getToken(j, STRING_DELIM);
125  aTripleStrings.push_back(aTriple);
126  }
127  }
128 
129  bool bRet = false;
130  nCount = aTripleStrings.size();
131  if(1 == nCount)
132  {
133  const TripleString& rTriple(aTripleStrings.front());
134  rShortName = rTriple.sShort;
135  rGroupName = rTriple.sGroup;
136  bRet = true;
137  }
138  else if(1 < nCount)
139  {
140  SwView *pView = ::GetActiveView();
141  SwGlossDecideDlg aDlg(pView ? pView->GetFrameWeld() : nullptr);
142  OUString sTitle = aDlg.get_title() + " " + aTripleStrings.front().sBlock;
143  aDlg.set_title(sTitle);
144 
145  weld::TreeView& rLB = aDlg.GetTreeView();
146  for (const auto& rTriple : aTripleStrings)
147  rLB.append_text(rTriple.sGroup.getToken(0, GLOS_DELIM));
148 
149  rLB.select(0);
150  if (aDlg.run() == RET_OK && rLB.get_selected_index() != -1)
151  {
152  const TripleString& rTriple(aTripleStrings[rLB.get_selected_index()]);
153  rShortName = rTriple.sShort;
154  rGroupName = rTriple.sGroup;
155  bRet = true;
156  }
157  else
158  bRet = false;
159  }
160  return bRet;
161 }
162 
164 {
165  if(!bFilled)
166  Update();
167  return aGroupArr.size();
168 }
169 
170 OUString SwGlossaryList::GetGroupName(size_t nPos)
171 {
172  OSL_ENSURE(aGroupArr.size() > nPos, "group not available");
173  if(nPos < aGroupArr.size())
174  {
175  AutoTextGroup* pGroup = aGroupArr[nPos].get();
176  OUString sRet = pGroup->sName;
177  return sRet;
178  }
179  return OUString();
180 }
181 
182 OUString SwGlossaryList::GetGroupTitle(size_t nPos)
183 {
184  OSL_ENSURE(aGroupArr.size() > nPos, "group not available");
185  if(nPos < aGroupArr.size())
186  {
187  AutoTextGroup* pGroup = aGroupArr[nPos].get();
188  return pGroup->sTitle;
189  }
190  return OUString();
191 }
192 
193 sal_uInt16 SwGlossaryList::GetBlockCount(size_t nGroup)
194 {
195  OSL_ENSURE(aGroupArr.size() > nGroup, "group not available");
196  if(nGroup < aGroupArr.size())
197  {
198  AutoTextGroup* pGroup = aGroupArr[nGroup].get();
199  return pGroup->nCount;
200  }
201  return 0;
202 }
203 
204 OUString SwGlossaryList::GetBlockLongName(size_t nGroup, sal_uInt16 nBlock)
205 {
206  OSL_ENSURE(aGroupArr.size() > nGroup, "group not available");
207  if(nGroup < aGroupArr.size())
208  {
209  AutoTextGroup* pGroup = aGroupArr[nGroup].get();
210  return pGroup->sLongNames.getToken(nBlock, STRING_DELIM);
211  }
212  return OUString();
213 }
214 
215 OUString SwGlossaryList::GetBlockShortName(size_t nGroup, sal_uInt16 nBlock)
216 {
217  OSL_ENSURE(aGroupArr.size() > nGroup, "group not available");
218  if(nGroup < aGroupArr.size())
219  {
220  AutoTextGroup* pGroup = aGroupArr[nGroup].get();
221  return pGroup->sShortNames.getToken(nBlock, STRING_DELIM);
222  }
223  return OUString();
224 }
225 
227 {
228  if(!IsActive())
229  Start();
230 
231  SvtPathOptions aPathOpt;
232  const OUString& sTemp( aPathOpt.GetAutoTextPath() );
233  if(sTemp != sPath)
234  {
235  sPath = sTemp;
236  bFilled = false;
237  ClearGroups();
238  }
240  const std::vector<OUString> & rPathArr = pGlossaries->GetPathArray();
241  const OUString sExt( SwGlossaries::GetExtension() );
242  if(!bFilled)
243  {
244  const size_t nGroupCount = pGlossaries->GetGroupCnt();
245  for(size_t i = 0; i < nGroupCount; ++i)
246  {
247  OUString sGrpName = pGlossaries->GetGroupName(i);
248  const size_t nPath = static_cast<size_t>(
249  sGrpName.getToken(1, GLOS_DELIM).toInt32());
250  if( nPath < rPathArr.size() )
251  {
252  std::unique_ptr<AutoTextGroup> pGroup(new AutoTextGroup);
253  pGroup->sName = sGrpName;
254 
255  FillGroup(pGroup.get(), pGlossaries);
256  OUString sName = rPathArr[nPath] + "/" +
257  pGroup->sName.getToken(0, GLOS_DELIM) + sExt;
259  &pGroup->aDateModified,
260  &pGroup->aDateModified );
261 
262  aGroupArr.insert( aGroupArr.begin(), std::move(pGroup) );
263  }
264  }
265  bFilled = true;
266  }
267  else
268  {
269  for( size_t nPath = 0; nPath < rPathArr.size(); nPath++ )
270  {
271  std::vector<OUString> aFoundGroupNames;
272  std::vector<OUString> aFiles;
273  std::vector<DateTime> aDateTimeArr;
274 
275  SWUnoHelper::UCB_GetFileListOfFolder( rPathArr[nPath], aFiles,
276  &sExt, &aDateTimeArr );
277  for( size_t nFiles = 0; nFiles < aFiles.size(); ++nFiles )
278  {
279  const OUString aTitle = aFiles[ nFiles ];
280  ::DateTime& rDT = aDateTimeArr[ nFiles ];
281 
282  OUString sName( aTitle.copy( 0, aTitle.getLength() - sExt.getLength() ));
283 
284  aFoundGroupNames.push_back(sName);
285  sName += OUStringLiteral1(GLOS_DELIM) + OUString::number( static_cast<sal_uInt16>(nPath) );
286  AutoTextGroup* pFound = FindGroup( sName );
287  if( !pFound )
288  {
289  pFound = new AutoTextGroup;
290  pFound->sName = sName;
291  FillGroup( pFound, pGlossaries );
292  pFound->aDateModified = rDT;
293 
294  aGroupArr.push_back(std::unique_ptr<AutoTextGroup>(pFound));
295  }
296  else if( pFound->aDateModified < rDT )
297  {
298  FillGroup(pFound, pGlossaries);
299  pFound->aDateModified = rDT;
300  }
301  }
302 
303  for( size_t i = aGroupArr.size(); i>0; )
304  {
305  --i;
306  // maybe remove deleted groups
307  AutoTextGroup* pGroup = aGroupArr[i].get();
308  const size_t nGroupPath = static_cast<size_t>(
309  pGroup->sName.getToken( 1, GLOS_DELIM).toInt32());
310  // Only the groups will be checked which are registered
311  // for the current subpath.
312  if( nGroupPath == nPath )
313  {
314  OUString sCompareGroup = pGroup->sName.getToken(0, GLOS_DELIM);
315  bool bFound = std::any_of(aFoundGroupNames.begin(), aFoundGroupNames.end(),
316  [&sCompareGroup](const OUString& rGroupName) { return sCompareGroup == rGroupName; });
317 
318  if(!bFound)
319  {
320  aGroupArr.erase(aGroupArr.begin() + i);
321  }
322  }
323  }
324  }
325  }
326 }
327 
329 {
330  // Only update automatically if a SwView has the focus.
331  if(::GetActiveView())
332  Update();
333 }
334 
335 AutoTextGroup* SwGlossaryList::FindGroup(const OUString& rGroupName)
336 {
337  for(auto & pRet : aGroupArr)
338  {
339  if(pRet->sName == rGroupName)
340  return pRet.get();
341  }
342  return nullptr;
343 }
344 
346 {
347  std::unique_ptr<SwTextBlocks> pBlock = pGlossaries->GetGroupDoc(pGroup->sName);
348  pGroup->nCount = pBlock ? pBlock->GetCount() : 0;
349  pGroup->sLongNames.clear();
350  pGroup->sShortNames.clear();
351  if(pBlock)
352  pGroup->sTitle = pBlock->GetName();
353 
354  for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
355  {
356  pGroup->sLongNames += pBlock->GetLongName(j)
357  + OUStringLiteral1(STRING_DELIM);
358  pGroup->sShortNames += pBlock->GetShortName(j)
359  + OUStringLiteral1(STRING_DELIM);
360  }
361 }
362 
363 // Give back all (not exceeding FIND_MAX_GLOS) found modules
364 // with matching beginning.
365 
366 void SwGlossaryList::HasLongName(const OUString& rBegin, std::vector<OUString> *pLongNames)
367 {
368  if(!bFilled)
369  Update();
370  sal_uInt16 nFound = 0;
371  const size_t nCount = aGroupArr.size();
372  sal_Int32 nBeginLen = rBegin.getLength();
373  const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
374 
375  for(size_t i = 0; i < nCount; ++i)
376  {
377  AutoTextGroup* pGroup = aGroupArr[i].get();
378  sal_Int32 nIdx{ 0 };
379  for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
380  {
381  OUString sBlock = pGroup->sLongNames.getToken(0, STRING_DELIM, nIdx);
382  if( nBeginLen + 1 < sBlock.getLength() &&
383  rSCmp.isEqual( sBlock.copy(0, nBeginLen), rBegin ))
384  {
385  pLongNames->push_back( sBlock );
386  nFound++;
387  if(FIND_MAX_GLOS == nFound)
388  break;
389  }
390  }
391  }
392 }
393 
395 {
396  aGroupArr.clear();
397  bFilled = false;
398 }
399 
400 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString sLongNames
Definition: gloslst.hxx:35
const ::utl::TransliterationWrapper & GetAppCmpStrIgnore()
Definition: init.cxx:823
std::unique_ptr< weld::Button > m_xOk
Definition: gloslst.cxx:49
sal_uInt16 GetBlockCount(size_t nGroup)
Definition: gloslst.cxx:193
OUString sShortNames
Definition: gloslst.hxx:36
DateTime aDateModified
Definition: gloslst.hxx:37
SwView * GetActiveView()
Definition: swmodul1.cxx:123
void Update()
Definition: gloslst.cxx:226
std::unique_ptr< weld::TreeView > m_xListLB
Definition: gloslst.cxx:50
void HasLongName(const OUString &rBegin, std::vector< OUString > *pLongNames)
Definition: gloslst.cxx:366
size_t GetGroupCnt()
Definition: glosdoc.cxx:98
size_t GetGroupCount()
Definition: gloslst.cxx:163
std::unique_ptr< SwTextBlocks > GetGroupDoc(const OUString &rName, bool bCreate=false)
Definition: glosdoc.cxx:158
static OUString GetExtension()
Definition: glosdoc.cxx:419
#define FIND_MAX_GLOS
Definition: gloslst.cxx:38
bool IsActive() const
OUString sName
Definition: gloslst.hxx:33
void append_text(const OUString &rStr)
OUString sShort
Definition: gloslst.cxx:44
OUString GetBlockLongName(size_t nGroup, sal_uInt16 nBlock)
Definition: gloslst.cxx:204
OUString GetGroupName(size_t nPos)
Definition: gloslst.cxx:170
SW_DLLPUBLIC SwGlossaries * GetGlossaries()
Definition: initui.cxx:175
OUString GetBlockShortName(size_t nGroup, sal_uInt16 nBlock)
Definition: gloslst.cxx:215
bool GetShortName(const OUString &rLongName, OUString &rShortName, OUString &rGroupName)
Definition: gloslst.cxx:99
OUString sGroup
Definition: gloslst.cxx:42
OUString GetGroupTitle(size_t nPos)
Definition: gloslst.cxx:182
virtual int get_selected_index() const =0
static std::unique_ptr< SwGlossaries > pGlossaries
Definition: initui.cxx:42
OUString sName
int i
weld::TreeView & GetTreeView()
Definition: gloslst.cxx:58
virtual void Start() override
std::vector< std::unique_ptr< AutoTextGroup > > aGroupArr
Definition: gloslst.hxx:48
virtual void Invoke() override
Definition: gloslst.cxx:328
IMPL_LINK_NOARG(SwGlossDecideDlg, DoubleClickHdl, weld::TreeView &, void)
Definition: gloslst.cxx:72
void SetTimeout(sal_uInt64 nTimeoutMs)
static void FillGroup(AutoTextGroup *pGroup, SwGlossaries *pGloss)
Definition: gloslst.cxx:345
OUString sTitle
Definition: gloslst.hxx:34
DECL_LINK(DoubleClickHdl, weld::TreeView &, void)
virtual void select(int pos)=0
OUString sPath
Definition: gloslst.hxx:49
OUString const & GetGroupName(size_t)
Definition: glosdoc.cxx:136
weld::Window * GetFrameWeld() const
std::vector< OUString > const & GetPathArray() const
Definition: glosdoc.hxx:120
void ClearGroups()
Definition: gloslst.cxx:394
SwGlossDecideDlg(weld::Window *pParent)
Definition: gloslst.cxx:61
RET_OK
bool UCB_GetFileListOfFolder(const OUString &rURL, std::vector< OUString > &rList, const OUString *pExtension, std::vector< ::DateTime > *pDateTimeList)
sal_uInt16 nCount
Definition: gloslst.hxx:32
SVL_DLLPUBLIC bool GetModifiedDateTimeOfFile(const OUString &rURL, Date *pDate, tools::Time *pTime)
const OUString & GetAutoTextPath() const
#define GLOS_TIMEOUT
Definition: gloslst.cxx:37
#define GLOS_DELIM
Definition: glosdoc.hxx:41
virtual ~SwGlossaryList() override
Definition: gloslst.cxx:90
OUString get_title() const
#define STRING_DELIM
Definition: gloslst.cxx:36
OUString sBlock
Definition: gloslst.cxx:43
AutoTextGroup * FindGroup(const OUString &rGroupName)
Definition: gloslst.cxx:335
Definition: view.hxx:146