LibreOffice Module vbahelper (master) 1
vbacommandbarhelper.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 */
20#include <com/sun/star/beans/XPropertySet.hpp>
21#include <com/sun/star/lang/XServiceInfo.hpp>
22#include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
23#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
24#include <com/sun/star/ui/theWindowStateConfiguration.hpp>
25#include <comphelper/random.hxx>
26#include <utility>
28#include <rtl/ustrbuf.hxx>
29#include <sal/log.hxx>
30#include <o3tl/string_view.hxx>
31#include <map>
32#include <string_view>
33
34using namespace com::sun::star;
35using namespace ooo::vba;
36
37typedef std::map< OUString, OUString > MSO2OOCommandbarMap;
38
39namespace {
40
41class MSO2OOCommandbarHelper final
42{
43private:
44 static MSO2OOCommandbarHelper* pMSO2OOCommandbarHelper;
45 MSO2OOCommandbarMap maBuildinToolbarMap;
46
47 MSO2OOCommandbarHelper()
48 {
49 // Buildin toolbars
50 maBuildinToolbarMap.insert( std::make_pair( OUString("Standard") , OUString("private:resource/toolbar/standardbar" ) ) );
51 maBuildinToolbarMap.insert( std::make_pair( OUString("Formatting"), OUString("private:resource/toolbar/formatobjectbar") ) );
52 maBuildinToolbarMap.insert( std::make_pair( OUString("Drawing"), OUString("private:resource/toolbar/drawbar") ) );
53 maBuildinToolbarMap.insert( std::make_pair( OUString("Toolbar List"), OUString("private:resource/toolbar/toolbar") ) );
54 maBuildinToolbarMap.insert( std::make_pair( OUString("Forms"), OUString("private:resource/toolbar/formcontrols") ) );
55 maBuildinToolbarMap.insert( std::make_pair( OUString("Form Controls"),OUString("private:resource/toolbar/formcontrols") ) );
56 maBuildinToolbarMap.insert( std::make_pair( OUString("Full Screen"), OUString("private:resource/toolbar/fullscreenbar") ) );
57 maBuildinToolbarMap.insert( std::make_pair( OUString("Chart"), OUString("private:resource/toolbar/flowchartshapes") ) );
58 maBuildinToolbarMap.insert( std::make_pair( OUString("Picture"), OUString("private:resource/toolbar/graphicobjectbar") ) );
59 maBuildinToolbarMap.insert( std::make_pair( OUString("WordArt"), OUString("private:resource/toolbar/fontworkobjectbar") ) );
60 maBuildinToolbarMap.insert( std::make_pair( OUString("3-D Settings"), OUString("private:resource/toolbar/extrusionobjectbar") ) );
61 }
62
63public:
64 static MSO2OOCommandbarHelper* getMSO2OOCommandbarHelper()
65 {
66 if( pMSO2OOCommandbarHelper == nullptr )
67 {
68 pMSO2OOCommandbarHelper = new MSO2OOCommandbarHelper();
69 }
70 return pMSO2OOCommandbarHelper;
71 }
72
73 OUString findBuildinToolbar( const OUString& sToolbarName )
74 {
75 auto it = std::find_if(maBuildinToolbarMap.begin(), maBuildinToolbarMap.end(),
76 [&sToolbarName](const MSO2OOCommandbarMap::value_type& rItem) { return rItem.first.equalsIgnoreAsciiCase( sToolbarName ); });
77 if( it != maBuildinToolbarMap.end() )
78 return it->second;
79 return OUString();
80 }
81};
82
83}
84
85MSO2OOCommandbarHelper* MSO2OOCommandbarHelper::pMSO2OOCommandbarHelper = nullptr;
86
87
88VbaCommandBarHelper::VbaCommandBarHelper( css::uno::Reference< css::uno::XComponentContext > xContext, css::uno::Reference< css::frame::XModel > xModel ) : mxContext(std::move( xContext )), mxModel(std::move( xModel ))
89{
90 Init();
91}
92
94{
95 uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUICfgSupplier( mxModel, uno::UNO_QUERY_THROW );
96 m_xDocCfgMgr = xUICfgSupplier->getUIConfigurationManager();
97
98 uno::Reference< lang::XServiceInfo > xServiceInfo( mxModel, uno::UNO_QUERY_THROW );
99 if( xServiceInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
100 {
101 maModuleId = "com.sun.star.sheet.SpreadsheetDocument";
102 }
103 else if( xServiceInfo->supportsService( "com.sun.star.text.TextDocument" ) )
104 {
105 maModuleId = "com.sun.star.text.TextDocument";
106 }
107
108 if( maModuleId.isEmpty() )
109 {
110 throw uno::RuntimeException( "Not implemented" );
111 }
112
113 css::uno::Reference< css::ui::XModuleUIConfigurationManagerSupplier > xUICfgMgrSupp(
114 css::ui::theModuleUIConfigurationManagerSupplier::get(mxContext) );
115
116 m_xAppCfgMgr.set( xUICfgMgrSupp->getUIConfigurationManager( maModuleId ), uno::UNO_SET_THROW );
117
118 css::uno::Reference< css::container::XNameAccess > xNameAccess = css::ui::theWindowStateConfiguration::get( mxContext );
119
120 m_xWindowState.set( xNameAccess->getByName( maModuleId ), uno::UNO_QUERY_THROW );
121}
122
123css::uno::Reference< css::container::XIndexAccess > VbaCommandBarHelper::getSettings( const OUString& sResourceUrl )
124{
125 if( m_xDocCfgMgr->hasSettings( sResourceUrl ) )
126 return m_xDocCfgMgr->getSettings( sResourceUrl, true );
127 else if( m_xAppCfgMgr->hasSettings( sResourceUrl ) )
128 return m_xAppCfgMgr->getSettings( sResourceUrl, true );
129 else
130 {
131 css::uno::Reference< css::container::XIndexAccess > xSettings( m_xAppCfgMgr->createSettings( ), uno::UNO_QUERY_THROW );
132 return xSettings;
133 }
134}
135
136void VbaCommandBarHelper::removeSettings( const OUString& sResourceUrl )
137{
138 if( m_xDocCfgMgr->hasSettings( sResourceUrl ) )
139 m_xDocCfgMgr->removeSettings( sResourceUrl );
140 else if( m_xAppCfgMgr->hasSettings( sResourceUrl ) )
141 m_xAppCfgMgr->removeSettings( sResourceUrl );
142
143 // persistChanges();
144}
145
146void VbaCommandBarHelper::ApplyTempChange( const OUString& sResourceUrl, const css::uno::Reference< css::container::XIndexAccess >& xSettings )
147{
148 if( m_xDocCfgMgr->hasSettings( sResourceUrl ) )
149 {
150 m_xDocCfgMgr->replaceSettings( sResourceUrl, xSettings );
151 }
152 else
153 {
154 m_xDocCfgMgr->insertSettings( sResourceUrl, xSettings );
155 }
156}
157
158uno::Reference< frame::XLayoutManager > VbaCommandBarHelper::getLayoutManager() const
159{
160 uno::Reference< frame::XFrame > xFrame( getModel()->getCurrentController()->getFrame(), uno::UNO_SET_THROW );
161 uno::Reference< beans::XPropertySet > xPropertySet( xFrame, uno::UNO_QUERY_THROW );
162 uno::Reference< frame::XLayoutManager > xLayoutManager( xPropertySet->getPropertyValue( "LayoutManager" ), uno::UNO_QUERY_THROW );
163 return xLayoutManager;
164}
165
166bool VbaCommandBarHelper::hasToolbar( const OUString& sResourceUrl, std::u16string_view sName )
167{
168 if( m_xDocCfgMgr->hasSettings( sResourceUrl ) )
169 {
170 OUString sUIName;
171 uno::Reference< beans::XPropertySet > xPropertySet( m_xDocCfgMgr->getSettings( sResourceUrl, false ), uno::UNO_QUERY_THROW );
172 xPropertySet->getPropertyValue( ITEM_DESCRIPTOR_UINAME ) >>= sUIName;
173 if( o3tl::equalsIgnoreAsciiCase( sName, sUIName ) )
174 return true;
175 }
176 return false;
177}
178
179// return the resource url if found
180OUString VbaCommandBarHelper::findToolbarByName( const css::uno::Reference< css::container::XNameAccess >& xNameAccess, const OUString& sName )
181{
182 // check if it is a buildin toolbar
183 OUString sResourceUrl = MSO2OOCommandbarHelper::getMSO2OOCommandbarHelper()->findBuildinToolbar( sName );
184 if( !sResourceUrl.isEmpty() )
185 return sResourceUrl;
186
187 const uno::Sequence< OUString > allNames = xNameAccess->getElementNames();
188 auto pName = std::find_if(allNames.begin(), allNames.end(),
189 [this, &sName](const OUString& rName) {
190 return rName.startsWith( ITEM_TOOLBAR_URL )
191 && hasToolbar( rName, sName );
192 });
193 if (pName != allNames.end())
194 return *pName;
195
196 // the customize toolbars creating during importing, should found there.
197 sResourceUrl = "private:resource/toolbar/custom_" + sName;
198 if( hasToolbar( sResourceUrl, sName ) )
199 return sResourceUrl;
200
201 return OUString();
202}
203
204// if found, return the position of the control. if not found, return -1
205sal_Int32 VbaCommandBarHelper::findControlByName( const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess, std::u16string_view sName, bool bMenu )
206{
207 sal_Int32 nCount = xIndexAccess->getCount();
208 css::uno::Sequence< css::beans::PropertyValue > aProps;
209 for( sal_Int32 i = 0; i < nCount; i++ )
210 {
211 OUString sLabel;
212 xIndexAccess->getByIndex( i ) >>= aProps;
213 getPropertyValue( aProps, ITEM_DESCRIPTOR_LABEL ) >>= sLabel;
214 // handle the hotkey marker '~' (remove in toolbars (?), replace by '&' in menus)
215 OUStringBuffer aBuffer;
216 sal_Int32 index = sLabel.indexOf( '~' );
217 if( index < 0 )
218 {
219 aBuffer = sLabel;
220 }
221 else
222 {
223 aBuffer.append( sLabel.subView(0, index) );
224 if( bMenu )
225 aBuffer.append( '&' );
226 aBuffer.append( sLabel.subView(index + 1) );
227 }
228 OUString sNewLabel = aBuffer.makeStringAndClear();
229 SAL_INFO("vbahelper", "VbaCommandBarHelper::findControlByName, control name: " << sNewLabel);
230 if( o3tl::equalsIgnoreAsciiCase( sName, sNewLabel ) )
231 return i;
232 }
233
234 // not found
235 return -1;
236}
237
239{
240 return OUString::Concat(ITEM_TOOLBAR_URL) + CUSTOM_TOOLBAR_STR +
241 // use a random number to minimize possible clash with existing custom toolbars
242 OUString::number(comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max()), 16);
243}
244
245/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::frame::XModel2 > mxModel
const char * pName
static sal_Int32 findControlByName(const css::uno::Reference< css::container::XIndexAccess > &xIndexAccess, std::u16string_view sName, bool bMenu)
css::uno::Reference< css::frame::XModel > mxModel
css::uno::Reference< css::ui::XUIConfigurationManager > m_xAppCfgMgr
void removeSettings(const OUString &sResourceUrl)
css::uno::Reference< css::container::XIndexAccess > getSettings(const OUString &sResourceUrl)
bool hasToolbar(const OUString &sResourceUrl, std::u16string_view sName)
VbaCommandBarHelper(css::uno::Reference< css::uno::XComponentContext > xContext, css::uno::Reference< css::frame::XModel > xModel)
void ApplyTempChange(const OUString &sResourceUrl, const css::uno::Reference< css::container::XIndexAccess > &xSettings)
css::uno::Reference< css::container::XNameAccess > m_xWindowState
css::uno::Reference< css::frame::XLayoutManager > getLayoutManager() const
css::uno::Reference< css::uno::XComponentContext > mxContext
static OUString generateCustomURL()
const css::uno::Reference< css::frame::XModel > & getModel() const
css::uno::Reference< css::ui::XUIConfigurationManager > m_xDocCfgMgr
OUString findToolbarByName(const css::uno::Reference< css::container::XNameAccess > &xNameAccess, const OUString &sName)
int nCount
uno::Reference< uno::XComponentContext > mxContext
OUString sName
#define SAL_INFO(area, stream)
int uniform_int_distribution(int a, int b)
int i
index
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
uno::Any getPropertyValue(const uno::Sequence< beans::PropertyValue > &aProp, const OUString &aName)
Definition: vbahelper.cxx:714
Reference< XFrame > xFrame
Reference< XModel > xModel
std::map< OUString, OUString > MSO2OOCommandbarMap
constexpr char16_t ITEM_TOOLBAR_URL[]
constexpr OUStringLiteral CUSTOM_TOOLBAR_STR
constexpr OUStringLiteral ITEM_DESCRIPTOR_UINAME
constexpr OUStringLiteral ITEM_DESCRIPTOR_LABEL
std::unique_ptr< char[]> aBuffer