1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <cfgutil.hxx>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/container/XEnumerationAccess.hpp>
25 #include <com/sun/star/container/XEnumeration.hpp>
26 #include <com/sun/star/document/XScriptInvocationContext.hpp>
27 #include <com/sun/star/frame/ModuleManager.hpp>
28 #include <com/sun/star/frame/Desktop.hpp>
29 #include <com/sun/star/frame/theUICommandDescription.hpp>
30 #include <com/sun/star/frame/XDispatchInformationProvider.hpp>
31 #include <com/sun/star/script/browse/XBrowseNode.hpp>
32 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
33 #include <com/sun/star/script/browse/theBrowseNodeFactory.hpp>
34 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
35 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
36 #include <com/sun/star/uno/RuntimeException.hpp>
37 #include <com/sun/star/ui/theUICategoryDescription.hpp>
39 #include <basic/sbx.hxx>
40 #include <basic/basicmanagerrepository.hxx>
41 #include <basic/sbstar.hxx>
42 #include <basic/sbxmeth.hxx>
43 #include <basic/sbmod.hxx>
44 #include <basic/basmgr.hxx>
45 #include <tools/urlobj.hxx>
46 #include <strings.hrc>
47 #include <bitmaps.hlst>
48 #include <sfx2/app.hxx>
49 #include <sfx2/minfitem.hxx>
50 #include <comphelper/DisableInteractionHelper.hxx>
51 #include <comphelper/documentinfo.hxx>
52 #include <comphelper/processfactory.hxx>
53 #include <comphelper/sequenceashashmap.hxx>
54 #include <svtools/imagemgr.hxx>
55 #include <rtl/ustrbuf.hxx>
56 #include <sal/log.hxx>
57 #include <osl/diagnose.h>
58 #include <unotools/configmgr.hxx>
59 #include <dialmgr.hxx>
60 #include <svl/stritem.hxx>
61 #include <vcl/commandinfoprovider.hxx>
62 #include <vcl/help.hxx>
63 #include <vcl/svapp.hxx>
64 #include <uno/current_context.hxx>
66 using namespace ::com::sun::star
;
67 using namespace ::com::sun::star::uno
;
68 using namespace ::com::sun::star::script
;
69 using namespace ::com::sun::star::frame
;
70 using namespace ::com::sun::star::document
;
72 SfxStylesInfo_Impl::SfxStylesInfo_Impl()
75 void SfxStylesInfo_Impl::init(const OUString
& rModuleName
, const css::uno::Reference
< css::frame::XModel
>& xModel
)
77 m_aModuleName
= rModuleName
;
81 static const char CMDURL_STYLEPROT_ONLY
[] = ".uno:StyleApply?";
82 static const char CMDURL_SPART_ONLY
[] = "Style:string=";
83 static const char CMDURL_FPART_ONLY
[] = "FamilyName:string=";
85 static const char STYLEPROP_UINAME
[] = "DisplayName";
87 OUString
SfxStylesInfo_Impl::generateCommand(const OUString
& sFamily
, const OUString
& sStyle
)
89 return ".uno:StyleApply?Style:string="
91 + "&FamilyName:string="
95 bool SfxStylesInfo_Impl::parseStyleCommand(SfxStyleInfo_Impl
& aStyle
)
97 static const sal_Int32 LEN_STYLEPROT
= strlen(CMDURL_STYLEPROT_ONLY
);
98 static const sal_Int32 LEN_SPART
= strlen(CMDURL_SPART_ONLY
);
99 static const sal_Int32 LEN_FPART
= strlen(CMDURL_FPART_ONLY
);
101 if (!aStyle
.sCommand
.startsWith(CMDURL_STYLEPROT_ONLY
))
104 aStyle
.sFamily
.clear();
105 aStyle
.sStyle
.clear();
107 sal_Int32 nCmdLen
= aStyle
.sCommand
.getLength();
108 OUString sCmdArgs
= aStyle
.sCommand
.copy(LEN_STYLEPROT
, nCmdLen
-LEN_STYLEPROT
);
109 sal_Int32 i
= sCmdArgs
.indexOf('&');
113 OUString sArg
= sCmdArgs
.copy(0, i
);
114 if (sArg
.startsWith(CMDURL_SPART_ONLY
))
115 aStyle
.sStyle
= sArg
.copy(LEN_SPART
);
116 else if (sArg
.startsWith(CMDURL_FPART_ONLY
))
117 aStyle
.sFamily
= sArg
.copy(LEN_FPART
);
119 sArg
= sCmdArgs
.copy(i
+1, sCmdArgs
.getLength()-i
-1);
120 if (sArg
.startsWith(CMDURL_SPART_ONLY
))
121 aStyle
.sStyle
= sArg
.copy(LEN_SPART
);
122 else if (sArg
.startsWith(CMDURL_FPART_ONLY
))
123 aStyle
.sFamily
= sArg
.copy(LEN_FPART
);
125 return !(aStyle
.sFamily
.isEmpty() || aStyle
.sStyle
.isEmpty());
128 void SfxStylesInfo_Impl::getLabel4Style(SfxStyleInfo_Impl
& aStyle
)
132 css::uno::Reference
< css::style::XStyleFamiliesSupplier
> xModel(m_xDoc
, css::uno::UNO_QUERY
);
134 css::uno::Reference
< css::container::XNameAccess
> xFamilies
;
136 xFamilies
= xModel
->getStyleFamilies();
138 css::uno::Reference
< css::container::XNameAccess
> xStyleSet
;
140 xFamilies
->getByName(aStyle
.sFamily
) >>= xStyleSet
;
142 css::uno::Reference
< css::beans::XPropertySet
> xStyle
;
144 xStyleSet
->getByName(aStyle
.sStyle
) >>= xStyle
;
146 aStyle
.sLabel
.clear();
148 xStyle
->getPropertyValue(STYLEPROP_UINAME
) >>= aStyle
.sLabel
;
150 catch(const css::uno::RuntimeException
&)
152 catch(const css::uno::Exception
&)
153 { aStyle
.sLabel
.clear(); }
155 if (aStyle
.sLabel
.isEmpty())
157 aStyle
.sLabel
= aStyle
.sCommand
;
161 std::vector
< SfxStyleInfo_Impl
> SfxStylesInfo_Impl::getStyleFamilies()
163 // It's an optional interface!
164 css::uno::Reference
< css::style::XStyleFamiliesSupplier
> xModel(m_xDoc
, css::uno::UNO_QUERY
);
166 return std::vector
< SfxStyleInfo_Impl
>();
168 css::uno::Reference
< css::container::XNameAccess
> xCont
= xModel
->getStyleFamilies();
169 css::uno::Sequence
< OUString
> lFamilyNames
= xCont
->getElementNames();
170 std::vector
< SfxStyleInfo_Impl
> lFamilies
;
171 for (const auto& aFamily
: lFamilyNames
)
173 if ((aFamily
== "CellStyles" && m_aModuleName
!= "com.sun.star.sheet.SpreadsheetDocument") ||
174 aFamily
== "cell" || aFamily
== "table" || aFamily
== "Default")
177 SfxStyleInfo_Impl aFamilyInfo
;
178 aFamilyInfo
.sFamily
= aFamily
;
182 css::uno::Reference
< css::beans::XPropertySet
> xFamilyInfo
;
183 xCont
->getByName(aFamilyInfo
.sFamily
) >>= xFamilyInfo
;
184 if (!xFamilyInfo
.is())
186 // TODO_AS currently there is no support for an UIName property .. use internal family name instead
187 aFamilyInfo
.sLabel
= aFamilyInfo
.sFamily
;
190 xFamilyInfo
->getPropertyValue(STYLEPROP_UINAME
) >>= aFamilyInfo
.sLabel
;
192 catch(const css::uno::RuntimeException
&)
194 catch(const css::uno::Exception
&)
195 { return std::vector
< SfxStyleInfo_Impl
>(); }
197 lFamilies
.push_back(aFamilyInfo
);
203 std::vector
< SfxStyleInfo_Impl
> SfxStylesInfo_Impl::getStyles(const OUString
& sFamily
)
205 css::uno::Sequence
< OUString
> lStyleNames
;
206 css::uno::Reference
< css::style::XStyleFamiliesSupplier
> xModel(m_xDoc
, css::uno::UNO_QUERY_THROW
);
207 css::uno::Reference
< css::container::XNameAccess
> xFamilies
= xModel
->getStyleFamilies();
208 css::uno::Reference
< css::container::XNameAccess
> xStyleSet
;
211 xFamilies
->getByName(sFamily
) >>= xStyleSet
;
212 lStyleNames
= xStyleSet
->getElementNames();
214 catch(const css::uno::RuntimeException
&)
216 catch(const css::uno::Exception
&)
217 { return std::vector
< SfxStyleInfo_Impl
>(); }
219 std::vector
< SfxStyleInfo_Impl
> lStyles
;
220 sal_Int32 c
= lStyleNames
.getLength();
224 SfxStyleInfo_Impl aStyleInfo
;
225 aStyleInfo
.sFamily
= sFamily
;
226 aStyleInfo
.sStyle
= lStyleNames
[i
];
227 aStyleInfo
.sCommand
= SfxStylesInfo_Impl::generateCommand(aStyleInfo
.sFamily
, aStyleInfo
.sStyle
);
231 css::uno::Reference
< css::beans::XPropertySet
> xStyle
;
232 xStyleSet
->getByName(aStyleInfo
.sStyle
) >>= xStyle
;
235 xStyle
->getPropertyValue("DisplayName") >>= aStyleInfo
.sLabel
;
237 catch(const css::uno::RuntimeException
&)
239 catch(const css::uno::Exception
&)
242 lStyles
.push_back(aStyleInfo
);
247 OUString
CuiConfigFunctionListBox::GetHelpText( bool bConsiderParent
)
249 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(get_selected_id().toInt64());
252 if ( pData
->nKind
== SfxCfgKind::FUNCTION_SLOT
)
255 return Application::GetHelp()->GetHelpText(pData
->sCommand
, m_xTreeView
.get());
257 return Application::GetHelp()->GetHelpText(pData
->sCommand
, static_cast<weld::Widget
*>(nullptr));
259 else if ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
261 return pData
->sHelpText
;
267 OUString
CuiConfigFunctionListBox::GetCurCommand()
269 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(get_selected_id().toInt64());
272 return pData
->sCommand
;
275 OUString
CuiConfigFunctionListBox::GetCurLabel()
277 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(get_selected_id().toInt64());
280 if (!pData
->sLabel
.isEmpty())
281 return pData
->sLabel
;
282 return pData
->sCommand
;
285 CuiConfigFunctionListBox::CuiConfigFunctionListBox(std::unique_ptr
<weld::TreeView
> xTreeView
)
286 : m_xTreeView(std::move(xTreeView
))
287 , m_xScratchIter(m_xTreeView
->make_iterator())
289 m_xTreeView
->make_sorted();
290 m_xTreeView
->set_size_request(m_xTreeView
->get_approximate_digit_width() * 35, m_xTreeView
->get_height_rows(9));
293 CuiConfigFunctionListBox::~CuiConfigFunctionListBox()
298 void CuiConfigFunctionListBox::ClearAll()
300 Deletes all entries in the FunctionListBox, all UserData and all
301 possibly existing MacroInfo.
304 sal_uInt16 nCount
= aArr
.size();
305 for ( sal_uInt16 i
=0; i
<nCount
; ++i
)
307 SfxGroupInfo_Impl
*pData
= aArr
[i
].get();
309 if ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
311 OUString
* pScriptURI
= static_cast<OUString
*>(pData
->pObject
);
315 if ( pData
->nKind
== SfxCfgKind::GROUP_SCRIPTCONTAINER
)
317 XInterface
* xi
= static_cast<XInterface
*>(pData
->pObject
);
326 m_xTreeView
->clear();
329 OUString
CuiConfigFunctionListBox::GetSelectedScriptURI()
331 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(get_selected_id().toInt64());
332 if (pData
&& pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
333 return *static_cast<OUString
*>(pData
->pObject
);
337 struct SvxConfigGroupBoxResource_Impl
339 OUString m_sMyMacros
;
340 OUString m_sProdMacros
;
342 OUString m_sDlgMacros
;
343 OUString m_aStrGroupStyles
;
345 SvxConfigGroupBoxResource_Impl();
348 SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() :
349 m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS
)),
350 m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS
)),
351 m_sMacros(CuiResId(RID_SVXSTR_BASICMACROS
)),
352 m_sDlgMacros(CuiResId(RID_SVXSTR_PRODMACROS
)),
353 m_aStrGroupStyles(CuiResId(RID_SVXSTR_GROUP_STYLES
))
357 void CuiConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl
* pStyles
)
359 m_pStylesInfo
= pStyles
;
365 /** examines a component whether it supports XEmbeddedScripts, or provides access to such a
366 component by implementing XScriptInvocationContext.
368 the model which supports the embedded scripts, or <NULL/> if it cannot find such a
371 Reference
< XModel
> lcl_getDocumentWithScripts_throw( const Reference
< XInterface
>& _rxComponent
)
373 Reference
< XEmbeddedScripts
> xScripts( _rxComponent
, UNO_QUERY
);
374 if ( !xScripts
.is() )
376 Reference
< XScriptInvocationContext
> xContext( _rxComponent
, UNO_QUERY
);
378 xScripts
.set( xContext
->getScriptContainer(), UNO_QUERY
);
381 return Reference
< XModel
>( xScripts
, UNO_QUERY
);
385 Reference
< XModel
> lcl_getScriptableDocument_nothrow( const Reference
< XFrame
>& _rxFrame
)
387 Reference
< XModel
> xDocument
;
389 // examine our associated frame
392 OSL_ENSURE( _rxFrame
.is(), "lcl_getScriptableDocument_nothrow: you need to pass a frame to this dialog/tab page!" );
395 // first try the model in the frame
396 Reference
< XController
> xController( _rxFrame
->getController(), UNO_SET_THROW
);
397 xDocument
= lcl_getDocumentWithScripts_throw( xController
->getModel() );
399 if ( !xDocument
.is() )
401 // if there is no suitable document in the frame, try the controller
402 xDocument
= lcl_getDocumentWithScripts_throw( _rxFrame
->getController() );
406 catch( const Exception
& )
414 CuiConfigGroupListBox::CuiConfigGroupListBox(std::unique_ptr
<weld::TreeView
> xTreeView
)
415 : xImp(new SvxConfigGroupBoxResource_Impl())
416 , m_pFunctionListBox(nullptr)
417 , m_pStylesInfo(nullptr)
418 , m_xTreeView(std::move(xTreeView
))
420 m_xTreeView
->connect_row_activated(LINK(this, CuiConfigGroupListBox
, OpenCurrentHdl
));
421 m_xTreeView
->connect_expanding(LINK(this, CuiConfigGroupListBox
, ExpandingHdl
));
422 m_xTreeView
->set_size_request(m_xTreeView
->get_approximate_digit_width() * 35, m_xTreeView
->get_height_rows(9));
425 IMPL_LINK_NOARG(CuiConfigGroupListBox
, OpenCurrentHdl
, weld::TreeView
&, void)
427 std::unique_ptr
<weld::TreeIter
> xIter(m_xTreeView
->make_iterator());
428 bool bValidIter
= m_xTreeView
->get_cursor(xIter
.get());
431 if (!m_xTreeView
->get_row_expanded(*xIter
))
432 m_xTreeView
->expand_row(*xIter
);
434 m_xTreeView
->collapse_row(*xIter
);
437 CuiConfigGroupListBox::~CuiConfigGroupListBox()
442 void CuiConfigGroupListBox::ClearAll()
444 sal_uInt16 nCount
= aArr
.size();
445 for ( sal_uInt16 i
=0; i
<nCount
; ++i
)
447 SfxGroupInfo_Impl
*pData
= aArr
[i
].get();
448 if (pData
->nKind
== SfxCfgKind::GROUP_SCRIPTCONTAINER
)
450 XInterface
* xi
= static_cast<XInterface
*>(pData
->pObject
);
459 m_xTreeView
->clear();
462 void CuiConfigGroupListBox::InitModule()
466 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider(m_xFrame
, css::uno::UNO_QUERY_THROW
);
467 css::uno::Sequence
< sal_Int16
> lGroups
= xProvider
->getSupportedCommandGroups();
468 sal_Int32 c1
= lGroups
.getLength();
473 // Add All Commands category
474 aArr
.push_back(std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_ALLFUNCTIONS
, 0));
475 m_xTreeView
->append(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())),
476 CuiResId(RID_SVXSTR_ALLFUNCTIONS
));
479 for (i1
=0; i1
<c1
; ++i1
)
481 sal_Int16
& rGroupID
= lGroups
[i1
];
482 OUString sGroupID
= OUString::number(rGroupID
);
483 OUString sGroupName
;
487 m_xModuleCategoryInfo
->getByName(sGroupID
) >>= sGroupName
;
488 if (sGroupName
.isEmpty())
491 catch(const css::container::NoSuchElementException
&)
494 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_FUNCTION
, rGroupID
) );
495 m_xTreeView
->append(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())),
499 catch(const css::uno::RuntimeException
&)
501 catch(const css::uno::Exception
&)
505 void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference
< css::script::browse::XBrowseNode
>& xRootNode
,
506 const weld::TreeIter
* pParentEntry
, bool bCheapChildrenOnDemand
)
509 if ( xRootNode
->hasChildNodes() )
511 // tdf#120362: Don't ask to enable disabled Java when filling script list
512 css::uno::ContextLayer
layer(
513 new comphelper::NoEnableJavaInteractionContext(css::uno::getCurrentContext()));
515 Sequence
< Reference
< browse::XBrowseNode
> > children
=
516 xRootNode
->getChildNodes();
517 bool bIsRootNode
= false;
519 OUString
user("user");
520 OUString
share("share");
521 if ( xRootNode
->getName() == "Root" )
526 //To mimic current starbasic behaviour we
527 //need to make sure that only the current document
528 //is displayed in the config tree. Tests below
529 //set the bDisplay flag to FALSE if the current
530 //node is a first level child of the Root and is NOT
531 //either the current document, user or share
532 OUString currentDocTitle
;
533 Reference
< XModel
> xDocument( lcl_getScriptableDocument_nothrow( m_xFrame
) );
534 if ( xDocument
.is() )
536 currentDocTitle
= ::comphelper::DocumentInfo::getDocumentTitle( xDocument
);
539 for ( sal_Int32 n
= 0; n
< children
.getLength(); ++n
)
541 Reference
< browse::XBrowseNode
>& theChild
= children
[n
];
542 bool bDisplay
= true;
543 OUString uiName
= theChild
->getName();
546 if ( ! (theChild
->getName() == user
|| theChild
->getName() == share
||
547 theChild
->getName() == currentDocTitle
) )
553 if ( uiName
== user
)
555 uiName
= xImp
->m_sMyMacros
;
557 else if ( uiName
== share
)
559 uiName
= xImp
->m_sProdMacros
;
563 if (children
[n
]->getType() != browse::BrowseNodeTypes::SCRIPT
&& bDisplay
)
565 // We call acquire on the XBrowseNode so that it does not
566 // get autodestructed and become invalid when accessed later.
569 bool bChildOnDemand
= false;
570 if ( !bCheapChildrenOnDemand
&& children
[n
]->hasChildNodes() )
572 Sequence
< Reference
< browse::XBrowseNode
> > grandchildren
=
573 children
[n
]->getChildNodes();
575 for ( sal_Int32 m
= 0; m
< grandchildren
.getLength(); ++m
)
577 if ( grandchildren
[m
]->getType() == browse::BrowseNodeTypes::CONTAINER
)
579 bChildOnDemand
= true;
580 m
= grandchildren
.getLength();
586 /* i30923 - Would be nice if there was a better
587 * way to determine if a basic lib had children
588 * without having to ask for them (which forces
589 * the library to be loaded */
590 bChildOnDemand
= true;
593 OUString aImage
= GetImage(theChild
, m_xContext
, bIsRootNode
);
595 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_SCRIPTCONTAINER
,
596 0, static_cast<void *>( theChild
.get())));
598 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())));
599 m_xTreeView
->insert(pParentEntry
, -1, &uiName
, &sId
, nullptr, nullptr, &aImage
, bChildOnDemand
, nullptr);
604 catch (RuntimeException
&) {
605 // do nothing, the entry will not be displayed in the UI
609 void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence
<DispatchInformation
>& xCommands
)
611 m_pFunctionListBox
->freeze();
612 for (const auto & rInfo
: xCommands
)
614 OUString sUIName
= MapCommand2UIName(rInfo
.Command
);
615 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::FUNCTION_SLOT
, 0 ) );
616 SfxGroupInfo_Impl
* pGrpInfo
= aArr
.back().get();
617 pGrpInfo
->sCommand
= rInfo
.Command
;
618 pGrpInfo
->sLabel
= sUIName
;
619 m_pFunctionListBox
->append(OUString::number(reinterpret_cast<sal_Int64
>(pGrpInfo
)), sUIName
);
621 m_pFunctionListBox
->thaw();
624 void CuiConfigGroupListBox::Init(const css::uno::Reference
< css::uno::XComponentContext
>& xContext
,
625 const css::uno::Reference
< css::frame::XFrame
>& xFrame
,
626 const OUString
& sModuleLongName
,
629 m_xTreeView
->freeze();
630 ClearAll(); // Remove all old entries from treelist box
632 m_xContext
= xContext
;
636 m_sModuleLongName
= sModuleLongName
;
637 m_xGlobalCategoryInfo
= css::ui::theUICategoryDescription::get( m_xContext
);
638 m_xModuleCategoryInfo
.set(m_xGlobalCategoryInfo
->getByName(m_sModuleLongName
), css::uno::UNO_QUERY_THROW
);
639 m_xUICmdDescription
= css::frame::theUICommandDescription::get( m_xContext
);
644 SAL_INFO("cui.customize", "** ** About to initialise SF Scripts");
645 // Add Scripting Framework entries
646 Reference
< browse::XBrowseNode
> rootNode
;
649 Reference
< browse::XBrowseNodeFactory
> xFac
= browse::theBrowseNodeFactory::get( m_xContext
);
650 rootNode
.set( xFac
->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR
) );
652 catch( Exception
& e
)
654 SAL_INFO("cui.customize", "Caught some exception whilst retrieving browse nodes from factory... Exception: " << e
);
655 // TODO exception handling
663 //We call acquire on the XBrowseNode so that it does not
664 //get autodestructed and become invalid when accessed later.
667 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_SCRIPTCONTAINER
, 0,
668 static_cast<void *>(rootNode
.get())));
669 OUString
aTitle(xImp
->m_sDlgMacros
);
670 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())));
671 m_xTreeView
->insert(nullptr, -1, &aTitle
, &sId
, nullptr, nullptr, nullptr, true, nullptr);
675 //We are only showing scripts not slot APIs so skip
676 //Root node and show location nodes
677 FillScriptList(rootNode
, nullptr, false);
684 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_STYLES
, 0, nullptr ) ); // TODO last parameter should contain user data
685 OUString
sStyle(xImp
->m_aStrGroupStyles
);
686 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())));
687 m_xTreeView
->insert(nullptr, -1, &sStyle
, &sId
, nullptr, nullptr, nullptr, true, nullptr);
691 m_xTreeView
->scroll_to_row(0);
692 m_xTreeView
->select(0);
695 OUString
CuiConfigGroupListBox::GetImage(
696 const Reference
< browse::XBrowseNode
>& node
,
697 Reference
< XComponentContext
> const & xCtx
,
703 if (node
->getName() == "user" || node
->getName() == "share" )
705 aImage
= RID_CUIBMP_HARDDISK
;
710 OUString nodeName
= node
->getName();
711 Reference
<XInterface
> xDocumentModel
= getDocumentModel(xCtx
, nodeName
);
712 if ( xDocumentModel
.is() )
714 Reference
< frame::XModuleManager2
> xModuleManager( frame::ModuleManager::create(xCtx
) );
715 // get the long name of the document:
716 OUString
appModule( xModuleManager
->identify(
718 Sequence
<beans::PropertyValue
> moduleDescr
;
719 Any aAny
= xModuleManager
->getByName(appModule
);
720 if( !( aAny
>>= moduleDescr
) )
722 throw RuntimeException("SFTreeListBox::Init: failed to get PropertyValue");
724 beans::PropertyValue
const * pmoduleDescr
=
725 moduleDescr
.getConstArray();
726 for ( sal_Int32 pos
= moduleDescr
.getLength(); pos
--; )
728 if ( pmoduleDescr
[ pos
].Name
== "ooSetupFactoryEmptyDocumentURL" )
730 pmoduleDescr
[ pos
].Value
>>= factoryURL
;
731 SAL_INFO("cui.customize", "factory url for doc images is " << factoryURL
);
736 if( !factoryURL
.isEmpty() )
738 aImage
= SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL
));
742 aImage
= RID_CUIBMP_DOC
;
748 if( node
->getType() == browse::BrowseNodeTypes::SCRIPT
)
749 aImage
= RID_CUIBMP_MACRO
;
751 aImage
= RID_CUIBMP_LIB
;
756 Reference
< XInterface
>
757 CuiConfigGroupListBox::getDocumentModel( Reference
< XComponentContext
> const & xCtx
, OUString
const & docName
)
759 Reference
< XInterface
> xModel
;
760 Reference
< frame::XDesktop2
> desktop
= frame::Desktop::create( xCtx
);
762 Reference
< container::XEnumerationAccess
> componentsAccess
=
763 desktop
->getComponents();
764 Reference
< container::XEnumeration
> components
=
765 componentsAccess
->createEnumeration();
766 while (components
->hasMoreElements())
768 Reference
< frame::XModel
> model(
769 components
->nextElement(), UNO_QUERY
);
773 ::comphelper::DocumentInfo::getDocumentTitle( model
);
774 if( sTdocUrl
== docName
)
784 OUString
CuiConfigGroupListBox::MapCommand2UIName(const OUString
& sCommand
)
789 css::uno::Reference
< css::container::XNameAccess
> xModuleConf
;
790 m_xUICmdDescription
->getByName(m_sModuleLongName
) >>= xModuleConf
;
791 if (xModuleConf
.is())
793 ::comphelper::SequenceAsHashMap
lProps(xModuleConf
->getByName(sCommand
));
794 sUIName
= lProps
.getUnpackedValueOrDefault("Name", OUString());
797 catch(const css::uno::RuntimeException
&)
799 catch(css::uno::Exception
&)
802 // fallback for missing UINames !?
803 if (sUIName
.isEmpty())
811 void CuiConfigGroupListBox::GroupSelected()
813 A function group or a basic module has been selected.
814 All functions/macros are displayed in the functionlistbox.
817 std::unique_ptr
<weld::TreeIter
> xIter(m_xTreeView
->make_iterator());
818 if (!m_xTreeView
->get_selected(xIter
.get()))
821 SfxGroupInfo_Impl
*pInfo
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(*xIter
).toInt64());
822 m_pFunctionListBox
->freeze();
823 m_pFunctionListBox
->ClearAll();
825 switch ( pInfo
->nKind
)
827 case SfxCfgKind::GROUP_ALLFUNCTIONS
:
829 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider( m_xFrame
, UNO_QUERY
);
830 bool bValidIter
= m_xTreeView
->get_iter_first(*xIter
);
833 SfxGroupInfo_Impl
*pCurrentInfo
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(*xIter
).toInt64());
834 if (pCurrentInfo
->nKind
== SfxCfgKind::GROUP_FUNCTION
)
836 css::uno::Sequence
< css::frame::DispatchInformation
> lCommands
;
839 lCommands
= xProvider
->getConfigurableDispatchInformation( pCurrentInfo
->nUniqueID
);
840 FillFunctionsList( lCommands
);
842 catch ( container::NoSuchElementException
& )
846 bValidIter
= m_xTreeView
->iter_next(*xIter
);
851 case SfxCfgKind::GROUP_FUNCTION
:
853 sal_uInt16 nGroup
= pInfo
->nUniqueID
;
854 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider (m_xFrame
, css::uno::UNO_QUERY_THROW
);
855 css::uno::Sequence
< css::frame::DispatchInformation
> lCommands
= xProvider
->getConfigurableDispatchInformation(nGroup
);
856 FillFunctionsList( lCommands
);
860 case SfxCfgKind::GROUP_SCRIPTCONTAINER
:
862 if (!m_xTreeView
->iter_has_child(*xIter
))
864 Reference
< browse::XBrowseNode
> rootNode(
865 static_cast< browse::XBrowseNode
* >( pInfo
->pObject
) ) ;
868 if ( rootNode
->hasChildNodes() )
870 Sequence
< Reference
< browse::XBrowseNode
> > children
=
871 rootNode
->getChildNodes();
873 for ( sal_Int32 n
= 0; n
< children
.getLength(); ++n
)
875 if (children
[n
]->getType() == browse::BrowseNodeTypes::SCRIPT
)
877 OUString uri
, description
;
879 Reference
< beans::XPropertySet
>xPropSet( children
[n
], UNO_QUERY
);
886 xPropSet
->getPropertyValue("URI");
891 value
= xPropSet
->getPropertyValue("Description");
892 value
>>= description
;
894 catch (Exception
&) {
895 // do nothing, the description will be empty
898 OUString
* pScriptURI
= new OUString( uri
);
900 OUString aImage
= GetImage(children
[n
], Reference
< XComponentContext
>(), false);
901 m_pFunctionListBox
->aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::FUNCTION_SCRIPT
, 0, pScriptURI
));
902 m_pFunctionListBox
->aArr
.back()->sCommand
= uri
;
903 m_pFunctionListBox
->aArr
.back()->sLabel
= children
[n
]->getName();
904 m_pFunctionListBox
->aArr
.back()->sHelpText
= description
;
906 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(m_pFunctionListBox
->aArr
.back().get())));
907 m_pFunctionListBox
->append(sId
, children
[n
]->getName(), aImage
);
912 catch (RuntimeException
&) {
913 // do nothing, the entry will not be displayed in the UI
919 case SfxCfgKind::GROUP_STYLES
:
921 SfxStyleInfo_Impl
* pFamily
= static_cast<SfxStyleInfo_Impl
*>(pInfo
->pObject
);
924 const std::vector
< SfxStyleInfo_Impl
> lStyles
= m_pStylesInfo
->getStyles(pFamily
->sFamily
);
925 for (auto const& lStyle
: lStyles
)
927 SfxStyleInfo_Impl
* pStyle
= new SfxStyleInfo_Impl(lStyle
);
928 m_pFunctionListBox
->aArr
.push_back(std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_STYLES
, 0, pStyle
));
929 m_pFunctionListBox
->aArr
.back()->sCommand
= pStyle
->sCommand
;
930 m_pFunctionListBox
->aArr
.back()->sLabel
= pStyle
->sLabel
;
931 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(m_pFunctionListBox
->aArr
.back().get())));
932 m_pFunctionListBox
->append(sId
, pStyle
->sLabel
);
939 // Do nothing, the list box will stay empty
940 SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast<int>(pInfo
->nKind
) );
944 m_pFunctionListBox
->thaw();
946 if (m_pFunctionListBox
->n_children())
947 m_pFunctionListBox
->select(0);
951 A basic or a library is opened.
953 IMPL_LINK(CuiConfigGroupListBox
, ExpandingHdl
, const weld::TreeIter
&, rIter
, bool)
955 SfxGroupInfo_Impl
*pInfo
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(rIter
).toInt64());
956 switch ( pInfo
->nKind
)
958 case SfxCfgKind::GROUP_SCRIPTCONTAINER
:
960 if (!m_xTreeView
->iter_has_child(rIter
))
962 Reference
< browse::XBrowseNode
> rootNode(
963 static_cast< browse::XBrowseNode
* >( pInfo
->pObject
) ) ;
964 FillScriptList(rootNode
, &rIter
, true /* i30923 */ );
969 case SfxCfgKind::GROUP_STYLES
:
971 if (!m_xTreeView
->iter_has_child(rIter
))
973 const std::vector
<SfxStyleInfo_Impl
> lStyleFamilies
= m_pStylesInfo
->getStyleFamilies();
974 for (auto const& lStyleFamily
: lStyleFamilies
)
976 SfxStyleInfo_Impl
* pFamily
= new SfxStyleInfo_Impl(lStyleFamily
);
977 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_STYLES
, 0, pFamily
));
978 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())));
979 m_xTreeView
->insert(&rIter
, -1, &pFamily
->sLabel
, &sId
, nullptr, nullptr, nullptr, false, nullptr);
986 OSL_FAIL( "Wrong group type!" );
992 void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem
*pItem
)
994 SelectMacro( pItem
->GetBasicManager()->GetName(),
995 pItem
->GetQualifiedName() );
998 void CuiConfigGroupListBox::SelectMacro( const OUString
& rBasic
,
999 const OUString
& rMacro
)
1001 const OUString
aBasicName(rBasic
+ " " + xImp
->m_sMacros
);
1002 sal_Int32 nIdx
{rMacro
.lastIndexOf('.')};
1003 const OUString
aMethod( rMacro
.copy(nIdx
+1) );
1008 // string contains at least 2 tokens
1009 nIdx
= rMacro
.lastIndexOf('.', nIdx
);
1012 // string contains at least 3 tokens
1013 aLib
= rMacro
.getToken( 0, '.' );
1014 aModule
= rMacro
.getToken( 0, '.', ++nIdx
);
1018 std::unique_ptr
<weld::TreeIter
> xIter
= m_xTreeView
->make_iterator();
1019 if (!m_xTreeView
->get_iter_first(*xIter
))
1024 OUString aEntryBas
= m_xTreeView
->get_text(*xIter
);
1025 if (aEntryBas
== aBasicName
)
1027 m_xTreeView
->expand_row(*xIter
);
1028 std::unique_ptr
<weld::TreeIter
> xLibIter
= m_xTreeView
->make_iterator(xIter
.get());
1029 if (m_xTreeView
->get_iter_first(*xLibIter
))
1033 OUString aEntryLib
= m_xTreeView
->get_text(*xLibIter
);
1034 if (aEntryLib
== aLib
)
1036 m_xTreeView
->expand_row(*xLibIter
);
1037 std::unique_ptr
<weld::TreeIter
> xModIter
= m_xTreeView
->make_iterator(xLibIter
.get());
1038 if (m_xTreeView
->get_iter_first(*xModIter
))
1042 OUString aEntryMod
= m_xTreeView
->get_text(*xModIter
);
1043 if ( aEntryMod
== aModule
)
1045 m_xTreeView
->expand_row(*xModIter
);
1046 m_xTreeView
->scroll_to_row(*xModIter
);
1047 m_xTreeView
->select(*xModIter
);
1048 for (int i
= 0, nCount
= m_pFunctionListBox
->n_children(); i
< nCount
; ++i
)
1050 OUString aEntryMethod
= m_pFunctionListBox
->get_text(i
);
1051 if (aEntryMethod
== aMethod
)
1053 m_pFunctionListBox
->select(i
);
1054 m_pFunctionListBox
->scroll_to_row(i
);
1059 } while (m_xTreeView
->iter_next_sibling(*xModIter
));
1062 } while (m_xTreeView
->iter_next_sibling(*xLibIter
));
1065 } while (m_xTreeView
->iter_next_sibling(*xIter
));
1069 * Implementation of SvxScriptSelectorDialog
1071 * This dialog is used for selecting Slot API commands
1072 * and Scripting Framework Scripts.
1075 SvxScriptSelectorDialog::SvxScriptSelectorDialog(
1076 weld::Window
* pParent
, bool bShowSlots
, const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
1077 : GenericDialogController(pParent
, "cui/ui/macroselectordialog.ui", "MacroSelectorDialog")
1078 , m_bShowSlots(bShowSlots
)
1079 , m_xDialogDescription(m_xBuilder
->weld_label(bShowSlots
? "helptoolbar" : "helpmacro"))
1080 , m_xCategories(new CuiConfigGroupListBox(m_xBuilder
->weld_tree_view("categories")))
1081 , m_xCommands(new CuiConfigFunctionListBox(m_xBuilder
->weld_tree_view("commands")))
1082 , m_xLibraryFT(m_xBuilder
->weld_label("libraryft"))
1083 , m_xCategoryFT(m_xBuilder
->weld_label("categoryft"))
1084 , m_xMacronameFT(m_xBuilder
->weld_label("macronameft"))
1085 , m_xCommandsFT(m_xBuilder
->weld_label("commandsft"))
1086 , m_xOKButton(m_xBuilder
->weld_button(bShowSlots
? "add" : "ok"))
1087 , m_xCancelButton(m_xBuilder
->weld_button(bShowSlots
? "close" : "cancel"))
1088 , m_xDescriptionText(m_xBuilder
->weld_text_view("description"))
1092 // If we are showing Slot API commands update labels in the UI
1093 m_xDialog
->set_title(CuiResId(RID_SVXSTR_SELECTOR_ADD_COMMANDS
));
1095 m_xCancelButton
->show();
1096 m_xDialogDescription
->show();
1097 m_xOKButton
->show();
1099 m_xLibraryFT
->set_visible(!m_bShowSlots
);
1100 m_xCategoryFT
->set_visible(m_bShowSlots
);
1101 m_xMacronameFT
->set_visible(!m_bShowSlots
);
1102 m_xCommandsFT
->set_visible(m_bShowSlots
);
1104 const OUString
aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame
));
1105 m_xCategories
->SetFunctionListBox(m_xCommands
.get());
1106 m_xCategories
->Init(comphelper::getProcessComponentContext(), xFrame
, aModuleName
, bShowSlots
);
1108 m_xCategories
->connect_changed(
1109 LINK( this, SvxScriptSelectorDialog
, SelectHdl
) );
1110 m_xCommands
->connect_changed( LINK( this, SvxScriptSelectorDialog
, SelectHdl
) );
1111 m_xCommands
->connect_row_activated( LINK( this, SvxScriptSelectorDialog
, FunctionDoubleClickHdl
) );
1113 m_xOKButton
->connect_clicked( LINK( this, SvxScriptSelectorDialog
, ClickHdl
) );
1114 m_xCancelButton
->connect_clicked( LINK( this, SvxScriptSelectorDialog
, ClickHdl
) );
1116 m_sDefaultDesc
= m_xDescriptionText
->get_text();
1118 // Support style commands
1119 uno::Reference
<frame::XController
> xController
;
1120 uno::Reference
<frame::XModel
> xModel
;
1122 xController
= xFrame
->getController();
1123 if (xController
.is())
1124 xModel
= xController
->getModel();
1126 m_aStylesInfo
.init(aModuleName
, xModel
);
1127 m_xCategories
->SetStylesInfo(&m_aStylesInfo
);
1132 SvxScriptSelectorDialog::~SvxScriptSelectorDialog()
1136 IMPL_LINK(SvxScriptSelectorDialog
, SelectHdl
, weld::TreeView
&, rCtrl
, void)
1138 if (&rCtrl
== &m_xCategories
->get_widget())
1140 m_xCategories
->GroupSelected();
1145 IMPL_LINK_NOARG(SvxScriptSelectorDialog
, FunctionDoubleClickHdl
, weld::TreeView
&, void)
1147 if (m_xOKButton
->get_sensitive())
1148 ClickHdl(*m_xOKButton
);
1151 // Check if command is selected and enable the OK button accordingly
1152 // Grab the help text for this id if available and update the description field
1154 SvxScriptSelectorDialog::UpdateUI()
1156 OUString url
= GetScriptURL();
1157 if ( !url
.isEmpty() )
1159 OUString sMessage
= m_xCommands
->GetHelpText();
1160 m_xDescriptionText
->set_text(sMessage
.isEmpty() ? m_sDefaultDesc
: sMessage
);
1162 m_xOKButton
->set_sensitive(true);
1166 m_xDescriptionText
->set_text(m_sDefaultDesc
);
1167 m_xOKButton
->set_sensitive(false);
1171 IMPL_LINK(SvxScriptSelectorDialog
, ClickHdl
, weld::Button
&, rButton
, void)
1173 if (&rButton
== m_xCancelButton
.get())
1175 m_xDialog
->response(RET_CANCEL
);
1177 else if (&rButton
== m_xOKButton
.get())
1179 // If we are displaying Slot API commands then this the dialog is being
1180 // run from Tools/Configure and we should not close it
1181 if ( !m_bShowSlots
)
1183 m_xDialog
->response(RET_OK
);
1187 // Select the next entry in the list if possible
1188 std::unique_ptr
<weld::TreeIter
> xIter
= m_xCommands
->make_iterator();
1189 if (m_xCommands
->get_selected(xIter
.get()) && m_xCommands
->iter_next_sibling(*xIter
))
1190 m_xCommands
->select(*xIter
);
1196 SvxScriptSelectorDialog::SetRunLabel()
1198 m_xOKButton
->set_label(CuiResId(RID_SVXSTR_SELECTOR_RUN
));
1202 SvxScriptSelectorDialog::GetScriptURL() const
1206 std::unique_ptr
<weld::TreeIter
> xIter
= m_xCommands
->make_iterator();
1207 if (m_xCommands
->get_selected(xIter
.get()))
1209 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xCommands
->get_id(*xIter
).toInt64());
1210 if ( ( pData
->nKind
== SfxCfgKind::FUNCTION_SLOT
)
1211 || ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
1212 || ( pData
->nKind
== SfxCfgKind::GROUP_STYLES
)
1215 result
= pData
->sCommand
;
1222 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */