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 // alle 30 s updaten
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 : /********************************************************************
110 : * Wenn der GroupName bereits bekannt ist, dann wird nur
111 : * rShortName gefuellt, sonst wird rGroupName ebenfals gesetzt und
112 : * bei Bedarf nach der richtigen Gruppe gefragt
113 : ********************************************************************/
114 :
115 0 : sal_Bool SwGlossaryList::GetShortName(const String& rLongName,
116 : String& rShortName, String& rGroupName )
117 : {
118 0 : if(!bFilled)
119 0 : Update();
120 :
121 0 : std::vector<TripleString> aTripleStrings;
122 :
123 0 : sal_uInt16 nCount = aGroupArr.size();
124 0 : sal_uInt16 nFound = 0;
125 0 : for(sal_uInt16 i = 0; i < nCount; i++ )
126 : {
127 0 : AutoTextGroup* pGroup = aGroupArr[i];
128 0 : if(rGroupName.Len() && rGroupName != pGroup->sName)
129 0 : continue;
130 :
131 0 : for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
132 : {
133 0 : String sLong = pGroup->sLongNames.GetToken(j, STRING_DELIM);
134 0 : if(rLongName != sLong)
135 0 : continue;
136 :
137 0 : TripleString pTriple;
138 0 : pTriple.sGroup = pGroup->sName;
139 0 : pTriple.sBlock = sLong;
140 0 : pTriple.sShort = pGroup->sShortNames.GetToken(j, STRING_DELIM);
141 0 : aTripleStrings.push_back(pTriple);
142 0 : ++nFound;
143 0 : }
144 : }
145 :
146 0 : sal_Bool bRet = sal_False;
147 0 : nCount = aTripleStrings.size();
148 0 : if(1 == nCount)
149 : {
150 0 : const TripleString& pTriple(aTripleStrings.front());
151 0 : rShortName = pTriple.sShort;
152 0 : rGroupName = pTriple.sGroup;
153 0 : bRet = sal_True;
154 : }
155 0 : else if(1 < nCount)
156 : {
157 0 : SwGlossDecideDlg aDlg(0);
158 0 : String sTitle = aDlg.GetText();
159 0 : sTitle += ' ';
160 0 : sTitle += aTripleStrings.front().sBlock;
161 0 : aDlg.SetText(sTitle);
162 :
163 0 : ListBox& rLB = aDlg.GetListBox();
164 0 : for(std::vector<TripleString>::const_iterator i = aTripleStrings.begin(); i != aTripleStrings.end(); ++i)
165 0 : rLB.InsertEntry(i->sGroup.GetToken(0, GLOS_DELIM));
166 :
167 0 : rLB.SelectEntryPos(0);
168 0 : if(RET_OK == aDlg.Execute() &&
169 0 : LISTBOX_ENTRY_NOTFOUND != rLB.GetSelectEntryPos())
170 : {
171 0 : const TripleString& pTriple(aTripleStrings[rLB.GetSelectEntryPos()]);
172 0 : rShortName = pTriple.sShort;
173 0 : rGroupName = pTriple.sGroup;
174 0 : bRet = sal_True;
175 : }
176 : else
177 0 : bRet = sal_False;
178 : }
179 0 : return bRet;
180 : }
181 :
182 0 : sal_uInt16 SwGlossaryList::GetGroupCount()
183 : {
184 0 : if(!bFilled)
185 0 : Update();
186 0 : return aGroupArr.size();
187 : }
188 :
189 0 : String SwGlossaryList::GetGroupName(sal_uInt16 nPos, sal_Bool bNoPath, String* pTitle)
190 : {
191 : OSL_ENSURE(aGroupArr.size() > nPos, "group not available");
192 0 : String sRet;
193 0 : if(nPos < aGroupArr.size())
194 : {
195 0 : AutoTextGroup* pGroup = aGroupArr[nPos];
196 0 : sRet = pGroup->sName;
197 0 : if(bNoPath)
198 0 : sRet = sRet.GetToken(0, GLOS_DELIM);
199 0 : if(pTitle)
200 0 : *pTitle = pGroup->sTitle;
201 : }
202 0 : return sRet;
203 :
204 : }
205 :
206 0 : sal_uInt16 SwGlossaryList::GetBlockCount(sal_uInt16 nGroup)
207 : {
208 : OSL_ENSURE(aGroupArr.size() > nGroup, "group not available");
209 0 : if(nGroup < aGroupArr.size())
210 : {
211 0 : AutoTextGroup* pGroup = aGroupArr[nGroup];
212 0 : return pGroup->nCount;
213 : }
214 0 : return 0;
215 : }
216 :
217 0 : String SwGlossaryList::GetBlockName(sal_uInt16 nGroup, sal_uInt16 nBlock, String& rShortName)
218 : {
219 : OSL_ENSURE(aGroupArr.size() > nGroup, "group not available");
220 0 : if(nGroup < aGroupArr.size())
221 : {
222 0 : AutoTextGroup* pGroup = aGroupArr[nGroup];
223 0 : rShortName = pGroup->sShortNames.GetToken(nBlock, STRING_DELIM);
224 0 : return pGroup->sLongNames.GetToken(nBlock, STRING_DELIM);
225 : }
226 0 : return aEmptyStr;
227 : }
228 :
229 0 : void SwGlossaryList::Update()
230 : {
231 0 : if(!IsActive())
232 0 : Start();
233 :
234 0 : SvtPathOptions aPathOpt;
235 0 : String sTemp( aPathOpt.GetAutoTextPath() );
236 0 : if(sTemp != sPath)
237 : {
238 0 : sPath = sTemp;
239 0 : bFilled = sal_False;
240 0 : ClearGroups();
241 : }
242 0 : SwGlossaries* pGlossaries = ::GetGlossaries();
243 0 : const std::vector<String> & rPathArr = pGlossaries->GetPathArray();
244 0 : String sExt( SwGlossaries::GetExtension() );
245 0 : if(!bFilled)
246 : {
247 0 : sal_uInt16 nGroupCount = pGlossaries->GetGroupCnt();
248 0 : for(sal_uInt16 i = 0; i < nGroupCount; i++)
249 : {
250 0 : String sGrpName = pGlossaries->GetGroupName(i);
251 0 : sal_uInt16 nPath = (sal_uInt16)sGrpName.GetToken(1, GLOS_DELIM).ToInt32();
252 0 : if( static_cast<size_t>(nPath) < rPathArr.size() )
253 : {
254 0 : AutoTextGroup* pGroup = new AutoTextGroup;
255 0 : pGroup->sName = sGrpName;
256 :
257 0 : FillGroup(pGroup, pGlossaries);
258 0 : String sName = rPathArr[nPath];
259 0 : sName += INET_PATH_TOKEN;
260 0 : sName += pGroup->sName.GetToken(0, GLOS_DELIM);
261 0 : sName += sExt;
262 :
263 : FStatHelper::GetModifiedDateTimeOfFile( sName,
264 : &pGroup->aDateModified,
265 0 : &pGroup->aDateModified );
266 :
267 0 : aGroupArr.insert( aGroupArr.begin(), pGroup );
268 : }
269 0 : }
270 0 : bFilled = sal_True;
271 : }
272 : else
273 : {
274 0 : for( size_t nPath = 0; nPath < rPathArr.size(); nPath++ )
275 : {
276 0 : std::vector<String> aFoundGroupNames;
277 0 : std::vector<String*> aFiles;
278 0 : std::vector<DateTime*> aDateTimeArr;
279 :
280 0 : SWUnoHelper::UCB_GetFileListOfFolder( rPathArr[nPath], aFiles,
281 0 : &sExt, &aDateTimeArr );
282 0 : for( size_t nFiles = 0; nFiles < aFiles.size(); ++nFiles )
283 : {
284 0 : String* pTitle = aFiles[ nFiles ];
285 0 : ::DateTime* pDT = (::DateTime*) aDateTimeArr[ static_cast<sal_uInt16>(nFiles) ];
286 :
287 0 : String sName( pTitle->Copy( 0, pTitle->Len() - sExt.Len() ));
288 :
289 0 : aFoundGroupNames.push_back(sName);
290 0 : sName += GLOS_DELIM;
291 0 : sName += String::CreateFromInt32( static_cast<sal_uInt16>(nPath) );
292 0 : AutoTextGroup* pFound = FindGroup( sName );
293 0 : if( !pFound )
294 : {
295 0 : pFound = new AutoTextGroup;
296 0 : pFound->sName = sName;
297 0 : FillGroup( pFound, pGlossaries );
298 0 : pFound->aDateModified = *pDT;
299 :
300 0 : aGroupArr.push_back(pFound);
301 : }
302 0 : else if( pFound->aDateModified < *pDT )
303 : {
304 0 : FillGroup(pFound, pGlossaries);
305 0 : pFound->aDateModified = *pDT;
306 : }
307 :
308 : // don't need any more these pointers
309 0 : delete pTitle;
310 0 : delete pDT;
311 0 : }
312 :
313 0 : sal_uInt16 nArrCount = aGroupArr.size();
314 0 : for( sal_uInt16 i = nArrCount; i; --i)
315 : {
316 : // evtl. geloeschte Gruppen entfernen
317 0 : AutoTextGroup* pGroup = aGroupArr[i - 1];
318 : sal_uInt16 nGroupPath = (sal_uInt16)pGroup->sName.GetToken( 1,
319 0 : GLOS_DELIM).ToInt32();
320 : // nur die Gruppen werden geprueft, die fuer den
321 : // aktuellen Teilpfad registriert sind
322 0 : if( nGroupPath == static_cast<sal_uInt16>(nPath) )
323 : {
324 0 : sal_Bool bFound = sal_False;
325 0 : String sCompareGroup = pGroup->sName.GetToken(0, GLOS_DELIM);
326 0 : for(std::vector<String>::const_iterator j = aFoundGroupNames.begin(); j != aFoundGroupNames.end() && !bFound; ++j)
327 0 : bFound = (sCompareGroup == *j);
328 :
329 0 : if(!bFound)
330 : {
331 0 : aGroupArr.erase(aGroupArr.begin() + i - 1);
332 0 : delete pGroup;
333 0 : }
334 : }
335 : }
336 0 : }
337 0 : }
338 0 : }
339 :
340 0 : void SwGlossaryList::Timeout()
341 : {
342 : // nur, wenn eine SwView den Fokus hat, wird automatisch upgedated
343 0 : if(::GetActiveView())
344 0 : Update();
345 0 : }
346 :
347 0 : AutoTextGroup* SwGlossaryList::FindGroup(const String& rGroupName)
348 : {
349 0 : for(sal_uInt16 i = 0; i < aGroupArr.size(); i++)
350 : {
351 0 : AutoTextGroup* pRet = aGroupArr[i];
352 0 : if(pRet->sName == rGroupName)
353 0 : return pRet;
354 : }
355 0 : return 0;
356 : }
357 :
358 0 : void SwGlossaryList::FillGroup(AutoTextGroup* pGroup, SwGlossaries* pGlossaries)
359 : {
360 0 : SwTextBlocks* pBlock = pGlossaries->GetGroupDoc(pGroup->sName);
361 0 : pGroup->nCount = pBlock ? pBlock->GetCount() : 0;
362 0 : pGroup->sLongNames = pGroup->sShortNames = aEmptyStr;
363 0 : if(pBlock)
364 0 : pGroup->sTitle = pBlock->GetName();
365 :
366 0 : for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
367 : {
368 0 : pGroup->sLongNames += pBlock->GetLongName(j);
369 0 : pGroup->sLongNames += STRING_DELIM;
370 0 : pGroup->sShortNames += pBlock->GetShortName(j);
371 0 : pGroup->sShortNames += STRING_DELIM;
372 : }
373 0 : pGlossaries->PutGroupDoc(pBlock);
374 0 : }
375 :
376 : /********************************************************************
377 : Alle (nicht mehr als FIND_MAX_GLOS) gefunden Bausteine mit
378 : passendem Anfang zurueckgeben
379 : ********************************************************************/
380 :
381 0 : bool SwGlossaryList::HasLongName(const String& rBegin, std::vector<String> *pLongNames)
382 : {
383 0 : if(!bFilled)
384 0 : Update();
385 0 : sal_uInt16 nFound = 0;
386 0 : sal_uInt16 nCount = aGroupArr.size();
387 0 : sal_uInt16 nBeginLen = rBegin.Len();
388 0 : const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
389 :
390 0 : for(sal_uInt16 i = 0; i < nCount; i++ )
391 : {
392 0 : AutoTextGroup* pGroup = aGroupArr[i];
393 0 : for(sal_uInt16 j = 0; j < pGroup->nCount; j++)
394 : {
395 0 : String sBlock = pGroup->sLongNames.GetToken(j, STRING_DELIM);
396 0 : if( rSCmp.isEqual( sBlock.Copy(0, nBeginLen), rBegin ) &&
397 0 : nBeginLen + 1 < sBlock.Len())
398 : {
399 0 : pLongNames->push_back( sBlock );
400 0 : nFound++;
401 0 : if(FIND_MAX_GLOS == nFound)
402 : break;
403 : }
404 0 : }
405 : }
406 0 : return nFound > 0;
407 : }
408 :
409 0 : void SwGlossaryList::ClearGroups()
410 : {
411 0 : sal_uInt16 nCount = aGroupArr.size();
412 0 : for( sal_uInt16 i = 0; i < nCount; ++i )
413 0 : delete aGroupArr[ i ];
414 :
415 0 : aGroupArr.clear();
416 0 : bFilled = sal_False;
417 0 : }
418 :
419 :
420 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|