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 <comphelper/string.hxx>
21 : #include <tools/urlobj.hxx>
22 : #include <tools/stream.hxx>
23 : #include <vcl/msgbox.hxx>
24 : #include <vcl/help.hxx>
25 : #include <unotools/transliterationwrapper.hxx>
26 : #include <unotools/tempfile.hxx>
27 : #include <unotools/pathoptions.hxx>
28 : #include "svtools/treelistentry.hxx"
29 :
30 : #include <swtypes.hxx>
31 : #include <glosbib.hxx>
32 : #include <gloshdl.hxx>
33 : #include <actctrl.hxx>
34 : #include <glossary.hxx>
35 : #include <glosdoc.hxx>
36 : #include <swunohelper.hxx>
37 :
38 : #include <glosbib.hrc>
39 : #include <misc.hrc>
40 : #include <helpid.h>
41 :
42 :
43 : #define PATH_CASE_SENSITIVE 0x01
44 : #define PATH_READONLY 0x02
45 :
46 : #define RENAME_TOKEN_DELIM (sal_Unicode)1
47 :
48 0 : SwGlossaryGroupDlg::SwGlossaryGroupDlg(Window * pParent,
49 : std::vector<String> const& rPathArr,
50 : SwGlossaryHdl *pHdl) :
51 : SvxStandardDialog(pParent, SW_RES(DLG_BIB_BASE)),
52 : aBibFT( this, SW_RES(FT_BIB)),
53 : aNameED( this, SW_RES(ED_NAME)),
54 : aPathFT( this, SW_RES(FT_PATH)),
55 : aPathLB( this, SW_RES(LB_PATH)),
56 : aSelectFT( this, SW_RES(FT_SELECT)),
57 : aGroupTLB( this, SW_RES(TLB_GROUPS)),
58 :
59 : aOkPB( this, SW_RES(BT_OK)),
60 : aCancelPB( this, SW_RES(BT_CANCEL)),
61 : aHelpPB( this, SW_RES(BT_HELP)),
62 : aNewPB( this, SW_RES(PB_NEW)),
63 : aDelPB( this, SW_RES(PB_DELETE)),
64 : aRenamePB( this, SW_RES(PB_RENAME)),
65 :
66 0 : pGlosHdl(pHdl)
67 : {
68 0 : FreeResource();
69 :
70 : long nTabs[] =
71 : { 2, // Number of Tabs
72 : 0, 160
73 0 : };
74 :
75 0 : aGroupTLB.SetHelpId(HID_GLOS_GROUP_TREE);
76 0 : aGroupTLB.SetTabs( &nTabs[0], MAP_APPFONT );
77 0 : aGroupTLB.SetStyle(aGroupTLB.GetStyle()|WB_HSCROLL|WB_CLIPCHILDREN|WB_SORT);
78 0 : aGroupTLB.SetSelectHdl(LINK(this, SwGlossaryGroupDlg, SelectHdl));
79 0 : aGroupTLB.GetModel()->SetSortMode(SortAscending);
80 0 : aNewPB.SetClickHdl(LINK(this, SwGlossaryGroupDlg, NewHdl));
81 0 : aDelPB.SetClickHdl(LINK(this, SwGlossaryGroupDlg, DeleteHdl));
82 0 : aNameED.SetModifyHdl(LINK(this, SwGlossaryGroupDlg, ModifyHdl));
83 0 : aPathLB.SetSelectHdl(LINK(this, SwGlossaryGroupDlg, ModifyHdl));
84 0 : aRenamePB.SetClickHdl(LINK(this, SwGlossaryGroupDlg, RenameHdl));
85 :
86 0 : for (size_t i = 0; i < rPathArr.size(); ++i)
87 : {
88 0 : String sPath(rPathArr[i]);
89 0 : INetURLObject aTempURL(sPath);
90 0 : sPath = aTempURL.GetMainURL(INetURLObject::DECODE_WITH_CHARSET );
91 0 : aPathLB.InsertEntry(sPath);
92 0 : sal_uLong nCaseReadonly = 0;
93 0 : utl::TempFile aTempFile(&sPath);
94 0 : aTempFile.EnableKillingFile();
95 0 : if(!aTempFile.IsValid())
96 0 : nCaseReadonly |= PATH_READONLY;
97 0 : else if( SWUnoHelper::UCB_IsCaseSensitiveFileName( aTempFile.GetURL()))
98 0 : nCaseReadonly |= PATH_CASE_SENSITIVE;
99 0 : aPathLB.SetEntryData(i, (void*)nCaseReadonly);
100 0 : }
101 0 : aPathLB.SelectEntryPos(0);
102 0 : aPathLB.Enable(sal_True);
103 :
104 0 : const sal_uInt16 nCount = pHdl->GetGroupCnt();
105 0 : for( sal_uInt16 i = 0; i < nCount; ++i)
106 : {
107 0 : String sTitle;
108 0 : String sGroup = pHdl->GetGroupName(i, &sTitle);
109 0 : if(!sGroup.Len())
110 0 : continue;
111 0 : GlosBibUserData* pData = new GlosBibUserData;
112 0 : pData->sGroupName = sGroup;
113 0 : pData->sGroupTitle = sTitle;
114 0 : String sTemp(sTitle);
115 0 : sTemp += '\t';
116 0 : pData->sPath = aPathLB.GetEntry((sal_uInt16)sGroup.GetToken(1, GLOS_DELIM).ToInt32());
117 0 : sTemp += pData->sPath;
118 0 : SvTreeListEntry* pEntry = aGroupTLB.InsertEntry(sTemp);
119 0 : pEntry->SetUserData(pData);
120 :
121 0 : }
122 0 : aGroupTLB.GetModel()->Resort();
123 0 : }
124 :
125 0 : SwGlossaryGroupDlg::~SwGlossaryGroupDlg()
126 : {
127 0 : }
128 :
129 0 : void SwGlossaryGroupDlg::Apply()
130 : {
131 0 : if(aNewPB.IsEnabled())
132 0 : NewHdl(&aNewPB);
133 :
134 0 : String aActGroup = SwGlossaryDlg::GetCurrGroup();
135 :
136 0 : for (OUVector_t::const_iterator it(m_RemovedArr.begin());
137 0 : it != m_RemovedArr.end(); ++it)
138 : {
139 : const String sDelGroup =
140 0 : ::comphelper::string::getToken(*it, 0, '\t');
141 0 : if( sDelGroup == aActGroup )
142 : {
143 : //when the current group is deleted, the current group has to be relocated
144 0 : if(aGroupTLB.GetEntryCount())
145 : {
146 0 : SvTreeListEntry* pFirst = aGroupTLB.First();
147 0 : GlosBibUserData* pUserData = (GlosBibUserData*)pFirst->GetUserData();
148 0 : pGlosHdl->SetCurGroup(pUserData->sGroupName);
149 : }
150 : }
151 0 : String sMsg(SW_RES(STR_QUERY_DELETE_GROUP1));
152 0 : String sTitle( ::comphelper::string::getToken(*it, 1, '\t') );
153 0 : if(sTitle.Len())
154 0 : sMsg += sTitle;
155 : else
156 0 : sDelGroup.GetToken(1, GLOS_DELIM);
157 0 : sMsg += SW_RESSTR(STR_QUERY_DELETE_GROUP2);
158 0 : QueryBox aQuery(this->GetParent(), WB_YES_NO|WB_DEF_NO, sMsg );
159 0 : if(RET_YES == aQuery.Execute())
160 0 : pGlosHdl->DelGroup( sDelGroup );
161 0 : }
162 :
163 : //don't rename before there was one
164 0 : for (OUVector_t::const_iterator it(m_RenamedArr.begin());
165 0 : it != m_RenamedArr.end(); ++it)
166 : {
167 : ::rtl::OUString const sOld(
168 0 : ::comphelper::string::getToken(*it, 0, RENAME_TOKEN_DELIM));
169 : String sNew(
170 0 : ::comphelper::string::getToken(*it, 1, RENAME_TOKEN_DELIM));
171 : ::rtl::OUString const sTitle(
172 0 : ::comphelper::string::getToken(*it, 2, RENAME_TOKEN_DELIM));
173 0 : pGlosHdl->RenameGroup(sOld, sNew, sTitle);
174 0 : if (it == m_RenamedArr.begin())
175 : {
176 0 : sCreatedGroup = sNew;
177 : }
178 0 : }
179 0 : for (OUVector_t::const_iterator it(m_InsertedArr.begin());
180 0 : it != m_InsertedArr.end(); ++it)
181 : {
182 0 : String sNewGroup = *it;
183 0 : String sNewTitle = sNewGroup.GetToken(0, GLOS_DELIM);
184 0 : if( sNewGroup != aActGroup )
185 : {
186 0 : pGlosHdl->NewGroup(sNewGroup, sNewTitle);
187 0 : if(!sCreatedGroup.Len())
188 0 : sCreatedGroup = sNewGroup;
189 : }
190 0 : }
191 0 : }
192 :
193 0 : IMPL_LINK( SwGlossaryGroupDlg, SelectHdl, SvTabListBox*, EMPTYARG )
194 : {
195 0 : aNewPB.Enable(sal_False);
196 0 : SvTreeListEntry* pFirstEntry = aGroupTLB.FirstSelected();
197 0 : if(pFirstEntry)
198 : {
199 0 : GlosBibUserData* pUserData = (GlosBibUserData*)pFirstEntry->GetUserData();
200 0 : String sEntry(pUserData->sGroupName);
201 0 : String sName(aNameED.GetText());
202 0 : sal_Bool bExists = sal_False;
203 0 : sal_uLong nPos = aGroupTLB.GetEntryPos(sName, 0);
204 0 : if( 0xffffffff > nPos)
205 : {
206 0 : SvTreeListEntry* pEntry = aGroupTLB.GetEntry(nPos);
207 0 : GlosBibUserData* pFoundData = (GlosBibUserData*)pEntry->GetUserData();
208 0 : String sGroup = pFoundData->sGroupName;
209 0 : bExists = sGroup == sEntry;
210 : }
211 :
212 0 : aRenamePB.Enable(!bExists && sName.Len());
213 0 : aDelPB.Enable(IsDeleteAllowed(sEntry));
214 : }
215 0 : return 0;
216 : }
217 :
218 0 : IMPL_LINK_NOARG(SwGlossaryGroupDlg, NewHdl)
219 : {
220 0 : String sGroup(aNameED.GetText());
221 0 : sGroup += GLOS_DELIM;
222 0 : sGroup += String::CreateFromInt32(aPathLB.GetSelectEntryPos());
223 : OSL_ENSURE(!pGlosHdl->FindGroupName(sGroup), "group already available!");
224 0 : m_InsertedArr.push_back(sGroup);
225 0 : String sTemp(aNameED.GetText());
226 0 : sTemp += '\t';
227 0 : sTemp += aPathLB.GetSelectEntry();
228 0 : SvTreeListEntry* pEntry = aGroupTLB.InsertEntry(sTemp);
229 0 : GlosBibUserData* pData = new GlosBibUserData;
230 0 : pData->sPath = aPathLB.GetSelectEntry();
231 0 : pData->sGroupName = sGroup;
232 0 : pData->sGroupTitle = aNameED.GetText();
233 0 : pEntry->SetUserData(pData);
234 0 : aGroupTLB.Select(pEntry);
235 0 : aGroupTLB.MakeVisible(pEntry);
236 0 : aGroupTLB.GetModel()->Resort();
237 :
238 0 : return 0;
239 : }
240 :
241 0 : IMPL_LINK( SwGlossaryGroupDlg, DeleteHdl, Button*, pButton )
242 : {
243 0 : SvTreeListEntry* pEntry = aGroupTLB.FirstSelected();
244 0 : if(!pEntry)
245 : {
246 0 : pButton->Enable(sal_False);
247 0 : return 0;
248 : }
249 0 : GlosBibUserData* pUserData = (GlosBibUserData*)pEntry->GetUserData();
250 0 : ::rtl::OUString const sEntry(pUserData->sGroupName);
251 : // if the name to be deleted is among the new ones - get rid of it
252 0 : sal_Bool bDelete = sal_True;
253 0 : for (OUVector_t::iterator it(m_InsertedArr.begin());
254 0 : it != m_InsertedArr.end(); ++it)
255 : {
256 0 : if (*it == sEntry)
257 : {
258 0 : m_InsertedArr.erase(it);
259 0 : bDelete = sal_False;
260 0 : break;
261 : }
262 :
263 : }
264 : // it should probably be renamed?
265 0 : if(bDelete)
266 : {
267 0 : for (OUVector_t::iterator it(m_RenamedArr.begin());
268 0 : it != m_RenamedArr.end(); ++it)
269 : {
270 0 : if (::comphelper::string::getToken(*it, 0, RENAME_TOKEN_DELIM)
271 0 : == sEntry)
272 : {
273 0 : m_RenamedArr.erase(it);
274 0 : bDelete = sal_False;
275 0 : break;
276 : }
277 : }
278 : }
279 0 : if(bDelete)
280 : {
281 0 : String sGroupEntry(pUserData->sGroupName);
282 0 : sGroupEntry += '\t';
283 0 : sGroupEntry += pUserData->sGroupTitle;
284 0 : m_RemovedArr.push_back(sGroupEntry);
285 : }
286 0 : delete pUserData;
287 0 : aGroupTLB.GetModel()->Remove(pEntry);
288 0 : if(!aGroupTLB.First())
289 0 : pButton->Enable(sal_False);
290 : //the content must be deleted - otherwise the new handler would be called in Apply()
291 0 : aNameED.SetText(aEmptyStr);
292 0 : return 0;
293 : }
294 :
295 0 : IMPL_LINK_NOARG(SwGlossaryGroupDlg, RenameHdl)
296 : {
297 0 : SvTreeListEntry* pEntry = aGroupTLB.FirstSelected();
298 0 : GlosBibUserData* pUserData = (GlosBibUserData*)pEntry->GetUserData();
299 0 : String sEntry(pUserData->sGroupName);
300 :
301 0 : String sNewName(aNameED.GetText());
302 0 : String sNewTitle(sNewName);
303 :
304 0 : sNewName += GLOS_DELIM;
305 0 : sNewName += String::CreateFromInt32(aPathLB.GetSelectEntryPos());
306 : OSL_ENSURE(!pGlosHdl->FindGroupName(sNewName), "group already available!");
307 :
308 : // if the name to be renamed is among the new ones - replace
309 0 : sal_Bool bDone = sal_False;
310 0 : for (OUVector_t::iterator it(m_InsertedArr.begin());
311 0 : it != m_InsertedArr.end(); ++it)
312 : {
313 0 : if (String(*it) == sEntry)
314 : {
315 0 : m_InsertedArr.erase(it);
316 0 : m_InsertedArr.push_back(sNewName);
317 0 : bDone = sal_True;
318 0 : break;
319 : }
320 : }
321 0 : if(!bDone)
322 : {
323 0 : sEntry += RENAME_TOKEN_DELIM;
324 0 : sEntry += sNewName;
325 0 : sEntry += RENAME_TOKEN_DELIM;
326 0 : sEntry += sNewTitle;
327 0 : m_RenamedArr.push_back(sEntry);
328 : }
329 0 : delete (GlosBibUserData*)pEntry->GetUserData();
330 0 : aGroupTLB.GetModel()->Remove(pEntry);
331 0 : String sTemp(aNameED.GetText());
332 0 : sTemp += '\t';
333 0 : sTemp += aPathLB.GetSelectEntry();
334 0 : pEntry = aGroupTLB.InsertEntry(sTemp);
335 0 : GlosBibUserData* pData = new GlosBibUserData;
336 0 : pData->sPath = aPathLB.GetSelectEntry();
337 0 : pData->sGroupName = sNewName;
338 0 : pData->sGroupTitle = sNewTitle;
339 0 : pEntry->SetUserData(pData);
340 0 : aGroupTLB.Select(pEntry);
341 0 : aGroupTLB.MakeVisible(pEntry);
342 0 : aGroupTLB.GetModel()->Resort();
343 0 : return 0;
344 : }
345 :
346 0 : IMPL_LINK_NOARG(SwGlossaryGroupDlg, ModifyHdl)
347 : {
348 0 : String sEntry(aNameED.GetText());
349 0 : sal_Bool bEnableNew = sal_True;
350 0 : sal_Bool bEnableDel = sal_False;
351 : sal_uLong nCaseReadonly =
352 0 : (sal_uLong)aPathLB.GetEntryData(aPathLB.GetSelectEntryPos());
353 0 : sal_Bool bDirReadonly = 0 != (nCaseReadonly&PATH_READONLY);
354 :
355 0 : if(!sEntry.Len() || bDirReadonly)
356 0 : bEnableNew = sal_False;
357 0 : else if(sEntry.Len())
358 : {
359 0 : sal_uLong nPos = aGroupTLB.GetEntryPos(sEntry, 0);
360 : //if it's not case sensitive you have to search for yourself
361 0 : if( 0xffffffff == nPos)
362 : {
363 0 : const ::utl::TransliterationWrapper& rSCmp = GetAppCmpStrIgnore();
364 0 : for(sal_uInt16 i = 0; i < aGroupTLB.GetEntryCount(); i++)
365 : {
366 0 : String sTemp = aGroupTLB.GetEntryText( i, 0 );
367 : nCaseReadonly = (sal_uLong)aPathLB.GetEntryData(
368 0 : aPathLB.GetEntryPos(aGroupTLB.GetEntryText(i,1)));
369 0 : sal_Bool bCase = 0 != (nCaseReadonly & PATH_CASE_SENSITIVE);
370 :
371 0 : if( !bCase && rSCmp.isEqual( sTemp, sEntry ))
372 : {
373 0 : nPos = i;
374 : break;
375 : }
376 0 : }
377 : }
378 0 : if( 0xffffffff > nPos)
379 : {
380 0 : bEnableNew = sal_False;
381 0 : aGroupTLB.Select(aGroupTLB.GetEntry( nPos ));
382 0 : aGroupTLB.MakeVisible(aGroupTLB.GetEntry( nPos ));
383 : }
384 : }
385 0 : SvTreeListEntry* pEntry = aGroupTLB.FirstSelected();
386 0 : if(pEntry)
387 : {
388 0 : GlosBibUserData* pUserData = (GlosBibUserData*)pEntry->GetUserData();
389 0 : bEnableDel = IsDeleteAllowed(pUserData->sGroupName);
390 : }
391 :
392 0 : aDelPB.Enable(bEnableDel);
393 0 : aNewPB.Enable(bEnableNew);
394 0 : aRenamePB.Enable(bEnableNew && pEntry);
395 0 : return 0;
396 : }
397 :
398 0 : sal_Bool SwGlossaryGroupDlg::IsDeleteAllowed(const String &rGroup)
399 : {
400 0 : sal_Bool bDel = (!pGlosHdl->IsReadOnly(&rGroup));
401 :
402 : // OM: if the name is among the new region name, it is deletable
403 : // as well! Because for non existing region names ReadOnly issues
404 : // sal_True.
405 :
406 0 : for (OUVector_t::const_iterator it(m_InsertedArr.begin());
407 0 : it != m_InsertedArr.end(); ++it)
408 : {
409 0 : if (String(*it) == rGroup)
410 : {
411 0 : bDel = sal_True;
412 0 : break;
413 : }
414 : }
415 :
416 0 : return bDel;
417 : }
418 :
419 0 : void FEdit::KeyInput( const KeyEvent& rKEvent )
420 : {
421 0 : KeyCode aCode = rKEvent.GetKeyCode();
422 0 : if( KEYGROUP_CURSOR == aCode.GetGroup() ||
423 0 : ( KEYGROUP_MISC == aCode.GetGroup() &&
424 0 : KEY_DELETE >= aCode.GetCode() ) ||
425 0 : SVT_SEARCHPATH_DELIMITER != rKEvent.GetCharCode() )
426 0 : Edit::KeyInput( rKEvent );
427 0 : }
428 :
429 0 : void SwGlossaryGroupTLB::RequestHelp( const HelpEvent& rHEvt )
430 : {
431 0 : Point aPos( ScreenToOutputPixel( rHEvt.GetMousePosPixel() ));
432 0 : SvTreeListEntry* pEntry = GetEntry( aPos );
433 0 : if(pEntry)
434 : {
435 : SvLBoxTab* pTab;
436 0 : SvLBoxItem* pItem = GetItem( pEntry, aPos.X(), &pTab );
437 0 : if(pItem)
438 : {
439 0 : aPos = GetEntryPosition( pEntry );
440 0 : Size aSize(pItem->GetSize( this, pEntry ));
441 0 : aPos.X() = GetTabPos( pEntry, pTab );
442 :
443 0 : if((aPos.X() + aSize.Width()) > GetSizePixel().Width())
444 0 : aSize.Width() = GetSizePixel().Width() - aPos.X();
445 0 : aPos = OutputToScreenPixel(aPos);
446 0 : Rectangle aItemRect( aPos, aSize );
447 0 : String sMsg;
448 0 : GlosBibUserData* pData = (GlosBibUserData*)pEntry->GetUserData();
449 0 : sMsg = pData->sPath;
450 0 : sMsg += INET_PATH_TOKEN;
451 0 : sMsg += pData->sGroupName.GetToken(0, GLOS_DELIM);
452 0 : sMsg += SwGlossaries::GetExtension();
453 :
454 : Help::ShowQuickHelp( this, aItemRect, sMsg,
455 0 : QUICKHELP_LEFT|QUICKHELP_VCENTER );
456 : }
457 : }
458 0 : }
459 :
460 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|