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>
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/container/XEnumerationAccess.hpp>
24 #include <com/sun/star/container/XEnumeration.hpp>
25 #include <com/sun/star/document/XScriptInvocationContext.hpp>
26 #include <com/sun/star/frame/ModuleManager.hpp>
27 #include <com/sun/star/frame/Desktop.hpp>
28 #include <com/sun/star/frame/theUICommandDescription.hpp>
29 #include <com/sun/star/frame/XDispatchInformationProvider.hpp>
30 #include <com/sun/star/script/browse/XBrowseNode.hpp>
31 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
32 #include <com/sun/star/script/browse/theBrowseNodeFactory.hpp>
33 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
34 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
35 #include <com/sun/star/uno/RuntimeException.hpp>
36 #include <com/sun/star/ui/theUICategoryDescription.hpp>
38 #include <basic/basmgr.hxx>
39 #include <tools/urlobj.hxx>
40 #include <strings.hrc>
41 #include <bitmaps.hlst>
42 #include <sfx2/minfitem.hxx>
43 #include <comphelper/SetFlagContextHelper.hxx>
44 #include <comphelper/documentinfo.hxx>
45 #include <comphelper/processfactory.hxx>
46 #include <comphelper/sequenceashashmap.hxx>
47 #include <svtools/imagemgr.hxx>
48 #include <sal/log.hxx>
49 #include <osl/diagnose.h>
50 #include <dialmgr.hxx>
51 #include <tools/diagnose_ex.h>
52 #include <vcl/commandinfoprovider.hxx>
53 #include <vcl/help.hxx>
54 #include <vcl/svapp.hxx>
56 using namespace ::com::sun::star
;
57 using namespace ::com::sun::star::uno
;
58 using namespace ::com::sun::star::script
;
59 using namespace ::com::sun::star::frame
;
60 using namespace ::com::sun::star::document
;
62 SfxStylesInfo_Impl::SfxStylesInfo_Impl()
65 void SfxStylesInfo_Impl::init(const OUString
& rModuleName
, const css::uno::Reference
< css::frame::XModel
>& xModel
)
67 m_aModuleName
= rModuleName
;
71 static const char CMDURL_STYLEPROT_ONLY
[] = ".uno:StyleApply?";
72 static const char CMDURL_SPART_ONLY
[] = "Style:string=";
73 static const char CMDURL_FPART_ONLY
[] = "FamilyName:string=";
75 static const char STYLEPROP_UINAME
[] = "DisplayName";
77 OUString
SfxStylesInfo_Impl::generateCommand(const OUString
& sFamily
, const OUString
& sStyle
)
79 return ".uno:StyleApply?Style:string="
81 + "&FamilyName:string="
85 bool SfxStylesInfo_Impl::parseStyleCommand(SfxStyleInfo_Impl
& aStyle
)
87 static const sal_Int32 LEN_STYLEPROT
= strlen(CMDURL_STYLEPROT_ONLY
);
88 static const sal_Int32 LEN_SPART
= strlen(CMDURL_SPART_ONLY
);
89 static const sal_Int32 LEN_FPART
= strlen(CMDURL_FPART_ONLY
);
91 if (!aStyle
.sCommand
.startsWith(CMDURL_STYLEPROT_ONLY
))
94 aStyle
.sFamily
.clear();
95 aStyle
.sStyle
.clear();
97 sal_Int32 nCmdLen
= aStyle
.sCommand
.getLength();
98 OUString sCmdArgs
= aStyle
.sCommand
.copy(LEN_STYLEPROT
, nCmdLen
-LEN_STYLEPROT
);
99 sal_Int32 i
= sCmdArgs
.indexOf('&');
103 OUString sArg
= sCmdArgs
.copy(0, i
);
104 if (sArg
.startsWith(CMDURL_SPART_ONLY
))
105 aStyle
.sStyle
= sArg
.copy(LEN_SPART
);
106 else if (sArg
.startsWith(CMDURL_FPART_ONLY
))
107 aStyle
.sFamily
= sArg
.copy(LEN_FPART
);
109 sArg
= sCmdArgs
.copy(i
+1, sCmdArgs
.getLength()-i
-1);
110 if (sArg
.startsWith(CMDURL_SPART_ONLY
))
111 aStyle
.sStyle
= sArg
.copy(LEN_SPART
);
112 else if (sArg
.startsWith(CMDURL_FPART_ONLY
))
113 aStyle
.sFamily
= sArg
.copy(LEN_FPART
);
115 return !(aStyle
.sFamily
.isEmpty() || aStyle
.sStyle
.isEmpty());
118 void SfxStylesInfo_Impl::getLabel4Style(SfxStyleInfo_Impl
& aStyle
)
122 css::uno::Reference
< css::style::XStyleFamiliesSupplier
> xModel(m_xDoc
, css::uno::UNO_QUERY
);
124 css::uno::Reference
< css::container::XNameAccess
> xFamilies
;
126 xFamilies
= xModel
->getStyleFamilies();
128 css::uno::Reference
< css::container::XNameAccess
> xStyleSet
;
130 xFamilies
->getByName(aStyle
.sFamily
) >>= xStyleSet
;
132 css::uno::Reference
< css::beans::XPropertySet
> xStyle
;
134 xStyleSet
->getByName(aStyle
.sStyle
) >>= xStyle
;
136 aStyle
.sLabel
.clear();
138 xStyle
->getPropertyValue(STYLEPROP_UINAME
) >>= aStyle
.sLabel
;
140 catch(const css::uno::RuntimeException
&)
142 catch(const css::uno::Exception
&)
143 { aStyle
.sLabel
.clear(); }
145 if (aStyle
.sLabel
.isEmpty())
147 aStyle
.sLabel
= aStyle
.sCommand
;
151 std::vector
< SfxStyleInfo_Impl
> SfxStylesInfo_Impl::getStyleFamilies() const
153 // It's an optional interface!
154 css::uno::Reference
< css::style::XStyleFamiliesSupplier
> xModel(m_xDoc
, css::uno::UNO_QUERY
);
156 return std::vector
< SfxStyleInfo_Impl
>();
158 css::uno::Reference
< css::container::XNameAccess
> xCont
= xModel
->getStyleFamilies();
159 const css::uno::Sequence
< OUString
> lFamilyNames
= xCont
->getElementNames();
160 std::vector
< SfxStyleInfo_Impl
> lFamilies
;
161 for (const auto& aFamily
: lFamilyNames
)
163 if ((aFamily
== "CellStyles" && m_aModuleName
!= "com.sun.star.sheet.SpreadsheetDocument") ||
164 aFamily
== "cell" || aFamily
== "table" || aFamily
== "Default")
167 SfxStyleInfo_Impl aFamilyInfo
;
168 aFamilyInfo
.sFamily
= aFamily
;
172 css::uno::Reference
< css::beans::XPropertySet
> xFamilyInfo
;
173 xCont
->getByName(aFamilyInfo
.sFamily
) >>= xFamilyInfo
;
174 if (!xFamilyInfo
.is())
176 // TODO_AS currently there is no support for an UIName property .. use internal family name instead
177 aFamilyInfo
.sLabel
= aFamilyInfo
.sFamily
;
180 xFamilyInfo
->getPropertyValue(STYLEPROP_UINAME
) >>= aFamilyInfo
.sLabel
;
182 catch(const css::uno::RuntimeException
&)
184 catch(const css::uno::Exception
&)
185 { return std::vector
< SfxStyleInfo_Impl
>(); }
187 lFamilies
.push_back(aFamilyInfo
);
193 std::vector
< SfxStyleInfo_Impl
> SfxStylesInfo_Impl::getStyles(const OUString
& sFamily
)
195 css::uno::Sequence
< OUString
> lStyleNames
;
196 css::uno::Reference
< css::style::XStyleFamiliesSupplier
> xModel(m_xDoc
, css::uno::UNO_QUERY_THROW
);
197 css::uno::Reference
< css::container::XNameAccess
> xFamilies
= xModel
->getStyleFamilies();
198 css::uno::Reference
< css::container::XNameAccess
> xStyleSet
;
201 xFamilies
->getByName(sFamily
) >>= xStyleSet
;
202 lStyleNames
= xStyleSet
->getElementNames();
204 catch(const css::uno::RuntimeException
&)
206 catch(const css::uno::Exception
&)
207 { return std::vector
< SfxStyleInfo_Impl
>(); }
209 std::vector
< SfxStyleInfo_Impl
> lStyles
;
210 sal_Int32 c
= lStyleNames
.getLength();
214 SfxStyleInfo_Impl aStyleInfo
;
215 aStyleInfo
.sFamily
= sFamily
;
216 aStyleInfo
.sStyle
= lStyleNames
[i
];
217 aStyleInfo
.sCommand
= SfxStylesInfo_Impl::generateCommand(aStyleInfo
.sFamily
, aStyleInfo
.sStyle
);
221 css::uno::Reference
< css::beans::XPropertySet
> xStyle
;
222 xStyleSet
->getByName(aStyleInfo
.sStyle
) >>= xStyle
;
225 xStyle
->getPropertyValue("DisplayName") >>= aStyleInfo
.sLabel
;
227 catch(const css::uno::RuntimeException
&)
229 catch(const css::uno::Exception
&)
232 lStyles
.push_back(aStyleInfo
);
237 OUString
CuiConfigFunctionListBox::GetHelpText( bool bConsiderParent
)
239 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(get_selected_id().toInt64());
242 if ( pData
->nKind
== SfxCfgKind::FUNCTION_SLOT
)
245 return Application::GetHelp()->GetHelpText(pData
->sCommand
, m_xTreeView
.get());
247 return Application::GetHelp()->GetHelpText(pData
->sCommand
, static_cast<weld::Widget
*>(nullptr));
249 else if ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
251 return pData
->sHelpText
;
257 OUString
CuiConfigFunctionListBox::GetCurCommand() const
259 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(get_selected_id().toInt64());
262 return pData
->sCommand
;
265 OUString
CuiConfigFunctionListBox::GetCurLabel() const
267 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(get_selected_id().toInt64());
270 if (!pData
->sLabel
.isEmpty())
271 return pData
->sLabel
;
272 return pData
->sCommand
;
275 CuiConfigFunctionListBox::CuiConfigFunctionListBox(std::unique_ptr
<weld::TreeView
> xTreeView
)
276 : m_xTreeView(std::move(xTreeView
))
277 , m_xScratchIter(m_xTreeView
->make_iterator())
279 m_xTreeView
->make_sorted();
280 m_xTreeView
->set_size_request(m_xTreeView
->get_approximate_digit_width() * 35, m_xTreeView
->get_height_rows(9));
283 CuiConfigFunctionListBox::~CuiConfigFunctionListBox()
288 void CuiConfigFunctionListBox::ClearAll()
290 Deletes all entries in the FunctionListBox, all UserData and all
291 possibly existing MacroInfo.
294 sal_uInt16 nCount
= aArr
.size();
295 for ( sal_uInt16 i
=0; i
<nCount
; ++i
)
297 SfxGroupInfo_Impl
*pData
= aArr
[i
].get();
299 if ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
301 OUString
* pScriptURI
= static_cast<OUString
*>(pData
->pObject
);
305 if ( pData
->nKind
== SfxCfgKind::GROUP_SCRIPTCONTAINER
)
307 XInterface
* xi
= static_cast<XInterface
*>(pData
->pObject
);
316 m_xTreeView
->clear();
319 OUString
CuiConfigFunctionListBox::GetSelectedScriptURI() const
321 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(get_selected_id().toInt64());
322 if (pData
&& pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
323 return *static_cast<OUString
*>(pData
->pObject
);
327 struct SvxConfigGroupBoxResource_Impl
329 OUString m_sMyMacros
;
330 OUString m_sProdMacros
;
332 OUString m_sDlgMacros
;
333 OUString m_aStrGroupStyles
;
335 SvxConfigGroupBoxResource_Impl();
338 SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() :
339 m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS
)),
340 m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS
)),
341 m_sMacros(CuiResId(RID_SVXSTR_BASICMACROS
)),
342 m_sDlgMacros(CuiResId(RID_SVXSTR_PRODMACROS
)),
343 m_aStrGroupStyles(CuiResId(RID_SVXSTR_GROUP_STYLES
))
347 void CuiConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl
* pStyles
)
349 m_pStylesInfo
= pStyles
;
355 /** examines a component whether it supports XEmbeddedScripts, or provides access to such a
356 component by implementing XScriptInvocationContext.
358 the model which supports the embedded scripts, or <NULL/> if it cannot find such a
361 Reference
< XModel
> lcl_getDocumentWithScripts_throw( const Reference
< XInterface
>& _rxComponent
)
363 Reference
< XEmbeddedScripts
> xScripts( _rxComponent
, UNO_QUERY
);
364 if ( !xScripts
.is() )
366 Reference
< XScriptInvocationContext
> xContext( _rxComponent
, UNO_QUERY
);
368 xScripts
= xContext
->getScriptContainer();
371 return Reference
< XModel
>( xScripts
, UNO_QUERY
);
375 Reference
< XModel
> lcl_getScriptableDocument_nothrow( const Reference
< XFrame
>& _rxFrame
)
377 Reference
< XModel
> xDocument
;
379 // examine our associated frame
382 OSL_ENSURE( _rxFrame
.is(), "lcl_getScriptableDocument_nothrow: you need to pass a frame to this dialog/tab page!" );
385 // first try the model in the frame
386 Reference
< XController
> xController( _rxFrame
->getController(), UNO_SET_THROW
);
387 xDocument
= lcl_getDocumentWithScripts_throw( xController
->getModel() );
389 if ( !xDocument
.is() )
391 // if there is no suitable document in the frame, try the controller
392 xDocument
= lcl_getDocumentWithScripts_throw( _rxFrame
->getController() );
396 catch( const Exception
& )
404 CuiConfigGroupListBox::CuiConfigGroupListBox(std::unique_ptr
<weld::TreeView
> xTreeView
)
405 : xImp(new SvxConfigGroupBoxResource_Impl())
406 , m_pFunctionListBox(nullptr)
407 , m_pStylesInfo(nullptr)
408 , m_xTreeView(std::move(xTreeView
))
410 m_xTreeView
->connect_expanding(LINK(this, CuiConfigGroupListBox
, ExpandingHdl
));
411 m_xTreeView
->set_size_request(m_xTreeView
->get_approximate_digit_width() * 35, m_xTreeView
->get_height_rows(9));
414 CuiConfigGroupListBox::~CuiConfigGroupListBox()
419 void CuiConfigGroupListBox::ClearAll()
421 sal_uInt16 nCount
= aArr
.size();
422 for ( sal_uInt16 i
=0; i
<nCount
; ++i
)
424 SfxGroupInfo_Impl
*pData
= aArr
[i
].get();
425 if (pData
->nKind
== SfxCfgKind::GROUP_SCRIPTCONTAINER
)
427 XInterface
* xi
= static_cast<XInterface
*>(pData
->pObject
);
436 m_xTreeView
->clear();
439 void CuiConfigGroupListBox::InitModule()
443 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider(m_xFrame
, css::uno::UNO_QUERY_THROW
);
444 css::uno::Sequence
< sal_Int16
> lGroups
= xProvider
->getSupportedCommandGroups();
445 sal_Int32 c1
= lGroups
.getLength();
450 // Add All Commands category
451 aArr
.push_back(std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_ALLFUNCTIONS
, 0));
452 m_xTreeView
->append(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())),
453 CuiResId(RID_SVXSTR_ALLFUNCTIONS
));
456 for (i1
=0; i1
<c1
; ++i1
)
458 sal_Int16
& rGroupID
= lGroups
[i1
];
459 OUString sGroupID
= OUString::number(rGroupID
);
460 OUString sGroupName
;
464 m_xModuleCategoryInfo
->getByName(sGroupID
) >>= sGroupName
;
465 if (sGroupName
.isEmpty())
468 catch(const css::container::NoSuchElementException
&)
471 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_FUNCTION
, rGroupID
) );
472 m_xTreeView
->append(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())),
476 catch(const css::uno::RuntimeException
&)
478 catch(const css::uno::Exception
&)
482 void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference
< css::script::browse::XBrowseNode
>& xRootNode
,
483 const weld::TreeIter
* pParentEntry
, bool bCheapChildrenOnDemand
)
486 if ( xRootNode
->hasChildNodes() )
488 // tdf#120362: Don't ask to enable disabled Java when filling script list
489 css::uno::ContextLayer
layer(comphelper::NoEnableJavaInteractionContext());
491 Sequence
< Reference
< browse::XBrowseNode
> > children
=
492 xRootNode
->getChildNodes();
493 bool bIsRootNode
= false;
495 OUString
user("user");
496 OUString
share("share");
497 if ( xRootNode
->getName() == "Root" )
502 //To mimic current starbasic behaviour we
503 //need to make sure that only the current document
504 //is displayed in the config tree. Tests below
505 //set the bDisplay flag to FALSE if the current
506 //node is a first level child of the Root and is NOT
507 //either the current document, user or share
508 OUString currentDocTitle
;
509 Reference
< XModel
> xDocument( lcl_getScriptableDocument_nothrow( m_xFrame
) );
510 if ( xDocument
.is() )
512 currentDocTitle
= ::comphelper::DocumentInfo::getDocumentTitle( xDocument
);
515 for ( sal_Int32 n
= 0; n
< children
.getLength(); ++n
)
517 Reference
< browse::XBrowseNode
>& theChild
= children
[n
];
518 bool bDisplay
= true;
519 OUString uiName
= theChild
->getName();
522 if ( ! (theChild
->getName() == user
|| theChild
->getName() == share
||
523 theChild
->getName() == currentDocTitle
) )
529 if ( uiName
== user
)
531 uiName
= xImp
->m_sMyMacros
;
533 else if ( uiName
== share
)
535 uiName
= xImp
->m_sProdMacros
;
539 if (children
[n
]->getType() != browse::BrowseNodeTypes::SCRIPT
&& bDisplay
)
541 // We call acquire on the XBrowseNode so that it does not
542 // get autodestructed and become invalid when accessed later.
545 bool bChildOnDemand
= false;
546 if ( !bCheapChildrenOnDemand
&& children
[n
]->hasChildNodes() )
548 Sequence
< Reference
< browse::XBrowseNode
> > grandchildren
=
549 children
[n
]->getChildNodes();
551 for ( sal_Int32 m
= 0; m
< grandchildren
.getLength(); ++m
)
553 if ( grandchildren
[m
]->getType() == browse::BrowseNodeTypes::CONTAINER
)
555 bChildOnDemand
= true;
556 m
= grandchildren
.getLength();
562 /* i30923 - Would be nice if there was a better
563 * way to determine if a basic lib had children
564 * without having to ask for them (which forces
565 * the library to be loaded */
566 bChildOnDemand
= true;
569 OUString aImage
= GetImage(theChild
, m_xContext
, bIsRootNode
);
571 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_SCRIPTCONTAINER
,
572 0, static_cast<void *>( theChild
.get())));
574 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())));
575 m_xTreeView
->insert(pParentEntry
, -1, &uiName
, &sId
, nullptr, nullptr, &aImage
, bChildOnDemand
, nullptr);
580 catch (RuntimeException
&) {
581 // do nothing, the entry will not be displayed in the UI
585 void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence
<DispatchInformation
>& xCommands
)
587 m_pFunctionListBox
->freeze();
588 for (const auto & rInfo
: xCommands
)
590 OUString sUIName
= MapCommand2UIName(rInfo
.Command
);
591 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::FUNCTION_SLOT
, 0 ) );
592 SfxGroupInfo_Impl
* pGrpInfo
= aArr
.back().get();
593 pGrpInfo
->sCommand
= rInfo
.Command
;
594 pGrpInfo
->sLabel
= sUIName
;
595 m_pFunctionListBox
->append(OUString::number(reinterpret_cast<sal_Int64
>(pGrpInfo
)), sUIName
);
597 m_pFunctionListBox
->thaw();
600 void CuiConfigGroupListBox::Init(const css::uno::Reference
< css::uno::XComponentContext
>& xContext
,
601 const css::uno::Reference
< css::frame::XFrame
>& xFrame
,
602 const OUString
& sModuleLongName
,
605 m_xTreeView
->freeze();
606 ClearAll(); // Remove all old entries from treelist box
608 m_xContext
= xContext
;
612 m_sModuleLongName
= sModuleLongName
;
613 m_xGlobalCategoryInfo
= css::ui::theUICategoryDescription::get( m_xContext
);
614 m_xModuleCategoryInfo
.set(m_xGlobalCategoryInfo
->getByName(m_sModuleLongName
), css::uno::UNO_QUERY_THROW
);
615 m_xUICmdDescription
= css::frame::theUICommandDescription::get( m_xContext
);
620 SAL_INFO("cui.customize", "** ** About to initialise SF Scripts");
621 // Add Scripting Framework entries
622 Reference
< browse::XBrowseNode
> rootNode
;
625 Reference
< browse::XBrowseNodeFactory
> xFac
= browse::theBrowseNodeFactory::get( m_xContext
);
626 rootNode
.set( xFac
->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR
) );
628 catch( const Exception
& )
630 TOOLS_WARN_EXCEPTION("cui.customize", "Caught some exception whilst retrieving browse nodes from factory");
631 // TODO exception handling
639 //We call acquire on the XBrowseNode so that it does not
640 //get autodestructed and become invalid when accessed later.
643 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_SCRIPTCONTAINER
, 0,
644 static_cast<void *>(rootNode
.get())));
645 OUString
aTitle(xImp
->m_sDlgMacros
);
646 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())));
647 m_xTreeView
->insert(nullptr, -1, &aTitle
, &sId
, nullptr, nullptr, nullptr, true, nullptr);
651 //We are only showing scripts not slot APIs so skip
652 //Root node and show location nodes
653 FillScriptList(rootNode
, nullptr, false);
660 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_STYLES
, 0, nullptr ) ); // TODO last parameter should contain user data
661 OUString
sStyle(xImp
->m_aStrGroupStyles
);
662 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())));
663 m_xTreeView
->insert(nullptr, -1, &sStyle
, &sId
, nullptr, nullptr, nullptr, true, nullptr);
667 m_xTreeView
->scroll_to_row(0);
668 m_xTreeView
->select(0);
671 OUString
CuiConfigGroupListBox::GetImage(
672 const Reference
< browse::XBrowseNode
>& node
,
673 Reference
< XComponentContext
> const & xCtx
,
679 if (node
->getName() == "user" || node
->getName() == "share" )
681 aImage
= RID_CUIBMP_HARDDISK
;
686 OUString nodeName
= node
->getName();
687 Reference
<XInterface
> xDocumentModel
= getDocumentModel(xCtx
, nodeName
);
688 if ( xDocumentModel
.is() )
690 Reference
< frame::XModuleManager2
> xModuleManager( frame::ModuleManager::create(xCtx
) );
691 // get the long name of the document:
692 OUString
appModule( xModuleManager
->identify(
694 Sequence
<beans::PropertyValue
> moduleDescr
;
695 Any aAny
= xModuleManager
->getByName(appModule
);
696 if( !( aAny
>>= moduleDescr
) )
698 throw RuntimeException("SFTreeListBox::Init: failed to get PropertyValue");
700 beans::PropertyValue
const * pmoduleDescr
=
701 moduleDescr
.getConstArray();
702 for ( sal_Int32 pos
= moduleDescr
.getLength(); pos
--; )
704 if ( pmoduleDescr
[ pos
].Name
== "ooSetupFactoryEmptyDocumentURL" )
706 pmoduleDescr
[ pos
].Value
>>= factoryURL
;
707 SAL_INFO("cui.customize", "factory url for doc images is " << factoryURL
);
712 if( !factoryURL
.isEmpty() )
714 aImage
= SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL
));
718 aImage
= RID_CUIBMP_DOC
;
724 if( node
->getType() == browse::BrowseNodeTypes::SCRIPT
)
725 aImage
= RID_CUIBMP_MACRO
;
727 aImage
= RID_CUIBMP_LIB
;
732 Reference
< XInterface
>
733 CuiConfigGroupListBox::getDocumentModel( Reference
< XComponentContext
> const & xCtx
, OUString
const & docName
)
735 Reference
< XInterface
> xModel
;
736 Reference
< frame::XDesktop2
> desktop
= frame::Desktop::create( xCtx
);
738 Reference
< container::XEnumerationAccess
> componentsAccess
=
739 desktop
->getComponents();
740 Reference
< container::XEnumeration
> components
=
741 componentsAccess
->createEnumeration();
742 while (components
->hasMoreElements())
744 Reference
< frame::XModel
> model(
745 components
->nextElement(), UNO_QUERY
);
749 ::comphelper::DocumentInfo::getDocumentTitle( model
);
750 if( sTdocUrl
== docName
)
760 OUString
CuiConfigGroupListBox::MapCommand2UIName(const OUString
& sCommand
)
765 css::uno::Reference
< css::container::XNameAccess
> xModuleConf
;
766 m_xUICmdDescription
->getByName(m_sModuleLongName
) >>= xModuleConf
;
767 if (xModuleConf
.is())
769 ::comphelper::SequenceAsHashMap
lProps(xModuleConf
->getByName(sCommand
));
770 sUIName
= lProps
.getUnpackedValueOrDefault("Name", OUString());
773 catch(const css::uno::RuntimeException
&)
775 catch(css::uno::Exception
&)
778 // fallback for missing UINames !?
779 if (sUIName
.isEmpty())
787 void CuiConfigGroupListBox::GroupSelected()
789 A function group or a basic module has been selected.
790 All functions/macros are displayed in the functionlistbox.
793 std::unique_ptr
<weld::TreeIter
> xIter(m_xTreeView
->make_iterator());
794 if (!m_xTreeView
->get_selected(xIter
.get()))
797 SfxGroupInfo_Impl
*pInfo
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(*xIter
).toInt64());
798 m_pFunctionListBox
->freeze();
799 m_pFunctionListBox
->ClearAll();
801 switch ( pInfo
->nKind
)
803 case SfxCfgKind::GROUP_ALLFUNCTIONS
:
805 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider( m_xFrame
, UNO_QUERY
);
806 bool bValidIter
= m_xTreeView
->get_iter_first(*xIter
);
809 SfxGroupInfo_Impl
*pCurrentInfo
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(*xIter
).toInt64());
810 if (pCurrentInfo
->nKind
== SfxCfgKind::GROUP_FUNCTION
)
812 css::uno::Sequence
< css::frame::DispatchInformation
> lCommands
;
815 lCommands
= xProvider
->getConfigurableDispatchInformation( pCurrentInfo
->nUniqueID
);
816 FillFunctionsList( lCommands
);
818 catch ( container::NoSuchElementException
& )
822 bValidIter
= m_xTreeView
->iter_next(*xIter
);
827 case SfxCfgKind::GROUP_FUNCTION
:
829 sal_uInt16 nGroup
= pInfo
->nUniqueID
;
830 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider (m_xFrame
, css::uno::UNO_QUERY_THROW
);
831 css::uno::Sequence
< css::frame::DispatchInformation
> lCommands
= xProvider
->getConfigurableDispatchInformation(nGroup
);
832 FillFunctionsList( lCommands
);
836 case SfxCfgKind::GROUP_SCRIPTCONTAINER
:
838 if (!m_xTreeView
->iter_has_child(*xIter
))
840 Reference
< browse::XBrowseNode
> rootNode(
841 static_cast< browse::XBrowseNode
* >( pInfo
->pObject
) ) ;
844 if ( rootNode
->hasChildNodes() )
846 Sequence
< Reference
< browse::XBrowseNode
> > children
=
847 rootNode
->getChildNodes();
849 for ( sal_Int32 n
= 0; n
< children
.getLength(); ++n
)
851 if (children
[n
]->getType() == browse::BrowseNodeTypes::SCRIPT
)
853 OUString uri
, description
;
855 Reference
< beans::XPropertySet
>xPropSet( children
[n
], UNO_QUERY
);
862 xPropSet
->getPropertyValue("URI");
867 value
= xPropSet
->getPropertyValue("Description");
868 value
>>= description
;
870 catch (Exception
&) {
871 // do nothing, the description will be empty
874 OUString
* pScriptURI
= new OUString( uri
);
876 OUString aImage
= GetImage(children
[n
], Reference
< XComponentContext
>(), false);
877 m_pFunctionListBox
->aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::FUNCTION_SCRIPT
, 0, pScriptURI
));
878 m_pFunctionListBox
->aArr
.back()->sCommand
= uri
;
879 m_pFunctionListBox
->aArr
.back()->sLabel
= children
[n
]->getName();
880 m_pFunctionListBox
->aArr
.back()->sHelpText
= description
;
882 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(m_pFunctionListBox
->aArr
.back().get())));
883 m_pFunctionListBox
->append(sId
, children
[n
]->getName(), aImage
);
888 catch (RuntimeException
&) {
889 // do nothing, the entry will not be displayed in the UI
895 case SfxCfgKind::GROUP_STYLES
:
897 SfxStyleInfo_Impl
* pFamily
= static_cast<SfxStyleInfo_Impl
*>(pInfo
->pObject
);
900 const std::vector
< SfxStyleInfo_Impl
> lStyles
= m_pStylesInfo
->getStyles(pFamily
->sFamily
);
901 for (auto const& lStyle
: lStyles
)
903 SfxStyleInfo_Impl
* pStyle
= new SfxStyleInfo_Impl(lStyle
);
904 m_pFunctionListBox
->aArr
.push_back(std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_STYLES
, 0, pStyle
));
905 m_pFunctionListBox
->aArr
.back()->sCommand
= pStyle
->sCommand
;
906 m_pFunctionListBox
->aArr
.back()->sLabel
= pStyle
->sLabel
;
907 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(m_pFunctionListBox
->aArr
.back().get())));
908 m_pFunctionListBox
->append(sId
, pStyle
->sLabel
);
915 // Do nothing, the list box will stay empty
916 SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast<int>(pInfo
->nKind
) );
920 m_pFunctionListBox
->thaw();
922 if (m_pFunctionListBox
->n_children())
923 m_pFunctionListBox
->select(0);
927 A basic or a library is opened.
929 IMPL_LINK(CuiConfigGroupListBox
, ExpandingHdl
, const weld::TreeIter
&, rIter
, bool)
931 SfxGroupInfo_Impl
*pInfo
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(rIter
).toInt64());
932 switch ( pInfo
->nKind
)
934 case SfxCfgKind::GROUP_SCRIPTCONTAINER
:
936 if (!m_xTreeView
->iter_has_child(rIter
))
938 Reference
< browse::XBrowseNode
> rootNode(
939 static_cast< browse::XBrowseNode
* >( pInfo
->pObject
) ) ;
940 FillScriptList(rootNode
, &rIter
, true /* i30923 */ );
945 case SfxCfgKind::GROUP_STYLES
:
947 if (!m_xTreeView
->iter_has_child(rIter
))
949 const std::vector
<SfxStyleInfo_Impl
> lStyleFamilies
= m_pStylesInfo
->getStyleFamilies();
950 for (auto const& lStyleFamily
: lStyleFamilies
)
952 SfxStyleInfo_Impl
* pFamily
= new SfxStyleInfo_Impl(lStyleFamily
);
953 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_STYLES
, 0, pFamily
));
954 OUString
sId(OUString::number(reinterpret_cast<sal_Int64
>(aArr
.back().get())));
955 m_xTreeView
->insert(&rIter
, -1, &pFamily
->sLabel
, &sId
, nullptr, nullptr, nullptr, false, nullptr);
962 OSL_FAIL( "Wrong group type!" );
968 void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem
*pItem
)
970 SelectMacro( pItem
->GetBasicManager()->GetName(),
971 pItem
->GetQualifiedName() );
974 void CuiConfigGroupListBox::SelectMacro( const OUString
& rBasic
,
975 const OUString
& rMacro
)
977 const OUString
aBasicName(rBasic
+ " " + xImp
->m_sMacros
);
978 sal_Int32 nIdx
{rMacro
.lastIndexOf('.')};
979 const OUString
aMethod( rMacro
.copy(nIdx
+1) );
984 // string contains at least 2 tokens
985 nIdx
= rMacro
.lastIndexOf('.', nIdx
);
988 // string contains at least 3 tokens
989 aLib
= rMacro
.getToken( 0, '.' );
990 aModule
= rMacro
.getToken( 0, '.', ++nIdx
);
994 std::unique_ptr
<weld::TreeIter
> xIter
= m_xTreeView
->make_iterator();
995 if (!m_xTreeView
->get_iter_first(*xIter
))
1000 OUString aEntryBas
= m_xTreeView
->get_text(*xIter
);
1001 if (aEntryBas
== aBasicName
)
1003 m_xTreeView
->expand_row(*xIter
);
1004 std::unique_ptr
<weld::TreeIter
> xLibIter
= m_xTreeView
->make_iterator(xIter
.get());
1005 if (m_xTreeView
->get_iter_first(*xLibIter
))
1009 OUString aEntryLib
= m_xTreeView
->get_text(*xLibIter
);
1010 if (aEntryLib
== aLib
)
1012 m_xTreeView
->expand_row(*xLibIter
);
1013 std::unique_ptr
<weld::TreeIter
> xModIter
= m_xTreeView
->make_iterator(xLibIter
.get());
1014 if (m_xTreeView
->get_iter_first(*xModIter
))
1018 OUString aEntryMod
= m_xTreeView
->get_text(*xModIter
);
1019 if ( aEntryMod
== aModule
)
1021 m_xTreeView
->expand_row(*xModIter
);
1022 m_xTreeView
->scroll_to_row(*xModIter
);
1023 m_xTreeView
->select(*xModIter
);
1024 for (int i
= 0, nCount
= m_pFunctionListBox
->n_children(); i
< nCount
; ++i
)
1026 OUString aEntryMethod
= m_pFunctionListBox
->get_text(i
);
1027 if (aEntryMethod
== aMethod
)
1029 m_pFunctionListBox
->select(i
);
1030 m_pFunctionListBox
->scroll_to_row(i
);
1035 } while (m_xTreeView
->iter_next_sibling(*xModIter
));
1038 } while (m_xTreeView
->iter_next_sibling(*xLibIter
));
1041 } while (m_xTreeView
->iter_next_sibling(*xIter
));
1045 * Implementation of SvxScriptSelectorDialog
1047 * This dialog is used for selecting Slot API commands
1048 * and Scripting Framework Scripts.
1051 SvxScriptSelectorDialog::SvxScriptSelectorDialog(
1052 weld::Window
* pParent
, bool bShowSlots
, const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
1053 : GenericDialogController(pParent
, "cui/ui/macroselectordialog.ui", "MacroSelectorDialog")
1054 , m_bShowSlots(bShowSlots
)
1055 , m_xDialogDescription(m_xBuilder
->weld_label(bShowSlots
? "helptoolbar" : "helpmacro"))
1056 , m_xCategories(new CuiConfigGroupListBox(m_xBuilder
->weld_tree_view("categories")))
1057 , m_xCommands(new CuiConfigFunctionListBox(m_xBuilder
->weld_tree_view("commands")))
1058 , m_xLibraryFT(m_xBuilder
->weld_label("libraryft"))
1059 , m_xCategoryFT(m_xBuilder
->weld_label("categoryft"))
1060 , m_xMacronameFT(m_xBuilder
->weld_label("macronameft"))
1061 , m_xCommandsFT(m_xBuilder
->weld_label("commandsft"))
1062 , m_xOKButton(m_xBuilder
->weld_button(bShowSlots
? "add" : "ok"))
1063 , m_xCancelButton(m_xBuilder
->weld_button(bShowSlots
? "close" : "cancel"))
1064 , m_xDescriptionText(m_xBuilder
->weld_text_view("description"))
1068 // If we are showing Slot API commands update labels in the UI
1069 m_xDialog
->set_title(CuiResId(RID_SVXSTR_SELECTOR_ADD_COMMANDS
));
1071 m_xCancelButton
->show();
1072 m_xDialogDescription
->show();
1073 m_xOKButton
->show();
1075 m_xLibraryFT
->set_visible(!m_bShowSlots
);
1076 m_xCategoryFT
->set_visible(m_bShowSlots
);
1077 m_xMacronameFT
->set_visible(!m_bShowSlots
);
1078 m_xCommandsFT
->set_visible(m_bShowSlots
);
1080 const OUString
aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame
));
1081 m_xCategories
->SetFunctionListBox(m_xCommands
.get());
1082 m_xCategories
->Init(comphelper::getProcessComponentContext(), xFrame
, aModuleName
, bShowSlots
);
1084 m_xCategories
->connect_changed(
1085 LINK( this, SvxScriptSelectorDialog
, SelectHdl
) );
1086 m_xCommands
->connect_changed( LINK( this, SvxScriptSelectorDialog
, SelectHdl
) );
1087 m_xCommands
->connect_row_activated( LINK( this, SvxScriptSelectorDialog
, FunctionDoubleClickHdl
) );
1089 m_xOKButton
->connect_clicked( LINK( this, SvxScriptSelectorDialog
, ClickHdl
) );
1090 m_xCancelButton
->connect_clicked( LINK( this, SvxScriptSelectorDialog
, ClickHdl
) );
1092 m_sDefaultDesc
= m_xDescriptionText
->get_text();
1094 // Support style commands
1095 uno::Reference
<frame::XController
> xController
;
1096 uno::Reference
<frame::XModel
> xModel
;
1098 xController
= xFrame
->getController();
1099 if (xController
.is())
1100 xModel
= xController
->getModel();
1102 m_aStylesInfo
.init(aModuleName
, xModel
);
1103 m_xCategories
->SetStylesInfo(&m_aStylesInfo
);
1108 SvxScriptSelectorDialog::~SvxScriptSelectorDialog()
1112 IMPL_LINK(SvxScriptSelectorDialog
, SelectHdl
, weld::TreeView
&, rCtrl
, void)
1114 if (&rCtrl
== &m_xCategories
->get_widget())
1116 m_xCategories
->GroupSelected();
1121 IMPL_LINK_NOARG(SvxScriptSelectorDialog
, FunctionDoubleClickHdl
, weld::TreeView
&, bool)
1123 if (m_xOKButton
->get_sensitive())
1124 ClickHdl(*m_xOKButton
);
1128 // Check if command is selected and enable the OK button accordingly
1129 // Grab the help text for this id if available and update the description field
1131 SvxScriptSelectorDialog::UpdateUI()
1133 OUString url
= GetScriptURL();
1134 if ( !url
.isEmpty() )
1136 OUString sMessage
= m_xCommands
->GetHelpText();
1137 m_xDescriptionText
->set_text(sMessage
.isEmpty() ? m_sDefaultDesc
: sMessage
);
1139 m_xOKButton
->set_sensitive(true);
1143 m_xDescriptionText
->set_text(m_sDefaultDesc
);
1144 m_xOKButton
->set_sensitive(false);
1148 IMPL_LINK(SvxScriptSelectorDialog
, ClickHdl
, weld::Button
&, rButton
, void)
1150 if (&rButton
== m_xCancelButton
.get())
1152 m_xDialog
->response(RET_CANCEL
);
1154 else if (&rButton
== m_xOKButton
.get())
1156 // If we are displaying Slot API commands then this the dialog is being
1157 // run from Tools/Configure and we should not close it
1158 if ( !m_bShowSlots
)
1160 m_xDialog
->response(RET_OK
);
1164 // Select the next entry in the list if possible
1165 std::unique_ptr
<weld::TreeIter
> xIter
= m_xCommands
->make_iterator();
1166 if (m_xCommands
->get_selected(xIter
.get()) && m_xCommands
->iter_next_sibling(*xIter
))
1167 m_xCommands
->select(*xIter
);
1173 SvxScriptSelectorDialog::SetRunLabel()
1175 m_xOKButton
->set_label(CuiResId(RID_SVXSTR_SELECTOR_RUN
));
1179 SvxScriptSelectorDialog::GetScriptURL() const
1183 std::unique_ptr
<weld::TreeIter
> xIter
= m_xCommands
->make_iterator();
1184 if (m_xCommands
->get_selected(xIter
.get()))
1186 SfxGroupInfo_Impl
*pData
= reinterpret_cast<SfxGroupInfo_Impl
*>(m_xCommands
->get_id(*xIter
).toInt64());
1187 if ( ( pData
->nKind
== SfxCfgKind::FUNCTION_SLOT
)
1188 || ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
1189 || ( pData
->nKind
== SfxCfgKind::GROUP_STYLES
)
1192 result
= pData
->sCommand
;
1199 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */