Line data Source code
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/dialog.hxx>
22 : #include <vcl/msgbox.hxx>
23 : #include <vcl/button.hxx>
24 : #include <vcl/fixed.hxx>
25 : #include <vcl/lstbox.hxx>
26 : #include <svl/fstathelper.hxx>
27 : #include <unotools/pathoptions.hxx>
28 : #include <unotools/transliterationwrapper.hxx>
29 : #include <swtypes.hxx>
30 : #include <swmodule.hxx>
31 : #include <shellio.hxx>
32 : #include <initui.hxx>
33 : #include <glosdoc.hxx>
34 : #include <gloslst.hxx>
35 : #include <swunohelper.hxx>
36 :
37 : #include <vector>
38 :
39 : #include <utlui.hrc>
40 : #include <gloslst.hrc>
41 :
42 :
43 : #define STRING_DELIM (char)0x0A
44 : #define GLOS_TIMEOUT 30000 // update every 30 seconds
45 : #define FIND_MAX_GLOS 20
46 :
47 :
48 0 : struct TripleString
49 : {
50 : String sGroup;
51 : String sBlock;
52 : String sShort;
53 : };
54 :
55 0 : class SwGlossDecideDlg : public ModalDialog
56 : {
57 : OKButton aOk;
58 : CancelButton aCancel;
59 : HelpButton aHelp;
60 : ListBox aListLB;
61 : FixedLine aFL;
62 :
63 : DECL_LINK(DoubleClickHdl, void*);
64 : DECL_LINK(SelectHdl, void*);
65 :
66 : public:
67 : SwGlossDecideDlg(Window* pParent);
68 0 : ListBox& GetListBox() {return aListLB;}
69 : };
70 :
71 0 : SwGlossDecideDlg::SwGlossDecideDlg(Window* pParent) :
72 : ModalDialog(pParent, SW_RES(DLG_GLOSSARY_DECIDE_DLG)),
73 : aOk(this, SW_RES(PB_OK)),
74 : aCancel(this, SW_RES(PB_CANCEL)),
75 : aHelp(this, SW_RES(PB_HELP)),
76 : aListLB(this, SW_RES(LB_LIST)),
77 0 : aFL(this, SW_RES(FL_GLOSS))
78 : {
79 0 : FreeResource();
80 0 : aListLB.SetDoubleClickHdl(LINK(this, SwGlossDecideDlg, DoubleClickHdl));
81 0 : aListLB.SetSelectHdl(LINK(this, SwGlossDecideDlg, SelectHdl));
82 0 : }
83 :
84 0 : IMPL_LINK_NOARG(SwGlossDecideDlg, DoubleClickHdl)
85 : {
86 0 : EndDialog(RET_OK);
87 0 : return 0;
88 : }
89 :
90 0 : IMPL_LINK_NOARG(SwGlossDecideDlg, SelectHdl)
91 : {
92 0 : aOk.Enable(LISTBOX_ENTRY_NOTFOUND != aListLB.GetSelectEntryPos());
93 0 : return 0;
94 : }
95 :
96 0 : SwGlossaryList::SwGlossaryList() :
97 0 : bFilled(sal_False)
98 : {
99 0 : SvtPathOptions aPathOpt;
100 0 : sPath = aPathOpt.GetAutoTextPath();
101 0 : SetTimeout(GLOS_TIMEOUT);
102 0 : }
103 :
104 0 : SwGlossaryList::~SwGlossaryList()
105 : {
106 0 : ClearGroups();
107 0 : }
108 :
109 : // If the GroupName is already known, then only rShortName
110 : // will be filled. Otherwise also rGroupName will be set and
111 : // on demand asked for the right group.
112 :
113 0 : sal_Bool SwGlossaryList::GetShortName(const String& rLongName,
114 : String& rShortName, String& rGroupName )
115 : {
116 0 : if(!bFilled)
117 0 : Update();
118 :
119 0 : std::vector<TripleString> aTripleStrings;
120 :
121 0 : sal_uInt16 nCount = aGroupArr.size();
122 0 : sal_uInt16 nFound = 0;
123 0 : for(sal_uInt16 i = 0; i < nCount; i++ )
124 : {
125 0 : AutoTextGroup* pGroup = aGroupArr[i];
126 0 : if(rGroupName.Len() && rGroupName != pGroup->sName)
127 0 : continue;
128 :
129 0 : for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
130 : {
131 0 : String sLong = pGroup->sLongNames.GetToken(j, STRING_DELIM);
132 0 : if(rLongName != sLong)
133 0 : continue;
134 :
135 0 : TripleString pTriple;
136 0 : pTriple.sGroup = pGroup->sName;
137 0 : pTriple.sBlock = sLong;
138 0 : pTriple.sShort = pGroup->sShortNames.GetToken(j, STRING_DELIM);
139 0 : aTripleStrings.push_back(pTriple);
140 0 : ++nFound;
141 0 : }
142 : }
143 :
144 0 : sal_Bool bRet = sal_False;
145 0 : nCount = aTripleStrings.size();
146 0 : if(1 == nCount)
147 : {
148 0 : const TripleString& pTriple(aTripleStrings.front());
149 0 : rShortName = pTriple.sShort;
150 0 : rGroupName = pTriple.sGroup;
151 0 : bRet = sal_True;
152 : }
153 0 : else if(1 < nCount)
154 : {
155 0 : SwGlossDecideDlg aDlg(0);
156 0 : String sTitle = aDlg.GetText();
157 0 : sTitle += ' ';
158 0 : sTitle += aTripleStrings.front().sBlock;
159 0 : aDlg.SetText(sTitle);
160 :
161 0 : ListBox& rLB = aDlg.GetListBox();
162 0 : for(std::vector<TripleString>::const_iterator i = aTripleStrings.begin(); i != aTripleStrings.end(); ++i)
163 0 : rLB.InsertEntry(i->sGroup.GetToken(0, GLOS_DELIM));
164 :
165 0 : rLB.SelectEntryPos(0);
166 0 : if(RET_OK == aDlg.Execute() &&
167 0 : LISTBOX_ENTRY_NOTFOUND != rLB.GetSelectEntryPos())
168 : {
169 0 : const TripleString& pTriple(aTripleStrings[rLB.GetSelectEntryPos()]);
170 0 : rShortName = pTriple.sShort;
171 0 : rGroupName = pTriple.sGroup;
172 0 : bRet = sal_True;
173 : }
174 : else
175 0 : bRet = sal_False;
176 : }
177 0 : return bRet;
178 : }
179 :
180 0 : sal_uInt16 SwGlossaryList::GetGroupCount()
181 : {
182 0 : if(!bFilled)
183 0 : Update();
184 0 : return aGroupArr.size();
185 : }
186 :
187 0 : String SwGlossaryList::GetGroupName(sal_uInt16 nPos, bool bNoPath, String* pTitle)
188 : {
189 : OSL_ENSURE(aGroupArr.size() > nPos, "group not available");
190 0 : String sRet;
191 0 : if(nPos < aGroupArr.size())
192 : {
193 0 : AutoTextGroup* pGroup = aGroupArr[nPos];
194 0 : sRet = pGroup->sName;
195 0 : if(bNoPath)
196 0 : sRet = sRet.GetToken(0, GLOS_DELIM);
197 0 : if(pTitle)
198 0 : *pTitle = pGroup->sTitle;
199 : }
200 0 : return sRet;
201 :
202 : }
203 :
204 0 : sal_uInt16 SwGlossaryList::GetBlockCount(sal_uInt16 nGroup)
205 : {
206 : OSL_ENSURE(aGroupArr.size() > nGroup, "group not available");
207 0 : if(nGroup < aGroupArr.size())
208 : {
209 0 : AutoTextGroup* pGroup = aGroupArr[nGroup];
210 0 : return pGroup->nCount;
211 : }
212 0 : return 0;
213 : }
214 :
215 0 : String SwGlossaryList::GetBlockName(sal_uInt16 nGroup, sal_uInt16 nBlock, String& rShortName)
216 : {
217 : OSL_ENSURE(aGroupArr.size() > nGroup, "group not available");
218 0 : if(nGroup < aGroupArr.size())
219 : {
220 0 : AutoTextGroup* pGroup = aGroupArr[nGroup];
221 0 : rShortName = pGroup->sShortNames.GetToken(nBlock, STRING_DELIM);
222 0 : return pGroup->sLongNames.GetToken(nBlock, STRING_DELIM);
223 : }
224 0 : return aEmptyStr;
225 : }
226 :
227 0 : void SwGlossaryList::Update()
228 : {
229 0 : if(!IsActive())
230 0 : Start();
231 :
232 0 : SvtPathOptions aPathOpt;
233 0 : String sTemp( aPathOpt.GetAutoTextPath() );
234 0 : if(sTemp != sPath)
235 : {
236 0 : sPath = sTemp;
237 0 : bFilled = sal_False;
238 0 : ClearGroups();
239 : }
240 0 : SwGlossaries* pGlossaries = ::GetGlossaries();
241 0 : const std::vector<String> & rPathArr = pGlossaries->GetPathArray();
242 0 : String sExt( SwGlossaries::GetExtension() );
243 0 : if(!bFilled)
244 : {
245 0 : sal_uInt16 nGroupCount = pGlossaries->GetGroupCnt();
246 0 : for(sal_uInt16 i = 0; i < nGroupCount; i++)
247 : {
248 0 : String sGrpName = pGlossaries->GetGroupName(i);
249 0 : sal_uInt16 nPath = (sal_uInt16)sGrpName.GetToken(1, GLOS_DELIM).ToInt32();
250 0 : if( static_cast<size_t>(nPath) < rPathArr.size() )
251 : {
252 0 : AutoTextGroup* pGroup = new AutoTextGroup;
253 0 : pGroup->sName = sGrpName;
254 :
255 0 : FillGroup(pGroup, pGlossaries);
256 0 : String sName = rPathArr[nPath];
257 0 : sName += INET_PATH_TOKEN;
258 0 : sName += pGroup->sName.GetToken(0, GLOS_DELIM);
259 0 : sName += sExt;
260 :
261 : FStatHelper::GetModifiedDateTimeOfFile( sName,
262 : &pGroup->aDateModified,
263 0 : &pGroup->aDateModified );
264 :
265 0 : aGroupArr.insert( aGroupArr.begin(), pGroup );
266 : }
267 0 : }
268 0 : bFilled = sal_True;
269 : }
270 : else
271 : {
272 0 : for( size_t nPath = 0; nPath < rPathArr.size(); nPath++ )
273 : {
274 0 : std::vector<String> aFoundGroupNames;
275 0 : std::vector<String*> aFiles;
276 0 : std::vector<DateTime*> aDateTimeArr;
277 :
278 0 : SWUnoHelper::UCB_GetFileListOfFolder( rPathArr[nPath], aFiles,
279 0 : &sExt, &aDateTimeArr );
280 0 : for( size_t nFiles = 0; nFiles < aFiles.size(); ++nFiles )
281 : {
282 0 : String* pTitle = aFiles[ nFiles ];
283 0 : ::DateTime* pDT = (::DateTime*) aDateTimeArr[ static_cast<sal_uInt16>(nFiles) ];
284 :
285 0 : String sName( pTitle->Copy( 0, pTitle->Len() - sExt.Len() ));
286 :
287 0 : aFoundGroupNames.push_back(sName);
288 0 : sName += GLOS_DELIM;
289 0 : sName += OUString::number( static_cast<sal_uInt16>(nPath) );
290 0 : AutoTextGroup* pFound = FindGroup( sName );
291 0 : if( !pFound )
292 : {
293 0 : pFound = new AutoTextGroup;
294 0 : pFound->sName = sName;
295 0 : FillGroup( pFound, pGlossaries );
296 0 : pFound->aDateModified = *pDT;
297 :
298 0 : aGroupArr.push_back(pFound);
299 : }
300 0 : else if( pFound->aDateModified < *pDT )
301 : {
302 0 : FillGroup(pFound, pGlossaries);
303 0 : pFound->aDateModified = *pDT;
304 : }
305 :
306 : // don't need any more these pointers
307 0 : delete pTitle;
308 0 : delete pDT;
309 0 : }
310 :
311 0 : sal_uInt16 nArrCount = aGroupArr.size();
312 0 : for( sal_uInt16 i = nArrCount; i; --i)
313 : {
314 : // maybe remove deleted groups
315 0 : AutoTextGroup* pGroup = aGroupArr[i - 1];
316 : sal_uInt16 nGroupPath = (sal_uInt16)pGroup->sName.GetToken( 1,
317 0 : GLOS_DELIM).ToInt32();
318 : // Only the groups will be checked which are registered
319 : // for the current subpath.
320 0 : if( nGroupPath == static_cast<sal_uInt16>(nPath) )
321 : {
322 0 : bool bFound = false;
323 0 : String sCompareGroup = pGroup->sName.GetToken(0, GLOS_DELIM);
324 0 : for(std::vector<String>::const_iterator j = aFoundGroupNames.begin(); j != aFoundGroupNames.end() && !bFound; ++j)
325 0 : bFound = (sCompareGroup == *j);
326 :
327 0 : if(!bFound)
328 : {
329 0 : aGroupArr.erase(aGroupArr.begin() + i - 1);
330 0 : delete pGroup;
331 0 : }
332 : }
333 : }
334 0 : }
335 0 : }
336 0 : }
337 :
338 0 : void SwGlossaryList::Timeout()
339 : {
340 : // Only update automatically if a SwView has the focus.
341 0 : if(::GetActiveView())
342 0 : Update();
343 0 : }
344 :
345 0 : AutoTextGroup* SwGlossaryList::FindGroup(const String& rGroupName)
346 : {
347 0 : for(sal_uInt16 i = 0; i < aGroupArr.size(); i++)
348 : {
349 0 : AutoTextGroup* pRet = aGroupArr[i];
350 0 : if(pRet->sName == rGroupName)
351 0 : return pRet;
352 : }
353 0 : return 0;
354 : }
355 :
356 0 : void SwGlossaryList::FillGroup(AutoTextGroup* pGroup, SwGlossaries* pGlossaries)
357 : {
358 0 : SwTextBlocks* pBlock = pGlossaries->GetGroupDoc(pGroup->sName);
359 0 : pGroup->nCount = pBlock ? pBlock->GetCount() : 0;
360 0 : pGroup->sLongNames = pGroup->sShortNames = aEmptyStr;
361 0 : if(pBlock)
362 0 : pGroup->sTitle = pBlock->GetName();
363 :
364 0 : for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
365 : {
366 0 : pGroup->sLongNames += pBlock->GetLongName(j);
367 0 : pGroup->sLongNames += STRING_DELIM;
368 0 : pGroup->sShortNames += pBlock->GetShortName(j);
369 0 : pGroup->sShortNames += STRING_DELIM;
370 : }
371 0 : pGlossaries->PutGroupDoc(pBlock);
372 0 : }
373 :
374 : // Give back all (not exceeding FIND_MAX_GLOS) found modules
375 : // with matching beginning.
376 :
377 0 : bool SwGlossaryList::HasLongName(const String& rBegin, std::vector<String> *pLongNames)
378 : {
379 0 : if(!bFilled)
380 0 : Update();
381 0 : sal_uInt16 nFound = 0;
382 0 : sal_uInt16 nCount = aGroupArr.size();
383 0 : sal_uInt16 nBeginLen = rBegin.Len();
384 0 : const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
385 :
386 0 : for(sal_uInt16 i = 0; i < nCount; i++ )
387 : {
388 0 : AutoTextGroup* pGroup = aGroupArr[i];
389 0 : for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
390 : {
391 0 : String sBlock = pGroup->sLongNames.GetToken(j, STRING_DELIM);
392 0 : if( rSCmp.isEqual( sBlock.Copy(0, nBeginLen), rBegin ) &&
393 0 : nBeginLen + 1 < sBlock.Len())
394 : {
395 0 : pLongNames->push_back( sBlock );
396 0 : nFound++;
397 0 : if(FIND_MAX_GLOS == nFound)
398 0 : break;
399 : }
400 0 : }
401 : }
402 0 : return nFound > 0;
403 : }
404 :
405 0 : void SwGlossaryList::ClearGroups()
406 : {
407 0 : sal_uInt16 nCount = aGroupArr.size();
408 0 : for( sal_uInt16 i = 0; i < nCount; ++i )
409 0 : delete aGroupArr[ i ];
410 :
411 0 : aGroupArr.clear();
412 0 : bFilled = sal_False;
413 99 : }
414 :
415 :
416 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|