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 <sal/config.h>
21 
22 #include <com/sun/star/frame/XAppDispatchProvider.hpp>
23 #include <com/sun/star/frame/XDispatch.hpp>
24 #include <com/sun/star/frame/XFrame.hpp>
25 #include <com/sun/star/frame/DispatchDescriptor.hpp>
26 #include <com/sun/star/lang/IllegalArgumentException.hpp>
27 #include <com/sun/star/lang/XInitialization.hpp>
28 #include <com/sun/star/lang/XServiceInfo.hpp>
29 #include <com/sun/star/uno/Exception.hpp>
30 #include <com/sun/star/util/URL.hpp>
31 
32 #include <basic/basmgr.hxx>
33 #include <basic/sbuno.hxx>
34 #include <comphelper/sequence.hxx>
35 #include <cppuhelper/implbase.hxx>
36 #include <cppuhelper/supportsservice.hxx>
37 #include <rtl/ref.hxx>
38 #include <sfx2/app.hxx>
39 #include <sfx2/dispatch.hxx>
40 #include <sfx2/docfile.hxx>
41 #include <sfx2/fcontnr.hxx>
42 #include <sfx2/frame.hxx>
43 #include <sfx2/module.hxx>
44 #include <sfx2/msg.hxx>
45 #include <sfx2/msgpool.hxx>
46 #include <sfx2/objsh.hxx>
47 #include <sfx2/request.hxx>
48 #include <sfx2/sfxbasecontroller.hxx>
49 #include <sfx2/sfxsids.hrc>
50 #include <sfx2/sfxuno.hxx>
51 #include <sfx2/unoctitm.hxx>
52 #include <svl/intitem.hxx>
53 #include <tools/urlobj.hxx>
54 #include <vcl/svapp.hxx>
55 
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::frame;
58 using namespace ::com::sun::star::uno;
59 
60 namespace {
61 
62 class SfxAppDispatchProvider : public ::cppu::WeakImplHelper< css::frame::XAppDispatchProvider,
63                                                                css::lang::XServiceInfo,
64                                                                css::lang::XInitialization >
65 {
66     css::uno::WeakReference < css::frame::XFrame > m_xFrame;
67 public:
SfxAppDispatchProvider()68     SfxAppDispatchProvider() {}
69 
70     virtual void SAL_CALL initialize(
71         css::uno::Sequence<css::uno::Any> const & aArguments) override;
72 
73     virtual OUString SAL_CALL getImplementationName() override;
74 
75     virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override;
76 
77     virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
78 
79     virtual css::uno::Reference < css::frame::XDispatch > SAL_CALL queryDispatch(
80             const css::util::URL& aURL, const OUString& sTargetFrameName,
81             sal_Int32 eSearchFlags ) override;
82 
83     virtual css::uno::Sequence< css::uno::Reference < css::frame::XDispatch > > SAL_CALL queryDispatches(
84             const css::uno::Sequence < css::frame::DispatchDescriptor >& seqDescriptor ) override;
85 
86     virtual css::uno::Sequence< sal_Int16 > SAL_CALL getSupportedCommandGroups() override;
87 
88     virtual css::uno::Sequence< css::frame::DispatchInformation > SAL_CALL getConfigurableDispatchInformation( sal_Int16 ) override;
89 };
90 
initialize(css::uno::Sequence<css::uno::Any> const & aArguments)91 void SfxAppDispatchProvider::initialize(
92     css::uno::Sequence<css::uno::Any> const & aArguments)
93 {
94     css::uno::Reference<css::frame::XFrame> f;
95     if (aArguments.getLength() != 1 || !(aArguments[0] >>= f)) {
96         throw css::lang::IllegalArgumentException(
97             "SfxAppDispatchProvider::initialize expects one XFrame argument",
98             static_cast<OWeakObject *>(this), 0);
99     }
100     m_xFrame = f;
101 }
102 
getImplementationName()103 OUString SAL_CALL SfxAppDispatchProvider::getImplementationName()
104 {
105     return "com.sun.star.comp.sfx2.AppDispatchProvider";
106 }
107 
supportsService(const OUString & sServiceName)108 sal_Bool SAL_CALL SfxAppDispatchProvider::supportsService( const OUString& sServiceName )
109 {
110     return cppu::supportsService(this, sServiceName);
111 }
112 
getSupportedServiceNames()113 css::uno::Sequence< OUString > SAL_CALL SfxAppDispatchProvider::getSupportedServiceNames()
114 {
115     return { "com.sun.star.frame.ProtocolHandler", "com.sun.star.frame.AppDispatchProvider" };
116 }
117 
queryDispatch(const util::URL & aURL,const OUString &,sal_Int32)118 Reference < XDispatch > SAL_CALL SfxAppDispatchProvider::queryDispatch(
119     const util::URL& aURL,
120     const OUString& /*sTargetFrameName*/,
121     sal_Int32 /*eSearchFlags*/ )
122 {
123     SolarMutexGuard guard;
124 
125     sal_uInt16                  nId( 0 );
126     bool                bMasterCommand( false );
127     Reference < XDispatch > xDisp;
128     const SfxSlot* pSlot = nullptr;
129     SfxApplication* pApp = SfxGetpApp();
130     if ( !pApp )
131         return xDisp;
132     SfxDispatcher* pAppDisp = pApp->GetAppDispatcher_Impl();
133     if ( aURL.Protocol == "slot:" || aURL.Protocol == "commandId:" )
134     {
135         nId = static_cast<sal_uInt16>(aURL.Path.toInt32());
136         SfxShell* pShell;
137         pAppDisp->GetShellAndSlot_Impl( nId, &pShell, &pSlot, true, true );
138     }
139     else if ( aURL.Protocol == ".uno:" )
140     {
141         // Support ".uno" commands. Map commands to slotid
142         bMasterCommand = SfxOfficeDispatch::IsMasterUnoCommand( aURL );
143         if ( bMasterCommand )
144             pSlot = pAppDisp->GetSlot( SfxOfficeDispatch::GetMasterUnoCommand( aURL ) );
145         else
146             pSlot = pAppDisp->GetSlot( aURL.Main );
147     }
148 
149     if ( pSlot )
150     {
151         SfxOfficeDispatch* pDispatch = new SfxOfficeDispatch( pAppDisp, pSlot, aURL ) ;
152         pDispatch->SetFrame(m_xFrame);
153         pDispatch->SetMasterUnoCommand( bMasterCommand );
154         xDisp = pDispatch;
155     }
156 
157     return xDisp;
158 }
159 
queryDispatches(const Sequence<DispatchDescriptor> & seqDescriptor)160 Sequence< Reference < XDispatch > > SAL_CALL SfxAppDispatchProvider::queryDispatches( const Sequence < DispatchDescriptor >& seqDescriptor )
161 {
162     sal_Int32 nCount = seqDescriptor.getLength();
163     uno::Sequence< uno::Reference < frame::XDispatch > > lDispatcher(nCount);
164     std::transform(seqDescriptor.begin(), seqDescriptor.end(), lDispatcher.begin(),
165         [this](const DispatchDescriptor& rDescr) -> uno::Reference<frame::XDispatch> {
166             return queryDispatch(rDescr.FeatureURL, rDescr.FrameName, rDescr.SearchFlags); });
167     return lDispatcher;
168 }
169 
getSupportedCommandGroups()170 Sequence< sal_Int16 > SAL_CALL SfxAppDispatchProvider::getSupportedCommandGroups()
171 {
172     SolarMutexGuard aGuard;
173 
174     std::vector< sal_Int16 > aGroupList;
175     SfxSlotPool& rAppSlotPool = SfxGetpApp()->GetAppSlotPool_Impl();
176 
177     const SfxSlotMode nMode( SfxSlotMode::TOOLBOXCONFIG|SfxSlotMode::ACCELCONFIG|SfxSlotMode::MENUCONFIG );
178 
179     // Select group ( group 0 is internal )
180     for (sal_uInt16 i=0; i< rAppSlotPool.GetGroupCount(); ++i)
181     {
182         rAppSlotPool.SeekGroup(i);
183         const SfxSlot* pSfxSlot = rAppSlotPool.FirstSlot();
184         while ( pSfxSlot )
185         {
186             if ( pSfxSlot->GetMode() & nMode )
187             {
188                 sal_Int16 nCommandGroup = MapGroupIDToCommandGroup( pSfxSlot->GetGroupId() );
189                 aGroupList.push_back( nCommandGroup );
190                 break;
191             }
192             pSfxSlot = rAppSlotPool.NextSlot();
193         }
194     }
195 
196     return comphelper::containerToSequence( aGroupList );
197 }
198 
getConfigurableDispatchInformation(sal_Int16 nCmdGroup)199 Sequence< frame::DispatchInformation > SAL_CALL SfxAppDispatchProvider::getConfigurableDispatchInformation( sal_Int16 nCmdGroup )
200 {
201     std::vector< frame::DispatchInformation > aCmdVector;
202 
203     SolarMutexGuard aGuard;
204     SfxSlotPool& rAppSlotPool = SfxGetpApp()->GetAppSlotPool_Impl();
205 
206     const SfxSlotMode nMode( SfxSlotMode::TOOLBOXCONFIG|SfxSlotMode::ACCELCONFIG|SfxSlotMode::MENUCONFIG );
207 
208     // Select group ( group 0 is internal )
209     for (sal_uInt16 i=0; i< rAppSlotPool.GetGroupCount(); ++i)
210     {
211         rAppSlotPool.SeekGroup(i);
212         const SfxSlot* pSfxSlot = rAppSlotPool.FirstSlot();
213         if ( pSfxSlot )
214         {
215             sal_Int16 nCommandGroup = MapGroupIDToCommandGroup( pSfxSlot->GetGroupId() );
216             if ( nCommandGroup == nCmdGroup )
217             {
218                 while ( pSfxSlot )
219                 {
220                     if ( pSfxSlot->GetMode() & nMode )
221                     {
222                         frame::DispatchInformation aCmdInfo;
223                         aCmdInfo.Command = ".uno:" + OUString::createFromAscii(pSfxSlot->GetUnoName());
224                         aCmdInfo.GroupId = nCommandGroup;
225                         aCmdVector.push_back( aCmdInfo );
226                     }
227                     pSfxSlot = rAppSlotPool.NextSlot();
228                 }
229             }
230         }
231     }
232 
233     return comphelper::containerToSequence( aCmdVector );
234 }
235 
236 }
237 
238 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
com_sun_star_comp_sfx2_AppDispatchProvider_get_implementation(css::uno::XComponentContext *,css::uno::Sequence<css::uno::Any> const &)239 com_sun_star_comp_sfx2_AppDispatchProvider_get_implementation(
240     css::uno::XComponentContext *,
241     css::uno::Sequence<css::uno::Any> const &)
242 {
243     return cppu::acquire(new SfxAppDispatchProvider);
244 }
245 
246 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
247