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>
41 #include <comphelper/sequence.hxx>
42 #include <rtl/ustring.hxx>
43 
44 using namespace com::sun::star;
45 using namespace com::sun::star::uno;
46 using namespace com::sun::star::i18n;
47 
48 
49 SmartTagMgr::SmartTagMgr( const OUString& rApplicationName )
50  : maApplicationName( rApplicationName ),
51  maRecognizerList(),
52  maActionList(),
53  maDisabledSmartTagTypes(),
54  maSmartTagMap(),
56  mbLabelTextWithSmartTags(true)
57 {
58 }
59 
61 {
62 }
63 
64 void SmartTagMgr::Init( const OUString& rConfigurationGroupName )
65 {
66  PrepareConfiguration( rConfigurationGroupName );
67  ReadConfiguration( true, true );
69  LoadLibraries();
70 }
71 
74 void SmartTagMgr::RecognizeString( const OUString& rText,
75  const Reference< text::XTextMarkup >& xMarkup,
76  const Reference< frame::XController >& xController,
77  const lang::Locale& rLocale,
78  sal_uInt32 nStart, sal_uInt32 nLen ) const
79 {
81  {
82  // if all smart tag types supported by this recognizer have been
83  // disabled, we do not have to call the recognizer:
84  bool bCallRecognizer = false;
85  const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount();
86  for ( sal_uInt32 j = 0; j < nSmartTagCount && !bCallRecognizer; ++j )
87  {
88  const OUString aSmartTagName = xRecognizer->getSmartTagName(j);
89  if ( IsSmartTagTypeEnabled( aSmartTagName ) )
90  bCallRecognizer = true;
91  }
92 
93  if ( bCallRecognizer )
94  {
95  // get the break iterator
96  if ( !mxBreakIter.is() )
97  {
98  mxBreakIter.set( BreakIterator::create(mxContext) );
99  }
100  xRecognizer->recognize( rText, nStart, nLen,
101  smarttags::SmartTagRecognizerMode_PARAGRAPH,
102  rLocale, xMarkup, maApplicationName, xController,
103  mxBreakIter );
104  }
105  }
106 }
107 
109  const Reference< text::XTextMarkup >& xMarkup,
110  const Reference< frame::XController >& xController) const
111 {
113  {
114  Reference< smarttags::XRangeBasedSmartTagRecognizer > xRangeBasedRecognizer( xRecognizer, UNO_QUERY);
115 
116  if (!xRangeBasedRecognizer.is()) continue;
117 
118  // if all smart tag types supported by this recognizer have been
119  // disabled, we do not have to call the recognizer:
120  bool bCallRecognizer = false;
121  const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount();
122  for ( sal_uInt32 j = 0; j < nSmartTagCount && !bCallRecognizer; ++j )
123  {
124  const OUString aSmartTagName = xRecognizer->getSmartTagName(j);
125  if ( IsSmartTagTypeEnabled( aSmartTagName ) )
126  bCallRecognizer = true;
127  }
128 
129  if ( bCallRecognizer )
130  {
131  xRangeBasedRecognizer->recognizeTextRange( xRange,
132  smarttags::SmartTagRecognizerMode_PARAGRAPH,
133  xMarkup, maApplicationName, xController);
134  }
135  }
136 
137 }
138 
139 void SmartTagMgr::GetActionSequences( std::vector< OUString >& rSmartTagTypes,
140  Sequence < Sequence< Reference< smarttags::XSmartTagAction > > >& rActionComponentsSequence,
141  Sequence < Sequence< sal_Int32 > >& rActionIndicesSequence ) const
142 {
143  rActionComponentsSequence.realloc( rSmartTagTypes.size() );
144  rActionIndicesSequence.realloc( rSmartTagTypes.size() );
145 
146  for ( size_t j = 0; j < rSmartTagTypes.size(); ++j )
147  {
148  const OUString& rSmartTagType = rSmartTagTypes[j];
149 
150  const sal_Int32 nNumberOfActionRefs = maSmartTagMap.count( rSmartTagType );
151 
152  Sequence< Reference< smarttags::XSmartTagAction > > aActions( nNumberOfActionRefs );
153  Sequence< sal_Int32 > aIndices( nNumberOfActionRefs );
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  aActions[ i ] = (*aActionsIter).second.mxSmartTagAction;
161  aIndices[ i++ ] = (*aActionsIter).second.mnSmartTagIndex;
162  }
163 
164  rActionComponentsSequence[ j ] = aActions;
165  rActionIndicesSequence[ j ] = aIndices;
166  }
167 }
168 
171 OUString 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 
195 bool SmartTagMgr::IsSmartTagTypeEnabled( const OUString& rSmartTagType ) const
196 {
197  return maDisabledSmartTagTypes.end() == maDisabledSmartTagTypes.find( rSmartTagType );
198 }
199 
202 void 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 = makeAny( *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 = makeAny( 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
253 void SmartTagMgr::modified( const lang::EventObject& )
254 {
255  SolarMutexGuard aGuard;
256 
257  maRecognizerList.clear();
258  maActionList.clear();
259  maSmartTagMap.clear();
260 
261  LoadLibraries();
262 }
263 
264 // css::lang::XEventListener
265 void 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
292 void 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 
375 void SmartTagMgr::PrepareConfiguration( const OUString& rConfigurationGroupName )
376 {
377  Any aAny = makeAny( "/org.openoffice.Office.Common/SmartTags/" + rConfigurationGroupName );
378  beans::PropertyValue aPathArgument;
379  aPathArgument.Name = "nodepath";
380  aPathArgument.Value = aAny;
382  aArguments[ 0 ] <<= 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 
416 void SmartTagMgr::ReadConfiguration( bool bExcludedTypes, bool bRecognize )
417 {
418  if ( !mxConfigurationSettings.is() )
419  return;
420 
421  if ( bExcludedTypes )
422  {
423  maDisabledSmartTagTypes.clear();
424 
425  Any aAny = mxConfigurationSettings->getPropertyValue( "ExcludedSmartTagTypes" );
426  Sequence< OUString > aValues;
427  aAny >>= aValues;
428 
429  for ( const auto& rValue : std::as_const(aValues) )
431  }
432 
433  if ( bRecognize )
434  {
435  Any aAny = mxConfigurationSettings->getPropertyValue( "RecognizeSmartTags" );
436  bool bValue = true;
437  aAny >>= bValue;
438 
439  mbLabelTextWithSmartTags = bValue;
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 
471 typedef 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: */
void Init(const OUString &rConfigurationGroupName)
Triggers configuration reading, library loading and listener registration NOTE: MUST BE CALLED AFTER ...
Definition: SmartTagMgr.cxx:64
uno::Reference< uno::XComponentContext > mxContext
std::multimap< OUString, ActionReference > maSmartTagMap
Definition: SmartTagMgr.hxx:93
css::uno::Reference< css::i18n::XBreakIterator > mxBreakIter
Definition: SmartTagMgr.hxx:94
void AssociateActionsWithRecognizers()
Sets up a map that maps smart tag type names to actions references.
void LoadLibraries()
Checks for installed smart tag recognizers/actions and stores them in maRecognizerList and maActionLi...
std::pair< const OUString, ActionReference > SmartTagMapElement
css::uno::Any const & rValue
Sequence< PropertyValue > aArguments
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.
std::set< OUString > maDisabledSmartTagTypes
Definition: SmartTagMgr.hxx:92
std::vector< css::uno::Reference< css::smarttags::XSmartTagAction > > maActionList
Definition: SmartTagMgr.hxx:91
const OUString maApplicationName
Definition: SmartTagMgr.hxx:89
css::uno::Reference< css::uno::XComponentContext > mxContext
Definition: SmartTagMgr.hxx:95
css::uno::Reference< css::smarttags::XSmartTagAction > mxSmartTagAction
Definition: SmartTagMgr.hxx:73
sal_Int32 mnSmartTagIndex
Definition: SmartTagMgr.hxx:74
int i
uno_Any a
void RegisterListener()
Registers the smart tag manager as listener at the package manager.
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
void WriteConfiguration(const bool *bLabelTextWithSmartTags, const std::vector< OUString > *pDisabledTypes) const
Writes configuration settings.
A reference to a smart tag action.
Definition: SmartTagMgr.hxx:71
std::vector< css::uno::Reference< css::smarttags::XSmartTagRecognizer > > maRecognizerList
Definition: SmartTagMgr.hxx:90
css::uno::Reference< css::beans::XPropertySet > mxConfigurationSettings
Definition: SmartTagMgr.hxx:96
const SvXMLTokenMapEntry aTypes[]
virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent &Event) override
virtual void SAL_CALL modified(const css::lang::EventObject &aEvent) override
bool mbLabelTextWithSmartTags
Definition: SmartTagMgr.hxx:97
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
void PrepareConfiguration(const OUString &rConfigurationGroupName)
Prepare configuration access.
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
bool IsSmartTagTypeEnabled(const OUString &rSmartTagType) const
Returns true if the given smart tag type is enabled.
Reference< XComponentContext > getProcessComponentContext()
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:74
Reference< XModel > xModel
OUString GetSmartTagCaption(const OUString &rSmartTagType, const css::lang::Locale &rLocale) const
Returns the caption for a smart tag type.
void ReadConfiguration(bool bExcludedTypes, bool bRecognize)
Reads the configuration data.
virtual ~SmartTagMgr() override
Definition: SmartTagMgr.cxx:60
SmartTagMgr(const OUString &rApplicationName)
Definition: SmartTagMgr.cxx:49
css::uno::Any SAL_CALL makeAny(const SharedUNOComponent< INTERFACE, COMPONENT > &value)