tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / framework / source / uielement / styletoolbarcontroller.cxx
blobacad86db5e25266cd086ef18786c1fd9bd3f8a79
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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 */
10 #include <uielement/styletoolbarcontroller.hxx>
12 #include <tools/urlobj.hxx>
13 #include <utility>
14 #include <vcl/svapp.hxx>
15 #include <vcl/toolbox.hxx>
16 #include <sal/log.hxx>
17 #include <o3tl/string_view.hxx>
19 #include <com/sun/star/frame/XController.hpp>
20 #include <com/sun/star/frame/status/Template.hpp>
21 #include <com/sun/star/lang/DisposedException.hpp>
22 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
23 #include <com/sun/star/util/XURLTransformer.hpp>
25 namespace {
27 OUString MapFamilyToCommand( std::u16string_view rFamily )
29 if ( rFamily == u"ParagraphStyles" ||
30 rFamily == u"CellStyles" || // In sc
31 rFamily == u"graphics" ) // In sd
32 return u".uno:ParaStyle"_ustr;
33 else if ( rFamily == u"CharacterStyles" )
34 return u".uno:CharStyle"_ustr;
35 else if ( rFamily == u"PageStyles" )
36 return u".uno:PageStyle"_ustr;
37 else if ( rFamily == u"FrameStyles" ||
38 rFamily == u"GraphicStyles" ) // In sc
39 return u".uno:FrameStyle"_ustr;
40 else if ( rFamily == u"NumberingStyles" )
41 return u".uno:ListStyle"_ustr;
42 else if ( rFamily == u"TableStyles" )
43 return u".uno:TableStyle"_ustr;
45 return OUString();
48 OUString GetDisplayFromInternalName( const css::uno::Reference< css::frame::XFrame >& rFrame,
49 const OUString& rStyleName,
50 const OUString& rFamilyName )
52 try
54 css::uno::Reference< css::frame::XController > xController(
55 rFrame->getController(), css::uno::UNO_SET_THROW );
56 css::uno::Reference< css::style::XStyleFamiliesSupplier > xStylesSupplier(
57 xController->getModel(), css::uno::UNO_QUERY_THROW );
58 css::uno::Reference< css::container::XNameAccess > xFamilies(
59 xStylesSupplier->getStyleFamilies(), css::uno::UNO_SET_THROW );
61 css::uno::Reference< css::container::XNameAccess > xStyleSet;
62 xFamilies->getByName( rFamilyName ) >>= xStyleSet;
63 css::uno::Reference< css::beans::XPropertySet > xStyle;
64 xStyleSet->getByName( rStyleName ) >>= xStyle;
66 OUString aDisplayName;
67 if ( xStyle.is() )
68 xStyle->getPropertyValue( u"DisplayName"_ustr ) >>= aDisplayName;
69 return aDisplayName;
71 catch ( const css::uno::Exception& )
73 // We couldn't get the display name. As a last resort we'll
74 // try to use the internal name, as was specified in the URL.
77 return rStyleName;
82 namespace framework {
84 StyleDispatcher::StyleDispatcher( const css::uno::Reference< css::frame::XFrame >& rFrame,
85 css::uno::Reference< css::util::XURLTransformer > xUrlTransformer,
86 const css::util::URL& rURL )
87 : m_aCommand( rURL.Complete )
88 , m_xUrlTransformer(std::move( xUrlTransformer ))
89 , m_xFrame( rFrame, css::uno::UNO_QUERY )
91 SAL_WARN_IF( !m_aCommand.startsWith( ".uno:StyleApply?" ), "fwk.uielement", "Wrong dispatcher!" );
93 OUString aParams = rURL.Arguments;
94 OUString aStyleName, aFamilyName;
95 sal_Int32 nIndex = 0;
98 std::u16string_view aParam = o3tl::getToken(aParams, 0, '&', nIndex );
100 sal_Int32 nParamIndex = 0;
101 std::u16string_view aParamName = o3tl::getToken(aParam, 0, '=', nParamIndex );
102 if ( nParamIndex < 0 )
103 break;
105 if ( aParamName == u"Style:string" )
107 std::u16string_view aValue = o3tl::getToken(aParam, 0, '=', nParamIndex );
108 aStyleName = INetURLObject::decode( aValue, INetURLObject::DecodeMechanism::WithCharset );
110 else if ( aParamName == u"FamilyName:string" )
112 aFamilyName = o3tl::getToken(aParam, 0, '=', nParamIndex );
115 } while ( nIndex >= 0 );
117 m_aStatusCommand = MapFamilyToCommand( aFamilyName );
118 if ( m_aStatusCommand.isEmpty() || aStyleName.isEmpty() )
120 // We can't provide status updates for this command, but just executing
121 // the command should still work (given that the command is valid).
122 SAL_WARN( "fwk.uielement", "Unable to parse as a style command: " << m_aCommand );
123 return;
126 m_aStyleName = GetDisplayFromInternalName( rFrame, aStyleName, aFamilyName );
127 if ( m_xFrame.is() )
129 css::util::URL aStatusURL;
130 aStatusURL.Complete = u".uno:StyleApply"_ustr;
131 m_xUrlTransformer->parseStrict( aStatusURL );
132 m_xStyleApplyStatusDispatch = m_xFrame->queryDispatch(aStatusURL, OUString(), 0);
133 aStatusURL.Complete = m_aStatusCommand;
134 m_xUrlTransformer->parseStrict( aStatusURL );
135 m_xStyleFamilyStatusDispatch = m_xFrame->queryDispatch(aStatusURL, OUString(), 0);
139 void StyleDispatcher::dispatch( const css::util::URL& rURL,
140 const css::uno::Sequence< css::beans::PropertyValue >& rArguments )
142 if ( !m_xFrame.is() )
143 return;
145 css::uno::Reference< css::frame::XDispatch > xDispatch( m_xFrame->queryDispatch( rURL, OUString(), 0 ) );
146 if ( xDispatch.is() )
147 xDispatch->dispatch( rURL, rArguments );
150 void StyleDispatcher::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& rListener,
151 const css::util::URL& /*rURL*/ )
153 if ( !m_xOwner.is() )
154 m_xOwner.set( rListener );
155 if (m_xStyleApplyStatusDispatch)
157 css::util::URL aStatusURL;
158 aStatusURL.Complete = u".uno:StyleApply"_ustr;
159 m_xUrlTransformer->parseStrict(aStatusURL);
160 m_xStyleApplyStatusDispatch->addStatusListener(this, aStatusURL);
162 if (m_xStyleFamilyStatusDispatch)
164 css::util::URL aStatusURL;
165 aStatusURL.Complete = m_aStatusCommand;
166 m_xUrlTransformer->parseStrict( aStatusURL );
167 m_xStyleFamilyStatusDispatch->addStatusListener(this, aStatusURL);
171 void StyleDispatcher::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*rListener*/,
172 const css::util::URL& /*rURL*/ )
174 if (m_xStyleFamilyStatusDispatch)
176 css::util::URL aStatusURL;
177 aStatusURL.Complete = m_aStatusCommand;
178 m_xUrlTransformer->parseStrict( aStatusURL );
179 m_xStyleFamilyStatusDispatch->removeStatusListener(this, aStatusURL);
181 if (m_xStyleApplyStatusDispatch)
183 css::util::URL aStatusURL;
184 aStatusURL.Complete = u".uno:StyleApply"_ustr;
185 m_xUrlTransformer->parseStrict(aStatusURL);
186 m_xStyleApplyStatusDispatch->removeStatusListener(this, aStatusURL);
190 void StyleDispatcher::statusChanged( const css::frame::FeatureStateEvent& rEvent )
192 if (rEvent.FeatureURL.Complete == ".uno:StyleApply")
194 m_bStyleApplyEnabled = rEvent.IsEnabled;
195 return;
198 css::frame::status::Template aTemplate;
199 rEvent.State >>= aTemplate;
201 css::frame::FeatureStateEvent aEvent;
202 aEvent.FeatureURL.Complete = m_aCommand;
203 m_xUrlTransformer->parseStrict( aEvent.FeatureURL );
205 aEvent.IsEnabled = m_bStyleApplyEnabled && rEvent.IsEnabled;
206 aEvent.Requery = rEvent.Requery;
207 aEvent.State <<= m_aStyleName == aTemplate.StyleName;
208 m_xOwner->statusChanged( aEvent );
211 void StyleDispatcher::disposing( const css::lang::EventObject& rSource )
213 if (rSource.Source == m_xStyleFamilyStatusDispatch)
214 m_xStyleFamilyStatusDispatch.clear();
215 if (rSource.Source == m_xStyleApplyStatusDispatch)
216 m_xStyleApplyStatusDispatch.clear();
219 StyleToolbarController::StyleToolbarController( const css::uno::Reference< css::uno::XComponentContext >& rContext,
220 const css::uno::Reference< css::frame::XFrame >& rFrame,
221 const OUString& rCommand )
222 : ToolboxController( rContext, rFrame, rCommand )
226 void StyleToolbarController::update()
228 if ( m_bDisposed )
229 throw css::lang::DisposedException();
231 css::util::URL aURL;
232 aURL.Complete = m_aCommandURL;
233 m_xUrlTransformer->parseStrict( aURL );
235 auto& xDispatcher = m_aListenerMap[m_aCommandURL];
236 if ( xDispatcher.is() )
237 xDispatcher->removeStatusListener( this, aURL );
239 xDispatcher.set( new StyleDispatcher( m_xFrame, m_xUrlTransformer, aURL ) );
240 xDispatcher->addStatusListener( this, aURL );
243 void StyleToolbarController::statusChanged( const css::frame::FeatureStateEvent& rEvent )
245 SolarMutexGuard aGuard;
247 if ( m_bDisposed )
248 throw css::lang::DisposedException();
250 ToolBox* pToolBox = nullptr;
251 ToolBoxItemId nItemId;
252 if ( getToolboxId( nItemId, &pToolBox ) )
254 bool bChecked = false;
255 rEvent.State >>= bChecked;
256 pToolBox->CheckItem( nItemId, bChecked );
257 pToolBox->EnableItem( nItemId, rEvent.IsEnabled );
261 void StyleToolbarController::dispose()
263 ToolboxController::dispose();
264 m_aListenerMap.clear(); // Break the cycle with StyleDispatcher.
269 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */