LibreOffice Module sc (master)  1
macromgr.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 #include <macromgr.hxx>
21 #include <document.hxx>
22 
23 #include <basic/basmgr.hxx>
24 #include <cppuhelper/implbase.hxx>
25 #include <sfx2/objsh.hxx>
26 #include <formulacell.hxx>
27 #include <vector>
28 #include <com/sun/star/container/XContainer.hpp>
29 #include <com/sun/star/script/XLibraryContainer.hpp>
30 
31 using namespace ::com::sun::star;
32 using ::com::sun::star::uno::Reference;
33 using ::std::vector;
34 using ::std::pair;
35 
42 {
43 public:
44  void addCell(const OUString& rModuleName, ScFormulaCell* pCell)
45  {
46  ModuleCellMap::iterator itr = maCells.find(rModuleName);
47  if (itr == maCells.end())
48  {
49  pair<ModuleCellMap::iterator, bool> r = maCells.emplace(
50  rModuleName, vector<ScFormulaCell*>());
51 
52  if (!r.second)
53  // insertion failed.
54  return;
55 
56  itr = r.first;
57  }
58  itr->second.push_back(pCell);
59  }
60 
61  void removeCell(const ScFormulaCell* pCell)
62  {
63  for (auto& rEntry : maCells)
64  {
65  rEntry.second.erase(std::remove(rEntry.second.begin(), rEntry.second.end(), pCell), rEntry.second.end() );
66  }
67  }
68 
69  void getCellsByModule(const OUString& rModuleName, vector<ScFormulaCell*>& rCells)
70  {
71  ModuleCellMap::iterator itr = maCells.find(rModuleName);
72  if (itr == maCells.end())
73  return;
74 
75  vector<ScFormulaCell*>& rCellList = itr->second;
76 
77  // Remove duplicates.
78  std::sort(rCellList.begin(), rCellList.end());
79  auto last = std::unique(rCellList.begin(), rCellList.end());
80  rCellList.erase(last, rCellList.end());
81 
82  // exception safe copy
83  vector<ScFormulaCell*> temp(rCellList);
84  rCells.swap(temp);
85  }
86 
87 private:
88  typedef std::unordered_map<OUString, vector<ScFormulaCell*>> ModuleCellMap;
89  ModuleCellMap maCells;
90 };
91 
93  mpDepTracker(new ScUserMacroDepTracker),
94  mrDoc(rDoc)
95 {
96 }
97 
99 {
100 }
101 
102 typedef ::cppu::WeakImplHelper< css::container::XContainerListener > ContainerListenerHelper;
103 
104 namespace {
105 
106 class VBAProjectListener : public ContainerListenerHelper
107 {
108  ScMacroManager* mpMacroMgr;
109 public:
110  explicit VBAProjectListener( ScMacroManager* pMacroMgr ) : mpMacroMgr( pMacroMgr ) {}
111  // XEventListener
112  virtual void SAL_CALL disposing( const lang::EventObject& /*Source*/ ) override {}
113 
114  // XContainerListener
115  virtual void SAL_CALL elementInserted( const container::ContainerEvent& /*Event*/ ) override {}
116  virtual void SAL_CALL elementReplaced( const container::ContainerEvent& Event ) override
117  {
118  OUString sModuleName;
119  Event.Accessor >>= sModuleName;
120  mpMacroMgr->InitUserFuncData();
121  mpMacroMgr->BroadcastModuleUpdate(sModuleName);
122  }
123  virtual void SAL_CALL elementRemoved( const container::ContainerEvent& /*Event*/ ) override {}
124 
125 };
126 
127 }
128 
130 {
131  // Clear unordered_map
132  mhFuncToVolatile.clear();
133  OUString sProjectName("Standard");
134 
135  Reference< container::XContainer > xModuleContainer;
137  if (!pShell)
138  return;
139  if (!pShell->GetBasicManager()->GetName().isEmpty())
140  {
141  sProjectName = pShell->GetBasicManager()->GetName();
142  }
143  try
144  {
145  Reference< script::XLibraryContainer > xLibraries( pShell->GetBasicContainer(), uno::UNO_SET_THROW );
146  xModuleContainer.set( xLibraries->getByName( sProjectName ), uno::UNO_QUERY_THROW );
147 
148  // remove old listener ( if there was one )
149  if ( mxContainerListener.is() )
150  xModuleContainer->removeContainerListener( mxContainerListener );
151  // Create listener
152  mxContainerListener = new VBAProjectListener( this );
153  xModuleContainer->addContainerListener( mxContainerListener );
154  }
155  catch (const uno::Exception&)
156  {
157  }
158 }
159 
160 void ScMacroManager::SetUserFuncVolatile( const OUString& sName, bool isVolatile )
161 {
162  mhFuncToVolatile[ sName ] = isVolatile;
163 }
164 
165 bool ScMacroManager::GetUserFuncVolatile( const OUString& sName )
166 {
167  NameBoolMap::iterator it = mhFuncToVolatile.find( sName );
168  if ( it == mhFuncToVolatile.end() )
169  return false;
170  return it->second;
171 }
172 
173 void ScMacroManager::AddDependentCell(const OUString& aModuleName, ScFormulaCell* pCell)
174 {
175  mpDepTracker->addCell(aModuleName, pCell);
176 }
177 
179 {
180  mpDepTracker->removeCell(pCell);
181 }
182 
183 void ScMacroManager::BroadcastModuleUpdate(const OUString& aModuleName)
184 {
185  vector<ScFormulaCell*> aCells;
186  mpDepTracker->getCellsByModule(aModuleName, aCells);
187  for (ScFormulaCell* pCell : aCells)
188  {
189  mrDoc.PutInFormulaTree(pCell); // for F9 recalc
190 
191  // for recalc on cell value change. If the cell is not volatile, the
192  // cell stops listening right away after it gets re-interpreted.
194  }
195 }
196 
197 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::container::XContainerListener > mxContainerListener
Definition: macromgr.hxx:42
A simple container to keep track of cells that depend on basic modules changes.
Definition: macromgr.cxx:41
SC_DLLPUBLIC void InitUserFuncData()
Definition: macromgr.cxx:129
void BroadcastModuleUpdate(const OUString &aModuleName)
Definition: macromgr.cxx:183
#define BCA_LISTEN_ALWAYS
Definition: address.hxx:952
NameBoolMap mhFuncToVolatile
Definition: macromgr.hxx:41
SC_DLLPUBLIC void SetUserFuncVolatile(const OUString &sName, bool isVolatile)
Definition: macromgr.cxx:160
void SAL_CALL elementReplaced(const css::container::ContainerEvent &Event) override
void addCell(const OUString &rModuleName, ScFormulaCell *pCell)
Definition: macromgr.cxx:44
SC_DLLPUBLIC bool GetUserFuncVolatile(const OUString &sName)
Definition: macromgr.cxx:165
ModuleCellMap maCells
Definition: macromgr.cxx:89
ScMacroManager(ScDocument &rDoc)
Definition: macromgr.cxx:92
void RemoveDependentCell(const ScFormulaCell *pCell)
Definition: macromgr.cxx:178
void getCellsByModule(const OUString &rModuleName, vector< ScFormulaCell * > &rCells)
Definition: macromgr.cxx:69
void PutInFormulaTree(ScFormulaCell *pCell)
Definition: documen7.cxx:258
::std::unique_ptr< ScUserMacroDepTracker > mpDepTracker
Definition: macromgr.hxx:44
const char last[]
void SAL_CALL elementRemoved(const css::container::ContainerEvent &Event) override
DECL_LISTENERMULTIPLEXER_END void SAL_CALL elementInserted(const css::container::ContainerEvent &Event) override
void removeCell(const ScFormulaCell *pCell)
Definition: macromgr.cxx:61
std::unordered_map< OUString, vector< ScFormulaCell * > > ModuleCellMap
Definition: macromgr.cxx:88
ScDocument & mrDoc
Definition: macromgr.hxx:45
::cppu::WeakImplHelper< css::container::XContainerListener > ContainerListenerHelper
::cppu::WeakImplHelper< css::container::XContainerListener > ContainerListenerHelper
Definition: macromgr.cxx:102
const OUString & GetName() const
void AddDependentCell(const OUString &aModuleName, ScFormulaCell *pCell)
Definition: macromgr.cxx:173
SfxObjectShell * GetDocumentShell() const
Definition: document.hxx:1058
void StartListeningArea(const ScRange &rRange, bool bGroupListening, SvtListener *pListener)
Definition: documen7.cxx:35
BasicManager * GetBasicManager() const
css::uno::Reference< css::script::XLibraryContainer > GetBasicContainer()