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