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 <SvxConfigPageHelper.hxx>
21
22 #include <com/sun/star/frame/ModuleManager.hpp>
23 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
24 #include <com/sun/star/ui/ImageType.hpp>
25 #include <com/sun/star/ui/ItemType.hpp>
26
27 #include <comphelper/random.hxx>
28 #include <comphelper/processfactory.hxx>
29 #include <svtools/imgdef.hxx>
30 #include <svtools/miscopt.hxx>
31
32 static sal_Int16 theImageType =
33 css::ui::ImageType::COLOR_NORMAL |
34 css::ui::ImageType::SIZE_DEFAULT;
35
RemoveEntry(SvxEntries * pEntries,SvxConfigEntry const * pChildEntry)36 void SvxConfigPageHelper::RemoveEntry( SvxEntries* pEntries, SvxConfigEntry const * pChildEntry )
37 {
38 SvxEntries::iterator iter = pEntries->begin();
39
40 while ( iter != pEntries->end() )
41 {
42 if ( pChildEntry == *iter )
43 {
44 pEntries->erase( iter );
45 break;
46 }
47 ++iter;
48 }
49 }
50
replaceSaveInName(const OUString & rMessage,const OUString & rSaveInName)51 OUString SvxConfigPageHelper::replaceSaveInName( const OUString& rMessage, const OUString& rSaveInName )
52 {
53 const OUString placeholder("%SAVE IN SELECTION%" );
54
55 OUString name = rMessage.replaceFirst(placeholder, rSaveInName);
56
57 return name;
58 }
59
stripHotKey(const OUString & str)60 OUString SvxConfigPageHelper::stripHotKey( const OUString& str )
61 {
62 return str.replaceFirst("~", "");
63 }
64
replaceSixteen(const OUString & str,sal_Int32 nReplacement)65 OUString SvxConfigPageHelper::replaceSixteen( const OUString& str, sal_Int32 nReplacement )
66 {
67 return str.replaceAll( OUString::number( 16 ), OUString::number( nReplacement ));
68 }
69
GetImageType()70 sal_Int16 SvxConfigPageHelper::GetImageType()
71 {
72 return theImageType;
73 }
74
InitImageType()75 void SvxConfigPageHelper::InitImageType()
76 {
77 theImageType =
78 css::ui::ImageType::COLOR_NORMAL |
79 css::ui::ImageType::SIZE_DEFAULT;
80
81 if (SvtMiscOptions().GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_LARGE)
82 {
83 theImageType |= css::ui::ImageType::SIZE_LARGE;
84 }
85 else if (SvtMiscOptions().GetCurrentSymbolsSize() == SFX_SYMBOLS_SIZE_32)
86 {
87 theImageType |= css::ui::ImageType::SIZE_32;
88 }
89 }
90
GetGraphic(const css::uno::Reference<css::ui::XImageManager> & xImageManager,const OUString & rCommandURL)91 css::uno::Reference< css::graphic::XGraphic > SvxConfigPageHelper::GetGraphic(
92 const css::uno::Reference< css::ui::XImageManager >& xImageManager,
93 const OUString& rCommandURL )
94 {
95 css::uno::Reference< css::graphic::XGraphic > result;
96
97 if ( xImageManager.is() )
98 {
99 // TODO handle large graphics
100 css::uno::Sequence< css::uno::Reference< css::graphic::XGraphic > > aGraphicSeq;
101
102 css::uno::Sequence<OUString> aImageCmdSeq { rCommandURL };
103
104 try
105 {
106 aGraphicSeq =
107 xImageManager->getImages( GetImageType(), aImageCmdSeq );
108
109 if ( aGraphicSeq.hasElements() )
110 {
111 result = aGraphicSeq[0];
112 }
113 }
114 catch ( css::uno::Exception& )
115 {
116 // will return empty XGraphic
117 }
118 }
119
120 return result;
121 }
122
123 OUString
generateCustomName(const OUString & prefix,SvxEntries * entries,sal_Int32 suffix)124 SvxConfigPageHelper::generateCustomName(
125 const OUString& prefix,
126 SvxEntries* entries,
127 sal_Int32 suffix /*= 1*/ )
128 {
129 OUString name;
130 sal_Int32 pos = 0;
131
132 // find and replace the %n placeholder in the prefix string
133 name = prefix.replaceFirst( "%n", OUString::number( suffix ), &pos );
134
135 if ( pos == -1 )
136 {
137 // no placeholder found so just append the suffix
138 name += OUString::number( suffix );
139 }
140
141 if (!entries)
142 return name;
143
144 // now check if there is an already existing entry with this name
145 bool bFoundEntry = false;
146 for (auto const& entry : *entries)
147 {
148 if ( name.equals(entry->GetName()) )
149 {
150 bFoundEntry = true;
151 break;
152 }
153 }
154
155 if (bFoundEntry)
156 {
157 // name already exists so try the next number up
158 return generateCustomName( prefix, entries, ++suffix );
159 }
160
161 return name;
162 }
163
generateCustomMenuURL(SvxEntries * entries,sal_Int32 suffix)164 OUString SvxConfigPageHelper::generateCustomMenuURL(
165 SvxEntries* entries,
166 sal_Int32 suffix /*= 1*/ )
167 {
168 OUString url = "vnd.openoffice.org:CustomMenu" + OUString::number( suffix );
169 if (!entries)
170 return url;
171
172 // now check is there is an already existing entry with this url
173 bool bFoundEntry = false;
174 for (auto const& entry : *entries)
175 {
176 if ( url.equals(entry->GetCommand()) )
177 {
178 bFoundEntry = true;
179 break;
180 }
181 }
182
183 if (bFoundEntry)
184 {
185 // url already exists so try the next number up
186 return generateCustomMenuURL( entries, ++suffix );
187 }
188
189 return url;
190 }
191
generateRandomValue()192 sal_uInt32 SvxConfigPageHelper::generateRandomValue()
193 {
194 return comphelper::rng::uniform_uint_distribution(0, std::numeric_limits<unsigned int>::max());
195 }
196
generateCustomURL(SvxEntries * entries)197 OUString SvxConfigPageHelper::generateCustomURL( SvxEntries* entries )
198 {
199 OUString url = OUStringLiteral(ITEM_TOOLBAR_URL) + CUSTOM_TOOLBAR_STR +
200 // use a random number to minimize possible clash with existing custom toolbars
201 OUString::number( generateRandomValue(), 16 );
202
203 // now check is there is an already existing entry with this url
204 bool bFoundEntry = false;
205 for (auto const& entry : *entries)
206 {
207 if ( url.equals(entry->GetCommand()) )
208 {
209 bFoundEntry = true;
210 break;
211 }
212 }
213
214 if (bFoundEntry)
215 {
216 // url already exists so try the next number up
217 return generateCustomURL( entries );
218 }
219
220 return url;
221 }
222
GetModuleName(const OUString & aModuleId)223 OUString SvxConfigPageHelper::GetModuleName( const OUString& aModuleId )
224 {
225 if ( aModuleId == "com.sun.star.text.TextDocument" ||
226 aModuleId == "com.sun.star.text.GlobalDocument" )
227 return "Writer";
228 else if ( aModuleId == "com.sun.star.text.WebDocument" )
229 return "Writer/Web";
230 else if ( aModuleId == "com.sun.star.drawing.DrawingDocument" )
231 return "Draw";
232 else if ( aModuleId == "com.sun.star.presentation.PresentationDocument" )
233 return "Impress";
234 else if ( aModuleId == "com.sun.star.sheet.SpreadsheetDocument" )
235 return "Calc";
236 else if ( aModuleId == "com.sun.star.script.BasicIDE" )
237 return "Basic";
238 else if ( aModuleId == "com.sun.star.formula.FormulaProperties" )
239 return "Math";
240 else if ( aModuleId == "com.sun.star.sdb.RelationDesign" )
241 return "Relation Design";
242 else if ( aModuleId == "com.sun.star.sdb.QueryDesign" )
243 return "Query Design";
244 else if ( aModuleId == "com.sun.star.sdb.TableDesign" )
245 return "Table Design";
246 else if ( aModuleId == "com.sun.star.sdb.DataSourceBrowser" )
247 return "Data Source Browser";
248 else if ( aModuleId == "com.sun.star.sdb.DatabaseDocument" )
249 return "Database";
250
251 return OUString();
252 }
253
GetUIModuleName(const OUString & aModuleId,const css::uno::Reference<css::frame::XModuleManager2> & rModuleManager)254 OUString SvxConfigPageHelper::GetUIModuleName(
255 const OUString& aModuleId,
256 const css::uno::Reference< css::frame::XModuleManager2 >& rModuleManager )
257 {
258 assert(rModuleManager.is());
259
260 OUString aModuleUIName;
261
262 try
263 {
264 css::uno::Any a = rModuleManager->getByName( aModuleId );
265 css::uno::Sequence< css::beans::PropertyValue > aSeq;
266
267 if ( a >>= aSeq )
268 {
269 for ( sal_Int32 i = 0; i < aSeq.getLength(); ++i )
270 {
271 if ( aSeq[i].Name == "ooSetupFactoryUIName" )
272 {
273 aSeq[i].Value >>= aModuleUIName;
274 break;
275 }
276 }
277 }
278 }
279 catch ( css::uno::RuntimeException& )
280 {
281 throw;
282 }
283 catch ( css::uno::Exception& )
284 {
285 }
286
287 if ( aModuleUIName.isEmpty() )
288 aModuleUIName = GetModuleName( aModuleId );
289
290 return aModuleUIName;
291 }
292
GetMenuItemData(const css::uno::Reference<css::container::XIndexAccess> & rItemContainer,sal_Int32 nIndex,OUString & rCommandURL,OUString & rLabel,sal_uInt16 & rType,sal_Int32 & rStyle,css::uno::Reference<css::container::XIndexAccess> & rSubMenu)293 bool SvxConfigPageHelper::GetMenuItemData(
294 const css::uno::Reference< css::container::XIndexAccess >& rItemContainer,
295 sal_Int32 nIndex,
296 OUString& rCommandURL,
297 OUString& rLabel,
298 sal_uInt16& rType,
299 sal_Int32& rStyle,
300 css::uno::Reference< css::container::XIndexAccess >& rSubMenu )
301 {
302 try
303 {
304 css::uno::Sequence< css::beans::PropertyValue > aProp;
305 if ( rItemContainer->getByIndex( nIndex ) >>= aProp )
306 {
307 for ( sal_Int32 i = 0; i < aProp.getLength(); ++i )
308 {
309 if ( aProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
310 {
311 aProp[i].Value >>= rCommandURL;
312 }
313 else if ( aProp[i].Name == ITEM_DESCRIPTOR_CONTAINER )
314 {
315 aProp[i].Value >>= rSubMenu;
316 }
317 else if ( aProp[i].Name == ITEM_DESCRIPTOR_STYLE )
318 {
319 aProp[i].Value >>= rStyle;
320 }
321 else if ( aProp[i].Name == ITEM_DESCRIPTOR_LABEL )
322 {
323 aProp[i].Value >>= rLabel;
324 }
325 else if ( aProp[i].Name == ITEM_DESCRIPTOR_TYPE )
326 {
327 aProp[i].Value >>= rType;
328 }
329 }
330
331 return true;
332 }
333 }
334 catch ( css::lang::IndexOutOfBoundsException& )
335 {
336 }
337
338 return false;
339 }
340
GetToolbarItemData(const css::uno::Reference<css::container::XIndexAccess> & rItemContainer,sal_Int32 nIndex,OUString & rCommandURL,OUString & rLabel,sal_uInt16 & rType,bool & rIsVisible,sal_Int32 & rStyle)341 bool SvxConfigPageHelper::GetToolbarItemData(
342 const css::uno::Reference< css::container::XIndexAccess >& rItemContainer,
343 sal_Int32 nIndex,
344 OUString& rCommandURL,
345 OUString& rLabel,
346 sal_uInt16& rType,
347 bool& rIsVisible,
348 sal_Int32& rStyle )
349 {
350 try
351 {
352 css::uno::Sequence< css::beans::PropertyValue > aProp;
353 if ( rItemContainer->getByIndex( nIndex ) >>= aProp )
354 {
355 for ( sal_Int32 i = 0; i < aProp.getLength(); ++i )
356 {
357 if ( aProp[i].Name == ITEM_DESCRIPTOR_COMMANDURL )
358 {
359 aProp[i].Value >>= rCommandURL;
360 }
361 else if ( aProp[i].Name == ITEM_DESCRIPTOR_STYLE )
362 {
363 aProp[i].Value >>= rStyle;
364 }
365 else if ( aProp[i].Name == ITEM_DESCRIPTOR_LABEL )
366 {
367 aProp[i].Value >>= rLabel;
368 }
369 else if ( aProp[i].Name == ITEM_DESCRIPTOR_TYPE )
370 {
371 aProp[i].Value >>= rType;
372 }
373 else if ( aProp[i].Name == ITEM_DESCRIPTOR_ISVISIBLE )
374 {
375 aProp[i].Value >>= rIsVisible;
376 }
377 }
378
379 return true;
380 }
381 }
382 catch ( css::lang::IndexOutOfBoundsException& )
383 {
384 }
385
386 return false;
387 }
388
ConvertSvxConfigEntry(const SvxConfigEntry * pEntry)389 css::uno::Sequence< css::beans::PropertyValue > SvxConfigPageHelper::ConvertSvxConfigEntry(
390 const SvxConfigEntry* pEntry )
391 {
392 css::uno::Sequence< css::beans::PropertyValue > aPropSeq( 4 );
393
394 aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL;
395 aPropSeq[0].Value <<= pEntry->GetCommand();
396
397 aPropSeq[1].Name = ITEM_DESCRIPTOR_TYPE;
398 aPropSeq[1].Value <<= css::ui::ItemType::DEFAULT;
399
400 // If the name has not been changed, then the label can be stored
401 // as an empty string.
402 // It will be initialised again later using the command to label map.
403 aPropSeq[2].Name = ITEM_DESCRIPTOR_LABEL;
404 if ( !pEntry->HasChangedName() && !pEntry->GetCommand().isEmpty() )
405 {
406 aPropSeq[2].Value <<= OUString();
407 }
408 else
409 {
410 aPropSeq[2].Value <<= pEntry->GetName();
411 }
412
413 aPropSeq[3].Name = ITEM_DESCRIPTOR_STYLE;
414 aPropSeq[3].Value <<= static_cast<sal_Int16>(pEntry->GetStyle());
415
416 return aPropSeq;
417 }
418
ConvertToolbarEntry(const SvxConfigEntry * pEntry)419 css::uno::Sequence< css::beans::PropertyValue > SvxConfigPageHelper::ConvertToolbarEntry(
420 const SvxConfigEntry* pEntry )
421 {
422 css::uno::Sequence< css::beans::PropertyValue > aPropSeq( 5 );
423
424 aPropSeq[0].Name = ITEM_DESCRIPTOR_COMMANDURL;
425 aPropSeq[0].Value <<= pEntry->GetCommand();
426
427 aPropSeq[1].Name = ITEM_DESCRIPTOR_TYPE;
428 aPropSeq[1].Value <<= css::ui::ItemType::DEFAULT;
429
430 // If the name has not been changed, then the label can be stored
431 // as an empty string.
432 // It will be initialised again later using the command to label map.
433 aPropSeq[2].Name = ITEM_DESCRIPTOR_LABEL;
434 if ( !pEntry->HasChangedName() && !pEntry->GetCommand().isEmpty() )
435 {
436 aPropSeq[2].Value <<= OUString();
437 }
438 else
439 {
440 aPropSeq[2].Value <<= pEntry->GetName();
441 }
442
443 aPropSeq[3].Name = ITEM_DESCRIPTOR_ISVISIBLE;
444 aPropSeq[3].Value <<= pEntry->IsVisible();
445
446 aPropSeq[4].Name = ITEM_DESCRIPTOR_STYLE;
447 aPropSeq[4].Value <<= static_cast<sal_Int16>(pEntry->GetStyle());
448
449 return aPropSeq;
450 }
451
EntrySort(SvxConfigEntry const * a,SvxConfigEntry const * b)452 bool SvxConfigPageHelper::EntrySort( SvxConfigEntry const * a, SvxConfigEntry const * b )
453 {
454 return a->GetName().compareTo( b->GetName() ) < 0;
455 }
456
SvxConfigEntryModified(SvxConfigEntry const * pEntry)457 bool SvxConfigPageHelper::SvxConfigEntryModified( SvxConfigEntry const * pEntry )
458 {
459 SvxEntries* pEntries = pEntry->GetEntries();
460 if ( !pEntries )
461 return false;
462
463 for ( const auto& entry : *pEntries )
464 {
465 if ( entry->IsModified() || SvxConfigEntryModified( entry ) )
466 return true;
467 }
468 return false;
469 }
470
471 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
472