LibreOffice Module svx (master) 1
SmartTagMgr.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// SMARTTAGS
21
22#include <svx/SmartTagMgr.hxx>
23
24#include <vcl/svapp.hxx>
25#include <com/sun/star/smarttags/XSmartTagRecognizer.hpp>
26#include <com/sun/star/smarttags/XRangeBasedSmartTagRecognizer.hpp>
27#include <com/sun/star/smarttags/XSmartTagAction.hpp>
28#include <com/sun/star/deployment/ExtensionManager.hpp>
29#include <com/sun/star/smarttags/SmartTagRecognizerMode.hpp>
30#include <com/sun/star/i18n/BreakIterator.hpp>
31#include <com/sun/star/lang/XMultiServiceFactory.hpp>
32#include <com/sun/star/lang/XSingleComponentFactory.hpp>
33#include <com/sun/star/lang/XServiceInfo.hpp>
34#include <com/sun/star/configuration/theDefaultProvider.hpp>
35#include <com/sun/star/container/XContentEnumerationAccess.hpp>
36#include <com/sun/star/beans/XPropertySet.hpp>
37#include <com/sun/star/beans/PropertyValue.hpp>
38#include <com/sun/star/util/XChangesBatch.hpp>
39#include <com/sun/star/util/XChangesNotifier.hpp>
42#include <rtl/ustring.hxx>
43
44using namespace com::sun::star;
45using namespace com::sun::star::uno;
46using namespace com::sun::star::i18n;
47
48
49SmartTagMgr::SmartTagMgr( const OUString& rApplicationName )
50 : maApplicationName( rApplicationName ),
52 mbLabelTextWithSmartTags(true)
53{
54}
55
57{
58}
59
60void SmartTagMgr::Init( std::u16string_view rConfigurationGroupName )
61{
62 PrepareConfiguration( rConfigurationGroupName );
63 ReadConfiguration( true, true );
66}
67
70void SmartTagMgr::RecognizeString( const OUString& rText,
71 const Reference< text::XTextMarkup >& xMarkup,
72 const Reference< frame::XController >& xController,
73 const lang::Locale& rLocale,
74 sal_uInt32 nStart, sal_uInt32 nLen ) const
75{
77 {
78 // if all smart tag types supported by this recognizer have been
79 // disabled, we do not have to call the recognizer:
80 bool bCallRecognizer = false;
81 const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount();
82 for ( sal_uInt32 j = 0; j < nSmartTagCount && !bCallRecognizer; ++j )
83 {
84 const OUString aSmartTagName = xRecognizer->getSmartTagName(j);
85 if ( IsSmartTagTypeEnabled( aSmartTagName ) )
86 bCallRecognizer = true;
87 }
88
89 if ( bCallRecognizer )
90 {
91 // get the break iterator
92 if ( !mxBreakIter.is() )
93 {
94 mxBreakIter.set( BreakIterator::create(mxContext) );
95 }
96 xRecognizer->recognize( rText, nStart, nLen,
97 smarttags::SmartTagRecognizerMode_PARAGRAPH,
98 rLocale, xMarkup, maApplicationName, xController,
100 }
101 }
102}
103
105 const Reference< text::XTextMarkup >& xMarkup,
106 const Reference< frame::XController >& xController) const
107{
109 {
110 Reference< smarttags::XRangeBasedSmartTagRecognizer > xRangeBasedRecognizer( xRecognizer, UNO_QUERY);
111
112 if (!xRangeBasedRecognizer.is()) continue;
113
114 // if all smart tag types supported by this recognizer have been
115 // disabled, we do not have to call the recognizer:
116 bool bCallRecognizer = false;
117 const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount();
118 for ( sal_uInt32 j = 0; j < nSmartTagCount && !bCallRecognizer; ++j )
119 {
120 const OUString aSmartTagName = xRecognizer->getSmartTagName(j);
121 if ( IsSmartTagTypeEnabled( aSmartTagName ) )
122 bCallRecognizer = true;
123 }
124
125 if ( bCallRecognizer )
126 {
127 xRangeBasedRecognizer->recognizeTextRange( xRange,
128 smarttags::SmartTagRecognizerMode_PARAGRAPH,
130 }
131 }
132
133}
134
135void SmartTagMgr::GetActionSequences( std::vector< OUString >& rSmartTagTypes,
136 Sequence < Sequence< Reference< smarttags::XSmartTagAction > > >& rActionComponentsSequence,
137 Sequence < Sequence< sal_Int32 > >& rActionIndicesSequence ) const
138{
139 rActionComponentsSequence.realloc( rSmartTagTypes.size() );
140 auto pActionComponentsSequence = rActionComponentsSequence.getArray();
141 rActionIndicesSequence.realloc( rSmartTagTypes.size() );
142 auto pActionIndicesSequence = rActionIndicesSequence.getArray();
143
144 for ( size_t j = 0; j < rSmartTagTypes.size(); ++j )
145 {
146 const OUString& rSmartTagType = rSmartTagTypes[j];
147
148 const sal_Int32 nNumberOfActionRefs = maSmartTagMap.count( rSmartTagType );
149
150 Sequence< Reference< smarttags::XSmartTagAction > > aActions( nNumberOfActionRefs );
151 auto aActionsRange = asNonConstRange(aActions);
152 Sequence< sal_Int32 > aIndices( nNumberOfActionRefs );
153 auto aIndicesRange = asNonConstRange(aIndices);
154
155 sal_uInt16 i = 0;
156 auto iters = maSmartTagMap.equal_range( rSmartTagType );
157
158 for ( auto aActionsIter = iters.first; aActionsIter != iters.second; ++aActionsIter )
159 {
160 aActionsRange[ i ] = (*aActionsIter).second.mxSmartTagAction;
161 aIndicesRange[ i++ ] = (*aActionsIter).second.mnSmartTagIndex;
162 }
163
164 pActionComponentsSequence[ j ] = aActions;
165 pActionIndicesSequence[ j ] = aIndices;
166 }
167}
168
171OUString SmartTagMgr::GetSmartTagCaption( const OUString& rSmartTagType, const css::lang::Locale& rLocale ) const
172{
173 OUString aRet;
174
175 auto aLower = maSmartTagMap.find( rSmartTagType );
176
177 if ( aLower != maSmartTagMap.end() )
178 {
179 const ActionReference& rActionRef = (*aLower).second;
181
182 if ( xAction.is() )
183 {
184 const sal_Int32 nSmartTagIndex = rActionRef.mnSmartTagIndex;
185 aRet = xAction->getSmartTagCaption( nSmartTagIndex, rLocale );
186 }
187 }
188
189 return aRet;
190}
191
192
195bool SmartTagMgr::IsSmartTagTypeEnabled( const OUString& rSmartTagType ) const
196{
197 return maDisabledSmartTagTypes.end() == maDisabledSmartTagTypes.find( rSmartTagType );
198}
199
202void SmartTagMgr::WriteConfiguration( const bool* pIsLabelTextWithSmartTags,
203 const std::vector< OUString >* pDisabledTypes ) const
204{
205 if ( !mxConfigurationSettings.is() )
206 return;
207
208 bool bCommit = false;
209
210 if ( pIsLabelTextWithSmartTags )
211 {
212 const Any aEnabled( *pIsLabelTextWithSmartTags );
213
214 try
215 {
216 mxConfigurationSettings->setPropertyValue( "RecognizeSmartTags", aEnabled );
217 bCommit = true;
218 }
219 catch ( css::uno::Exception& )
220 {
221 }
222 }
223
224 if ( pDisabledTypes )
225 {
227
228 const Any aNewTypes( aTypes );
229
230 try
231 {
232 mxConfigurationSettings->setPropertyValue( "ExcludedSmartTagTypes", aNewTypes );
233 bCommit = true;
234 }
235 catch ( css::uno::Exception& )
236 {
237 }
238 }
239
240 if ( bCommit )
241 {
242 try
243 {
244 Reference< util::XChangesBatch >( mxConfigurationSettings, UNO_QUERY_THROW )->commitChanges();
245 }
246 catch ( css::uno::Exception& )
247 {
248 }
249 }
250}
251
252// css::util::XModifyListener
253void SmartTagMgr::modified( const lang::EventObject& )
254{
255 SolarMutexGuard aGuard;
256
257 maRecognizerList.clear();
258 maActionList.clear();
259 maSmartTagMap.clear();
260
262}
263
264// css::lang::XEventListener
265void SmartTagMgr::disposing( const lang::EventObject& rEvent )
266{
267 SolarMutexGuard aGuard;
268
269 uno::Reference< frame::XModel > xModel( rEvent.Source, uno::UNO_QUERY );
270 uno::Reference< util::XModifyBroadcaster > xMB(xModel, uno::UNO_QUERY);
271 uno::Reference< util::XChangesNotifier > xCN(xModel, uno::UNO_QUERY);
272
273 try
274 {
275 if( xMB.is() )
276 {
277 uno::Reference< util::XModifyListener > xListener( this );
278 xMB->removeModifyListener( xListener );
279 }
280 else if ( xCN.is() )
281 {
282 uno::Reference< util::XChangesListener > xListener( this );
283 xCN->removeChangesListener( xListener );
284 }
285 }
286 catch(Exception& )
287 {
288 }
289}
290
291// css::util::XChangesListener
292void SmartTagMgr::changesOccurred( const util::ChangesEvent& rEvent )
293{
294 SolarMutexGuard aGuard;
295
296 bool bExcludedTypes = false;
297 bool bRecognize = false;
298
299 for( const util::ElementChange& rElementChange : rEvent.Changes)
300 {
301 OUString sTemp;
302 rElementChange.Accessor >>= sTemp;
303
304 if ( sTemp == "ExcludedSmartTagTypes" )
305 bExcludedTypes = true;
306 else if ( sTemp == "RecognizeSmartTags" )
307 bRecognize = true;
308 }
309
310 ReadConfiguration( bExcludedTypes, bRecognize );
311}
312
314{
315 Reference< container::XContentEnumerationAccess > rContent( mxContext->getServiceManager(), UNO_QUERY_THROW );
316
317 // load recognizers: No recognizers -> nothing to do.
318 Reference < container::XEnumeration > rEnum = rContent->createContentEnumeration( "com.sun.star.smarttags.SmartTagRecognizer");
319 if ( !rEnum.is() || !rEnum->hasMoreElements() )
320 return;
321
322 // iterate over all implementations of the smart tag recognizer service:
323 while( rEnum->hasMoreElements())
324 {
325 const Any a = rEnum->nextElement();
328
329 if (a >>= xsInfo)
330 xSCF.set(xsInfo, UNO_QUERY);
331 else
332 continue;
333
335 createInstanceWithContext(mxContext), UNO_QUERY );
336
337 if (!xLib.is())
338 continue;
339
340 xLib->initialize( Sequence< Any >() );
341 maRecognizerList.push_back(xLib);
342 }
343
344 // load actions: No actions -> nothing to do.
345 rEnum = rContent->createContentEnumeration( "com.sun.star.smarttags.SmartTagAction");
346 if ( !rEnum.is() )
347 return;
348
349 // iterate over all implementations of the smart tag action service:
350 while( rEnum->hasMoreElements())
351 {
352 const Any a = rEnum->nextElement();
355
356 if (a >>= xsInfo)
357 xSCF.set(xsInfo, UNO_QUERY);
358 else
359 continue;
360
362 createInstanceWithContext(mxContext), UNO_QUERY );
363
364 if (!xLib.is())
365 continue;
366
367 xLib->initialize( Sequence< Any >() );
368 maActionList.push_back(xLib);
369 }
370
372
373}
374
375void SmartTagMgr::PrepareConfiguration( std::u16string_view rConfigurationGroupName )
376{
377 Any aAny(
378 OUString::Concat("/org.openoffice.Office.Common/SmartTags/") + rConfigurationGroupName );
379 beans::PropertyValue aPathArgument;
380 aPathArgument.Name = "nodepath";
381 aPathArgument.Value = aAny;
382 Sequence< Any > aArguments{ Any(aPathArgument) };
383 Reference< lang::XMultiServiceFactory > xConfProv = configuration::theDefaultProvider::get( mxContext );
384
385 // try to get read-write access to configuration:
386 Reference< XInterface > xConfigurationAccess;
387 try
388 {
389 xConfigurationAccess = xConfProv->createInstanceWithArguments(
390 "com.sun.star.configuration.ConfigurationUpdateAccess", aArguments );
391 }
392 catch ( uno::Exception& )
393 {
394 }
395
396 // fallback: try read-only access to configuration:
397 if ( !xConfigurationAccess.is() )
398 {
399 try
400 {
401 xConfigurationAccess = xConfProv->createInstanceWithArguments(
402 "com.sun.star.configuration.ConfigurationAccess", aArguments );
403 }
404 catch ( uno::Exception& )
405 {
406 }
407 }
408
409 if ( xConfigurationAccess.is() )
410 {
411 mxConfigurationSettings.set( xConfigurationAccess, UNO_QUERY );
412 }
413}
414
415
416void SmartTagMgr::ReadConfiguration( bool bExcludedTypes, bool bRecognize )
417{
418 if ( !mxConfigurationSettings.is() )
419 return;
420
421 if ( bExcludedTypes )
422 {
424
425 Any aAny = mxConfigurationSettings->getPropertyValue( "ExcludedSmartTagTypes" );
426 Sequence< OUString > aValues;
427 aAny >>= aValues;
428
429 for ( const auto& rValue : std::as_const(aValues) )
430 maDisabledSmartTagTypes.insert( rValue );
431 }
432
433 if ( bRecognize )
434 {
435 Any aAny = mxConfigurationSettings->getPropertyValue( "RecognizeSmartTags" );
436 bool bValue = true;
437 aAny >>= bValue;
438
440 }
441}
442
444{
445 // register as listener at package manager
446 try
447 {
449 deployment::ExtensionManager::get( mxContext ) );
450 Reference< util::XModifyBroadcaster > xMB ( xExtensionManager, UNO_QUERY_THROW );
451
452 Reference< util::XModifyListener > xListener( this );
453 xMB->addModifyListener( xListener );
454 }
455 catch ( uno::Exception& )
456 {
457 }
458
459 // register as listener at configuration
460 try
461 {
463 Reference< util::XChangesListener > xListener( this );
464 xCN->addChangesListener( xListener );
465 }
466 catch ( uno::Exception& )
467 {
468 }
469}
470
471typedef std::pair < const OUString, ActionReference > SmartTagMapElement;
472
476{
477 const sal_uInt32 nActionLibCount = maActionList.size();
478 const sal_uInt32 nRecognizerCount = maRecognizerList.size();
479
480 for ( sal_uInt32 i = 0; i < nRecognizerCount; ++i )
481 {
483 const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount();
484 for ( sal_uInt32 j = 0; j < nSmartTagCount; ++j )
485 {
486 const OUString aSmartTagName = xRecognizer->getSmartTagName(j);
487
488 // check if smart tag type has already been processed:
489 if ( maSmartTagMap.find( aSmartTagName ) != maSmartTagMap.end() )
490 continue;
491
492 bool bFound = false;
493 for ( sal_uInt32 k = 0; k < nActionLibCount; ++k )
494 {
496 const sal_uInt32 nSmartTagCountInActionLib = xActionLib->getSmartTagCount();
497 for ( sal_uInt32 l = 0; l < nSmartTagCountInActionLib; ++l )
498 {
499 const OUString aSmartTagNameInActionLib = xActionLib->getSmartTagName(l);
500 if ( aSmartTagName == aSmartTagNameInActionLib )
501 {
502 // found actions and recognizer for same smarttag
503 ActionReference aActionRef( xActionLib, l );
504
505 // add recognizer/action pair to map
506 maSmartTagMap.insert( SmartTagMapElement( aSmartTagName, aActionRef ));
507
508 bFound = true;
509 }
510 }
511 }
512
513 if ( !bFound )
514 {
515 // insert 'empty' action reference if there is no action associated with
516 // the current smart tag type:
518 ActionReference aActionRef( xActionLib, 0 );
519
520 // add recognizer/action pair to map
521 maSmartTagMap.insert( SmartTagMapElement( aSmartTagName, aActionRef ));
522 }
523 }
524 }
525}
526
527/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::pair< const OUString, ActionReference > SmartTagMapElement
virtual void SAL_CALL modified(const css::lang::EventObject &aEvent) override
css::uno::Reference< css::beans::XPropertySet > mxConfigurationSettings
Definition: SmartTagMgr.hxx:97
css::uno::Reference< css::uno::XComponentContext > mxContext
Definition: SmartTagMgr.hxx:96
std::vector< css::uno::Reference< css::smarttags::XSmartTagAction > > maActionList
Definition: SmartTagMgr.hxx:92
std::vector< css::uno::Reference< css::smarttags::XSmartTagRecognizer > > maRecognizerList
Definition: SmartTagMgr.hxx:91
const OUString maApplicationName
Definition: SmartTagMgr.hxx:90
std::set< OUString > maDisabledSmartTagTypes
Definition: SmartTagMgr.hxx:93
void PrepareConfiguration(std::u16string_view rConfigurationGroupName)
Prepare configuration access.
void RegisterListener()
Registers the smart tag manager as listener at the package manager.
void WriteConfiguration(const bool *bLabelTextWithSmartTags, const std::vector< OUString > *pDisabledTypes) const
Writes configuration settings.
css::uno::Reference< css::i18n::XBreakIterator > mxBreakIter
Definition: SmartTagMgr.hxx:95
void RecognizeTextRange(const css::uno::Reference< css::text::XTextRange > &rRange, const css::uno::Reference< css::text::XTextMarkup > &rMarkup, const css::uno::Reference< css::frame::XController > &rController) const
bool mbLabelTextWithSmartTags
Definition: SmartTagMgr.hxx:98
SmartTagMgr(const OUString &rApplicationName)
Definition: SmartTagMgr.cxx:49
void GetActionSequences(std::vector< OUString > &rSmartTagTypes, css::uno::Sequence< css::uno::Sequence< css::uno::Reference< css::smarttags::XSmartTagAction > > > &rActionComponentsSequence, css::uno::Sequence< css::uno::Sequence< sal_Int32 > > &rActionIndicesSequence) const
Returns all action references associated with a given list of smart tag types.
bool IsSmartTagTypeEnabled(const OUString &rSmartTagType) const
Returns true if the given smart tag type is enabled.
void AssociateActionsWithRecognizers()
Sets up a map that maps smart tag type names to actions references.
virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent &Event) override
void LoadLibraries()
Checks for installed smart tag recognizers/actions and stores them in maRecognizerList and maActionLi...
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
OUString GetSmartTagCaption(const OUString &rSmartTagType, const css::lang::Locale &rLocale) const
Returns the caption for a smart tag type.
void Init(std::u16string_view rConfigurationGroupName)
Triggers configuration reading, library loading and listener registration NOTE: MUST BE CALLED AFTER ...
Definition: SmartTagMgr.cxx:60
void ReadConfiguration(bool bExcludedTypes, bool bRecognize)
Reads the configuration data.
std::multimap< OUString, ActionReference > maSmartTagMap
Definition: SmartTagMgr.hxx:94
void RecognizeString(const OUString &rText, const css::uno::Reference< css::text::XTextMarkup > &rMarkup, const css::uno::Reference< css::frame::XController > &rController, const css::lang::Locale &rLocale, sal_uInt32 nStart, sal_uInt32 nLen) const
Dispatches the recognize call to all installed smart tag recognizers.
Definition: SmartTagMgr.cxx:70
virtual ~SmartTagMgr() override
Definition: SmartTagMgr.cxx:56
uno::Reference< uno::XComponentContext > mxContext
Sequence< PropertyValue > aArguments
uno_Any a
@ Exception
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getProcessComponentContext()
int i
A reference to a smart tag action.
Definition: SmartTagMgr.hxx:73
sal_Int32 mnSmartTagIndex
Definition: SmartTagMgr.hxx:75
css::uno::Reference< css::smarttags::XSmartTagAction > mxSmartTagAction
Definition: SmartTagMgr.hxx:74
Reference< XController > xController
Reference< XModel > xModel
const SvXMLTokenMapEntry aTypes[]