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/lok.hxx>
46 #include <comphelper/processfactory.hxx>
47 #include <comphelper/sequenceashashmap.hxx>
48 #include <svtools/imagemgr.hxx>
49 #include <sal/log.hxx>
50 #include <osl/diagnose.h>
51 #include <dialmgr.hxx>
52 #include <comphelper/diagnose_ex.hxx>
53 #include <vcl/commandevent.hxx>
54 #include <vcl/commandinfoprovider.hxx>
55 #include <vcl/help.hxx>
56 #include <vcl/svapp.hxx>
57 #include <o3tl/string_view.hxx>
59 #include <sfx2/sidebar/ResourceManager.hxx>
60 #include <sfx2/sidebar/Context.hxx>
61 #include <unotools/viewoptions.hxx>
63 using namespace ::com::sun::star
;
64 using namespace ::com::sun::star::uno
;
65 using namespace ::com::sun::star::script
;
66 using namespace ::com::sun::star::frame
;
67 using namespace ::com::sun::star::document
;
69 SfxStylesInfo_Impl::SfxStylesInfo_Impl()
72 void SfxStylesInfo_Impl::init(const OUString
& rModuleName
, const css::uno::Reference
< css::frame::XModel
>& xModel
)
74 m_aModuleName
= rModuleName
;
78 const char CMDURL_STYLEPROT_ONLY
[] = ".uno:StyleApply?";
79 const char CMDURL_SPART_ONLY
[] = "Style:string=";
80 const char CMDURL_FPART_ONLY
[] = "FamilyName:string=";
82 constexpr OUString STYLEPROP_UINAME
= u
"DisplayName"_ustr
;
83 constexpr OUString MACRO_SELECTOR_CONFIGNAME
= u
"MacroSelectorDialog"_ustr
;
84 constexpr OUString LAST_RUN_MACRO_INFO
= u
"LastRunMacro"_ustr
;
86 OUString
SfxStylesInfo_Impl::generateCommand(
87 std::u16string_view sFamily
, std::u16string_view sStyle
)
89 return OUString::Concat(".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() const
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 const 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(u
"DisplayName"_ustr
) >>= aStyleInfo
.sLabel
;
237 catch(const css::uno::RuntimeException
&)
239 catch(const css::uno::Exception
&)
242 lStyles
.push_back(aStyleInfo
);
247 OUString
CuiConfigFunctionListBox::GetCommandHelpText()
249 SfxGroupInfo_Impl
*pData
= weld::fromId
<SfxGroupInfo_Impl
*>(get_selected_id());
252 if ( pData
->nKind
== SfxCfgKind::FUNCTION_SLOT
)
254 return Application::GetHelp()->GetHelpText(pData
->sCommand
);
256 else if ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
258 return pData
->sHelpText
;
264 OUString
CuiConfigFunctionListBox::GetCurCommand() const
266 SfxGroupInfo_Impl
*pData
= weld::fromId
<SfxGroupInfo_Impl
*>(get_selected_id());
269 return pData
->sCommand
;
272 OUString
CuiConfigFunctionListBox::GetCurLabel() const
274 SfxGroupInfo_Impl
*pData
= weld::fromId
<SfxGroupInfo_Impl
*>(get_selected_id());
277 if (!pData
->sLabel
.isEmpty())
278 return pData
->sLabel
;
279 return pData
->sCommand
;
282 CuiConfigFunctionListBox::CuiConfigFunctionListBox(std::unique_ptr
<weld::TreeView
> xTreeView
)
283 : m_xTreeView(std::move(xTreeView
))
284 , m_xScratchIter(m_xTreeView
->make_iterator())
286 m_xTreeView
->make_sorted();
287 m_xTreeView
->set_size_request(m_xTreeView
->get_approximate_digit_width() * 35, m_xTreeView
->get_height_rows(9));
288 m_xTreeView
->connect_query_tooltip(LINK(this, CuiConfigFunctionListBox
, QueryTooltip
));
291 CuiConfigFunctionListBox::~CuiConfigFunctionListBox()
296 IMPL_LINK(CuiConfigFunctionListBox
, QueryTooltip
, const weld::TreeIter
&, rIter
, OUString
)
298 SfxGroupInfo_Impl
*pData
= weld::fromId
<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(rIter
));
301 OUString aLabel
= CuiResId(RID_CUISTR_COMMANDLABEL
) + ": ";
302 OUString aName
= CuiResId(RID_CUISTR_COMMANDNAME
) + ": ";
303 OUString aTip
= CuiResId(RID_CUISTR_COMMANDTIP
) + ": ";
304 return aLabel
+ pData
->sLabel
+ "\n" + aName
+ pData
->sCommand
+ "\n" + aTip
+ pData
->sTooltip
;
307 void CuiConfigFunctionListBox::ClearAll()
309 Deletes all entries in the FunctionListBox, all UserData and all
310 possibly existing MacroInfo.
313 sal_uInt16 nCount
= aArr
.size();
314 for ( sal_uInt16 i
=0; i
<nCount
; ++i
)
316 SfxGroupInfo_Impl
*pData
= aArr
[i
].get();
318 if ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
320 OUString
* pScriptURI
= static_cast<OUString
*>(pData
->pObject
);
324 if ( pData
->nKind
== SfxCfgKind::GROUP_SCRIPTCONTAINER
)
326 XInterface
* xi
= static_cast<XInterface
*>(pData
->pObject
);
335 m_xTreeView
->clear();
338 OUString
CuiConfigFunctionListBox::GetSelectedScriptURI() const
340 SfxGroupInfo_Impl
*pData
= weld::fromId
<SfxGroupInfo_Impl
*>(get_selected_id());
341 if (pData
&& pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
342 return *static_cast<OUString
*>(pData
->pObject
);
346 struct SvxConfigGroupBoxResource_Impl
348 OUString m_sMyMacros
;
349 OUString m_sProdMacros
;
350 OUString m_sDlgMacros
;
351 OUString m_aStrGroupStyles
;
352 OUString m_aStrGroupSidebarDecks
;
354 SvxConfigGroupBoxResource_Impl();
357 SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() :
358 m_sMyMacros(CuiResId(RID_CUISTR_MYMACROS
)),
359 m_sProdMacros(CuiResId(RID_CUISTR_PRODMACROS
)),
360 m_sDlgMacros(CuiResId(RID_CUISTR_PRODMACROS
)),
361 m_aStrGroupStyles(CuiResId(RID_CUISTR_GROUP_STYLES
)),
362 m_aStrGroupSidebarDecks(CuiResId(RID_CUISTR_GROUP_SIDEBARDECKS
))
366 void CuiConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl
* pStyles
)
368 m_pStylesInfo
= pStyles
;
374 /** examines a component whether it supports XEmbeddedScripts, or provides access to such a
375 component by implementing XScriptInvocationContext.
377 the model which supports the embedded scripts, or <NULL/> if it cannot find such a
380 Reference
< XModel
> lcl_getDocumentWithScripts_throw( const Reference
< XInterface
>& _rxComponent
)
382 Reference
< XEmbeddedScripts
> xScripts( _rxComponent
, UNO_QUERY
);
383 if ( !xScripts
.is() )
385 Reference
< XScriptInvocationContext
> xContext( _rxComponent
, UNO_QUERY
);
387 xScripts
= xContext
->getScriptContainer();
390 return Reference
< XModel
>( xScripts
, UNO_QUERY
);
394 Reference
< XModel
> lcl_getScriptableDocument_nothrow( const Reference
< XFrame
>& _rxFrame
)
396 Reference
< XModel
> xDocument
;
398 // examine our associated frame
401 OSL_ENSURE( _rxFrame
.is(), "lcl_getScriptableDocument_nothrow: you need to pass a frame to this dialog/tab page!" );
404 // first try the model in the frame
405 Reference
< XController
> xController( _rxFrame
->getController(), UNO_SET_THROW
);
406 xDocument
= lcl_getDocumentWithScripts_throw( xController
->getModel() );
408 if ( !xDocument
.is() )
410 // if there is no suitable document in the frame, try the controller
411 xDocument
= lcl_getDocumentWithScripts_throw( _rxFrame
->getController() );
415 catch( const Exception
& )
423 CuiConfigGroupListBox::CuiConfigGroupListBox(std::unique_ptr
<weld::TreeView
> xTreeView
)
424 : xImp(new SvxConfigGroupBoxResource_Impl())
425 , m_pFunctionListBox(nullptr)
426 , m_pStylesInfo(nullptr)
427 , m_xTreeView(std::move(xTreeView
))
428 , m_xScratchIter(m_xTreeView
->make_iterator())
430 m_xTreeView
->connect_expanding(LINK(this, CuiConfigGroupListBox
, ExpandingHdl
));
431 m_xTreeView
->set_size_request(m_xTreeView
->get_approximate_digit_width() * 35, m_xTreeView
->get_height_rows(9));
434 CuiConfigGroupListBox::~CuiConfigGroupListBox()
439 void CuiConfigGroupListBox::ClearAll()
441 sal_uInt16 nCount
= aArr
.size();
442 for ( sal_uInt16 i
=0; i
<nCount
; ++i
)
444 SfxGroupInfo_Impl
*pData
= aArr
[i
].get();
445 if (pData
->nKind
== SfxCfgKind::GROUP_STYLES
&& pData
->pObject
)
447 SfxStyleInfo_Impl
* pStyle
= static_cast<SfxStyleInfo_Impl
*>(pData
->pObject
);
450 else if (pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
&& pData
->pObject
)
452 OUString
* pScriptURI
= static_cast<OUString
*>(pData
->pObject
);
455 else if (pData
->nKind
== SfxCfgKind::GROUP_SCRIPTCONTAINER
)
457 XInterface
* xi
= static_cast<XInterface
*>(pData
->pObject
);
466 m_xTreeView
->clear();
469 sal_Int32
CuiConfigGroupListBox::InitModule()
473 // return the number of added groups
474 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider(m_xFrame
, css::uno::UNO_QUERY_THROW
);
475 css::uno::Sequence
< sal_Int16
> lGroups
= xProvider
->getSupportedCommandGroups();
476 sal_Int32 c1
= lGroups
.getLength();
478 sal_Int32 nAddedGroups
= 0;
480 for (i1
=0; i1
<c1
; ++i1
)
482 sal_Int16 nGroupID
= lGroups
[i1
];
483 OUString sGroupID
= OUString::number(nGroupID
);
484 OUString sGroupName
;
488 m_xModuleCategoryInfo
->getByName(sGroupID
) >>= sGroupName
;
489 if (sGroupName
.isEmpty())
492 catch(const css::container::NoSuchElementException
&)
495 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_FUNCTION
, nGroupID
) );
496 m_xTreeView
->append(weld::toId(aArr
.back().get()), sGroupName
);
501 catch(const css::uno::RuntimeException
&)
503 catch(const css::uno::Exception
&)
508 void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference
< css::script::browse::XBrowseNode
>& xRootNode
,
509 const weld::TreeIter
* pParentEntry
)
512 if ( xRootNode
->hasChildNodes() )
514 // tdf#120362: Don't ask to enable disabled Java when filling script list
515 css::uno::ContextLayer
layer(comphelper::NoEnableJavaInteractionContext());
517 const Sequence
< Reference
< browse::XBrowseNode
> > children
=
518 xRootNode
->getChildNodes();
519 bool bIsRootNode
= false;
521 OUString
user(u
"user"_ustr
);
522 OUString
share(u
"share"_ustr
);
523 if ( xRootNode
->getName() == "Root" )
528 //To mimic current starbasic behaviour we
529 //need to make sure that only the current document
530 //is displayed in the config tree. Tests below
531 //set the bDisplay flag to FALSE if the current
532 //node is a first level child of the Root and is NOT
533 //either the current document, user or share
534 OUString currentDocTitle
;
535 Reference
< XModel
> xDocument( lcl_getScriptableDocument_nothrow( m_xFrame
) );
536 if ( xDocument
.is() )
538 currentDocTitle
= ::comphelper::DocumentInfo::getDocumentTitle( xDocument
);
541 for ( Reference
< browse::XBrowseNode
> const & theChild
: children
)
546 bool bDisplay
= true;
547 OUString uiName
= theChild
->getName();
550 if ( ! (uiName
== user
|| uiName
== share
||
551 uiName
== currentDocTitle
) )
557 if ( uiName
== user
)
559 uiName
= xImp
->m_sMyMacros
;
561 else if ( uiName
== share
)
563 uiName
= xImp
->m_sProdMacros
;
567 if (theChild
->getType() != browse::BrowseNodeTypes::SCRIPT
&& bDisplay
)
569 // We call acquire on the XBrowseNode so that it does not
570 // get autodestructed and become invalid when accessed later.
573 bool bChildOnDemand
= false;
575 if ( theChild
->hasChildNodes() )
577 const Sequence
< Reference
< browse::XBrowseNode
> > grandchildren
=
578 theChild
->getChildNodes();
580 for ( const auto& rxNode
: grandchildren
)
585 if ( rxNode
->getType() == browse::BrowseNodeTypes::CONTAINER
)
587 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(weld::toId(aArr
.back().get()));
599 m_xTreeView
->insert(pParentEntry
, -1, &uiName
, &sId
, nullptr, nullptr, bChildOnDemand
, m_xScratchIter
.get());
600 m_xTreeView
->set_image(*m_xScratchIter
, aImage
);
605 catch (RuntimeException
&) {
606 // do nothing, the entry will not be displayed in the UI
610 void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence
<DispatchInformation
>& xCommands
)
612 m_pFunctionListBox
->freeze();
613 for (const auto & rInfo
: xCommands
)
615 auto aProperties
= vcl::CommandInfoProvider::GetCommandProperties(rInfo
.Command
, m_sModuleLongName
);
617 OUString sUIName
= MapCommand2UIName(rInfo
.Command
);
618 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::FUNCTION_SLOT
, 0 ) );
619 SfxGroupInfo_Impl
* pGrpInfo
= aArr
.back().get();
620 pGrpInfo
->sCommand
= rInfo
.Command
;
621 pGrpInfo
->sLabel
= sUIName
;
622 pGrpInfo
->sTooltip
= vcl::CommandInfoProvider::GetTooltipForCommand(rInfo
.Command
, aProperties
, m_xFrame
);
623 m_pFunctionListBox
->append(weld::toId(pGrpInfo
), sUIName
);
625 m_pFunctionListBox
->thaw();
628 void CuiConfigGroupListBox::Init(const css::uno::Reference
< css::uno::XComponentContext
>& xContext
,
629 const css::uno::Reference
< css::frame::XFrame
>& xFrame
,
630 const OUString
& sModuleLongName
,
633 m_xTreeView
->freeze();
634 ClearAll(); // Remove all old entries from treelist box
636 m_xContext
= xContext
;
638 sal_Int32 nAddedGroups
= 0;
641 m_sModuleLongName
= sModuleLongName
;
642 m_xGlobalCategoryInfo
= css::ui::theUICategoryDescription::get( m_xContext
);
643 m_xModuleCategoryInfo
.set(m_xGlobalCategoryInfo
->getByName(m_sModuleLongName
), css::uno::UNO_QUERY_THROW
);
644 m_xUICmdDescription
= css::frame::theUICommandDescription::get( m_xContext
);
646 nAddedGroups
= InitModule();
649 SAL_INFO("cui.customize", "** ** About to initialise SF Scripts");
650 // Add Scripting Framework entries
651 Reference
< browse::XBrowseNode
> rootNode
;
654 Reference
< browse::XBrowseNodeFactory
> xFac
= browse::theBrowseNodeFactory::get( m_xContext
);
655 rootNode
.set( xFac
->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR
) );
657 catch( const Exception
& )
659 TOOLS_WARN_EXCEPTION("cui.customize", "Caught some exception whilst retrieving browse nodes from factory");
660 // TODO exception handling
664 m_xTreeView
->make_sorted();
665 m_xTreeView
->make_unsorted();
666 m_xTreeView
->freeze();
668 // add All Commands to the top
669 if ( bEventMode
&& nAddedGroups
)
671 aArr
.insert(aArr
.begin(), std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_ALLFUNCTIONS
, 0));
672 OUString
sId(weld::toId(aArr
.front().get()));
673 OUString
s(CuiResId(RID_CUISTR_ALLFUNCTIONS
));
674 m_xTreeView
->insert(nullptr, 0, &s
, &sId
, nullptr, nullptr, false, nullptr);
677 // add application macros to the end
682 //We call acquire on the XBrowseNode so that it does not
683 //get autodestructed and become invalid when accessed later.
686 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_SCRIPTCONTAINER
, 0,
687 static_cast<void *>(rootNode
.get())));
688 OUString
aTitle(xImp
->m_sDlgMacros
);
689 OUString
sId(weld::toId(aArr
.back().get()));
690 m_xTreeView
->insert(nullptr, -1, &aTitle
, &sId
, nullptr, nullptr, true, nullptr);
694 //We are only showing scripts not slot APIs so skip
695 //Root node and show location nodes
696 FillScriptList(rootNode
, nullptr);
700 // add styles and sidebar decks to the end
703 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_STYLES
, 0, nullptr ) ); // TODO last parameter should contain user data
704 OUString
sStyle(xImp
->m_aStrGroupStyles
);
705 OUString
sId(weld::toId(aArr
.back().get()));
706 m_xTreeView
->insert(nullptr, -1, &sStyle
, &sId
, nullptr, nullptr, true, nullptr);
708 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_SIDEBARDECKS
, 0));
709 OUString
sSidebarDecks(xImp
->m_aStrGroupSidebarDecks
);
710 sId
= weld::toId(aArr
.back().get());
711 m_xTreeView
->insert(nullptr, -1, &sSidebarDecks
, &sId
, nullptr, nullptr, false, nullptr);
715 m_xTreeView
->scroll_to_row(0);
716 m_xTreeView
->select(0);
719 OUString
CuiConfigGroupListBox::GetImage(
720 const Reference
< browse::XBrowseNode
>& node
,
721 Reference
< XComponentContext
> const & xCtx
,
727 if (node
->getName() == "user" || node
->getName() == "share" )
729 aImage
= RID_CUIBMP_HARDDISK
;
734 OUString nodeName
= node
->getName();
735 Reference
<XInterface
> xDocumentModel
= getDocumentModel(xCtx
, nodeName
);
736 if ( xDocumentModel
.is() )
738 Reference
< frame::XModuleManager2
> xModuleManager( frame::ModuleManager::create(xCtx
) );
739 // get the long name of the document:
740 OUString
appModule( xModuleManager
->identify(
742 Sequence
<beans::PropertyValue
> moduleDescr
;
743 Any aAny
= xModuleManager
->getByName(appModule
);
744 if( !( aAny
>>= moduleDescr
) )
746 throw RuntimeException(u
"SFTreeListBox::Init: failed to get PropertyValue"_ustr
);
748 for ( sal_Int32 pos
= moduleDescr
.getLength(); pos
--; )
750 if (moduleDescr
[pos
].Name
== "ooSetupFactoryEmptyDocumentURL")
752 moduleDescr
[pos
].Value
>>= factoryURL
;
753 SAL_INFO("cui.customize", "factory url for doc images is " << factoryURL
);
758 if( !factoryURL
.isEmpty() )
760 aImage
= SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL
));
764 aImage
= RID_CUIBMP_DOC
;
770 if( node
->getType() == browse::BrowseNodeTypes::SCRIPT
)
771 aImage
= RID_CUIBMP_MACRO
;
773 aImage
= RID_CUIBMP_LIB
;
778 Reference
< XInterface
>
779 CuiConfigGroupListBox::getDocumentModel( Reference
< XComponentContext
> const & xCtx
, std::u16string_view docName
)
781 Reference
< XInterface
> xModel
;
782 Reference
< frame::XDesktop2
> desktop
= frame::Desktop::create( xCtx
);
784 Reference
< container::XEnumerationAccess
> componentsAccess
=
785 desktop
->getComponents();
786 Reference
< container::XEnumeration
> components
=
787 componentsAccess
->createEnumeration();
788 while (components
->hasMoreElements())
790 Reference
< frame::XModel
> model(
791 components
->nextElement(), UNO_QUERY
);
795 ::comphelper::DocumentInfo::getDocumentTitle( model
);
796 if( sTdocUrl
== docName
)
806 OUString
CuiConfigGroupListBox::MapCommand2UIName(const OUString
& sCommand
)
811 css::uno::Reference
< css::container::XNameAccess
> xModuleConf
;
812 m_xUICmdDescription
->getByName(m_sModuleLongName
) >>= xModuleConf
;
813 if (xModuleConf
.is())
815 ::comphelper::SequenceAsHashMap
lProps(xModuleConf
->getByName(sCommand
));
816 sUIName
= lProps
.getUnpackedValueOrDefault(u
"Name"_ustr
, OUString());
819 catch(const css::uno::RuntimeException
&)
821 catch(css::uno::Exception
&)
824 // fallback for missing UINames !?
825 if (sUIName
.isEmpty())
833 void CuiConfigGroupListBox::GroupSelected()
835 A function group or a basic module has been selected.
836 All functions/macros are displayed in the functionlistbox.
839 std::unique_ptr
<weld::TreeIter
> xIter(m_xTreeView
->make_iterator());
840 if (!m_xTreeView
->get_selected(xIter
.get()))
843 SfxGroupInfo_Impl
*pInfo
= weld::fromId
<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(*xIter
));
844 m_pFunctionListBox
->freeze();
845 m_pFunctionListBox
->ClearAll();
847 switch ( pInfo
->nKind
)
849 case SfxCfgKind::GROUP_ALLFUNCTIONS
:
851 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider( m_xFrame
, UNO_QUERY
);
852 bool bValidIter
= m_xTreeView
->get_iter_first(*xIter
);
855 SfxGroupInfo_Impl
*pCurrentInfo
= weld::fromId
<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(*xIter
));
856 if (pCurrentInfo
->nKind
== SfxCfgKind::GROUP_FUNCTION
)
858 css::uno::Sequence
< css::frame::DispatchInformation
> lCommands
;
861 lCommands
= xProvider
->getConfigurableDispatchInformation( pCurrentInfo
->nUniqueID
);
862 FillFunctionsList( lCommands
);
864 catch ( container::NoSuchElementException
& )
868 bValidIter
= m_xTreeView
->iter_next(*xIter
);
873 case SfxCfgKind::GROUP_FUNCTION
:
875 sal_uInt16 nGroup
= pInfo
->nUniqueID
;
876 css::uno::Reference
< css::frame::XDispatchInformationProvider
> xProvider (m_xFrame
, css::uno::UNO_QUERY_THROW
);
877 css::uno::Sequence
< css::frame::DispatchInformation
> lCommands
= xProvider
->getConfigurableDispatchInformation(nGroup
);
878 FillFunctionsList( lCommands
);
882 case SfxCfgKind::GROUP_SCRIPTCONTAINER
:
884 Reference
< browse::XBrowseNode
> rootNode(
885 static_cast< browse::XBrowseNode
* >( pInfo
->pObject
) ) ;
888 if ( rootNode
->hasChildNodes() )
890 const Sequence
< Reference
< browse::XBrowseNode
> > children
=
891 rootNode
->getChildNodes();
893 for ( const Reference
< browse::XBrowseNode
>& childNode
: children
)
898 if (childNode
->getType() == browse::BrowseNodeTypes::SCRIPT
)
900 OUString uri
, description
;
902 Reference
< beans::XPropertySet
>xPropSet( childNode
, UNO_QUERY
);
909 xPropSet
->getPropertyValue(u
"URI"_ustr
);
914 value
= xPropSet
->getPropertyValue(u
"Description"_ustr
);
915 value
>>= description
;
917 catch (Exception
&) {
918 // do nothing, the description will be empty
921 OUString
* pScriptURI
= new OUString( uri
);
923 OUString aImage
= GetImage(childNode
, Reference
< XComponentContext
>(), false);
924 m_pFunctionListBox
->aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::FUNCTION_SCRIPT
, 0, pScriptURI
));
925 m_pFunctionListBox
->aArr
.back()->sCommand
= uri
;
926 m_pFunctionListBox
->aArr
.back()->sLabel
= childNode
->getName();
927 m_pFunctionListBox
->aArr
.back()->sHelpText
= description
;
929 OUString
sId(weld::toId(m_pFunctionListBox
->aArr
.back().get()));
930 m_pFunctionListBox
->append(sId
, childNode
->getName(), aImage
);
935 catch (RuntimeException
&) {
936 // do nothing, the entry will not be displayed in the UI
941 case SfxCfgKind::GROUP_STYLES
:
943 SfxStyleInfo_Impl
* pFamily
= static_cast<SfxStyleInfo_Impl
*>(pInfo
->pObject
);
946 const std::vector
< SfxStyleInfo_Impl
> lStyles
= m_pStylesInfo
->getStyles(pFamily
->sFamily
);
947 for (auto const& lStyle
: lStyles
)
949 SfxStyleInfo_Impl
* pStyle
= new SfxStyleInfo_Impl(lStyle
);
950 m_pFunctionListBox
->aArr
.push_back(std::make_unique
<SfxGroupInfo_Impl
>(SfxCfgKind::GROUP_STYLES
, 0, pStyle
));
951 m_pFunctionListBox
->aArr
.back()->sCommand
= pStyle
->sCommand
;
952 m_pFunctionListBox
->aArr
.back()->sLabel
= pStyle
->sLabel
;
953 OUString
sId(weld::toId(m_pFunctionListBox
->aArr
.back().get()));
954 m_pFunctionListBox
->append(sId
, pStyle
->sLabel
);
960 case SfxCfgKind::GROUP_SIDEBARDECKS
:
962 sfx2::sidebar::ResourceManager aResourceManager
;
963 sfx2::sidebar::Context
aContext(m_sModuleLongName
, OUString());
964 sfx2::sidebar::ResourceManager::DeckContextDescriptorContainer aDecks
;
965 aResourceManager
.GetMatchingDecks(aDecks
, aContext
, false, m_xFrame
->getController());
967 for (auto const& rDeck
: aDecks
)
969 const OUString sCommand
= ".uno:SidebarDeck." + rDeck
.msId
;
970 m_pFunctionListBox
->aArr
.push_back(std::make_unique
<SfxGroupInfo_Impl
>(
971 SfxCfgKind::GROUP_SIDEBARDECKS
, 0,
973 m_pFunctionListBox
->aArr
.back()->sCommand
= sCommand
;
974 m_pFunctionListBox
->aArr
.back()->sLabel
= rDeck
.msId
;
975 m_pFunctionListBox
->aArr
.back()->sTooltip
=
976 vcl::CommandInfoProvider::GetCommandShortcut(sCommand
, m_xFrame
);
977 m_pFunctionListBox
->append(weld::toId(m_pFunctionListBox
->aArr
.back().get()),
985 // Do nothing, the list box will stay empty
986 SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast<int>(pInfo
->nKind
) );
990 m_pFunctionListBox
->thaw();
992 if (m_pFunctionListBox
->n_children())
993 m_pFunctionListBox
->select(0);
997 A basic or a library is opened.
999 IMPL_LINK(CuiConfigGroupListBox
, ExpandingHdl
, const weld::TreeIter
&, rIter
, bool)
1001 SfxGroupInfo_Impl
*pInfo
= weld::fromId
<SfxGroupInfo_Impl
*>(m_xTreeView
->get_id(rIter
));
1002 switch ( pInfo
->nKind
)
1004 case SfxCfgKind::GROUP_SCRIPTCONTAINER
:
1006 if (!m_xTreeView
->iter_has_child(rIter
))
1008 Reference
< browse::XBrowseNode
> rootNode(
1009 static_cast< browse::XBrowseNode
* >( pInfo
->pObject
) ) ;
1010 FillScriptList(rootNode
, &rIter
);
1015 case SfxCfgKind::GROUP_STYLES
:
1017 if (!m_xTreeView
->iter_has_child(rIter
))
1019 const std::vector
<SfxStyleInfo_Impl
> lStyleFamilies
= m_pStylesInfo
->getStyleFamilies();
1020 for (auto const& lStyleFamily
: lStyleFamilies
)
1022 SfxStyleInfo_Impl
* pFamily
= new SfxStyleInfo_Impl(lStyleFamily
);
1023 aArr
.push_back( std::make_unique
<SfxGroupInfo_Impl
>( SfxCfgKind::GROUP_STYLES
, 0, pFamily
));
1024 OUString
sId(weld::toId(aArr
.back().get()));
1025 m_xTreeView
->insert(&rIter
, -1, &pFamily
->sLabel
, &sId
, nullptr, nullptr, false, nullptr);
1032 OSL_FAIL( "Wrong group type!" );
1038 #if HAVE_FEATURE_SCRIPTING
1039 void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem
*pItem
)
1041 const std::u16string_view aLocation
= pItem
->GetLocation();
1042 const std::u16string_view aLib
= pItem
->GetLib();
1043 const std::u16string_view aModule
= pItem
->GetModule();
1044 const std::u16string_view aMethod
= pItem
->GetMethod();
1046 std::unique_ptr
<weld::TreeIter
> xIter
= m_xTreeView
->make_iterator();
1047 if (!m_xTreeView
->get_iter_first(*xIter
))
1052 OUString aEntryBas
= m_xTreeView
->get_text(*xIter
);
1053 if (aEntryBas
== xImp
->m_sDlgMacros
)
1055 m_xTreeView
->expand_row(*xIter
);
1056 std::unique_ptr
<weld::TreeIter
> xLocationIter
= m_xTreeView
->make_iterator(xIter
.get());
1057 if (m_xTreeView
->iter_children(*xLocationIter
))
1061 if (aLocation
!= m_xTreeView
->get_text(*xLocationIter
))
1063 m_xTreeView
->expand_row(*xLocationIter
);
1064 std::unique_ptr
<weld::TreeIter
> xLibIter
= m_xTreeView
->make_iterator(xLocationIter
.get());
1065 if (m_xTreeView
->iter_children(*xLibIter
))
1069 OUString aEntryLib
= m_xTreeView
->get_text(*xLibIter
);
1070 if (aEntryLib
== aLib
)
1072 if (aModule
.empty())
1074 m_xTreeView
->scroll_to_row(*xLibIter
);
1075 m_xTreeView
->select(*xLibIter
);
1077 weld::TreeView
& rFunctionListBoxTreeView
1078 = m_pFunctionListBox
->get_widget();
1079 std::unique_ptr
<weld::TreeIter
> xFunctionListBoxIter
1080 = rFunctionListBoxTreeView
.make_iterator();
1081 if (!rFunctionListBoxTreeView
.get_iter_first(
1082 *xFunctionListBoxIter
))
1086 OUString aEntryMethod
= rFunctionListBoxTreeView
.get_text(
1087 *xFunctionListBoxIter
);
1088 if (aEntryMethod
== aMethod
)
1090 rFunctionListBoxTreeView
.scroll_to_row(
1091 *xFunctionListBoxIter
);
1092 rFunctionListBoxTreeView
.select(*xFunctionListBoxIter
);
1096 rFunctionListBoxTreeView
.iter_next(*xFunctionListBoxIter
));
1100 m_xTreeView
->expand_row(*xLibIter
);
1101 std::unique_ptr
<weld::TreeIter
> xModIter
= m_xTreeView
->make_iterator(xLibIter
.get());
1102 if (m_xTreeView
->iter_children(*xModIter
))
1106 OUString aEntryMod
= m_xTreeView
->get_text(*xModIter
);
1107 if ( aEntryMod
== aModule
)
1109 m_xTreeView
->expand_row(*xModIter
);
1110 m_xTreeView
->scroll_to_row(*xModIter
);
1111 m_xTreeView
->select(*xModIter
);
1113 for (int i
= 0, nCount
= m_pFunctionListBox
->n_children(); i
< nCount
; ++i
)
1115 OUString aEntryMethod
= m_pFunctionListBox
->get_text(i
);
1116 if (aEntryMethod
== aMethod
)
1118 m_pFunctionListBox
->select(i
);
1119 m_pFunctionListBox
->scroll_to_row(i
);
1123 m_xTreeView
->collapse_row(*xModIter
);
1125 } while (m_xTreeView
->iter_next_sibling(*xModIter
));
1127 m_xTreeView
->collapse_row(*xLibIter
);
1129 } while (m_xTreeView
->iter_next_sibling(*xLibIter
));
1131 m_xTreeView
->collapse_row(*xLocationIter
);
1132 } while (m_xTreeView
->iter_next_sibling(*xLocationIter
));
1134 // If the macro can't be located, preselect the "Application Macros" category:
1135 m_xTreeView
->scroll_to_row(*xIter
);
1136 m_xTreeView
->select(*xIter
);
1139 } while (m_xTreeView
->iter_next_sibling(*xIter
));
1144 * Implementation of SvxScriptSelectorDialog
1146 * This dialog is used for selecting Slot API commands
1147 * and Scripting Framework Scripts.
1150 SvxScriptSelectorDialog::SvxScriptSelectorDialog(
1151 weld::Window
* pParent
, const css::uno::Reference
< css::frame::XFrame
>& xFrame
)
1152 : GenericDialogController(pParent
, u
"cui/ui/macroselectordialog.ui"_ustr
, u
"MacroSelectorDialog"_ustr
)
1153 , m_xDialogDescription(m_xBuilder
->weld_label(u
"helpmacro"_ustr
))
1154 , m_xCategories(new CuiConfigGroupListBox(m_xBuilder
->weld_tree_view(u
"categories"_ustr
)))
1155 , m_xCommands(new CuiConfigFunctionListBox(m_xBuilder
->weld_tree_view(u
"commands"_ustr
)))
1156 , m_xLibraryFT(m_xBuilder
->weld_label(u
"libraryft"_ustr
))
1157 , m_xMacronameFT(m_xBuilder
->weld_label(u
"macronameft"_ustr
))
1158 , m_xOKButton(m_xBuilder
->weld_button(u
"ok"_ustr
))
1159 , m_xCancelButton(m_xBuilder
->weld_button(u
"cancel"_ustr
))
1160 , m_xDescriptionText(m_xBuilder
->weld_text_view(u
"description"_ustr
))
1161 , m_xDescriptionFrame(m_xBuilder
->weld_frame(u
"descriptionframe"_ustr
))
1163 m_xCancelButton
->show();
1164 m_xDialogDescription
->show();
1165 m_xOKButton
->show();
1167 m_xLibraryFT
->set_visible(true);
1168 m_xMacronameFT
->set_visible(true);
1170 const OUString
aModuleName(vcl::CommandInfoProvider::GetModuleIdentifier(xFrame
));
1171 m_xCategories
->SetFunctionListBox(m_xCommands
.get());
1172 m_xCategories
->Init(comphelper::getProcessComponentContext(), xFrame
, aModuleName
, /*bShowSlots*/false);
1174 m_xCategories
->connect_changed(
1175 LINK( this, SvxScriptSelectorDialog
, SelectHdl
) );
1176 m_xCommands
->connect_changed( LINK( this, SvxScriptSelectorDialog
, SelectHdl
) );
1177 m_xCommands
->connect_row_activated( LINK( this, SvxScriptSelectorDialog
, FunctionDoubleClickHdl
) );
1178 m_xCommands
->connect_popup_menu( LINK( this, SvxScriptSelectorDialog
, ContextMenuHdl
) );
1180 m_xOKButton
->connect_clicked( LINK( this, SvxScriptSelectorDialog
, ClickHdl
) );
1181 m_xCancelButton
->connect_clicked( LINK( this, SvxScriptSelectorDialog
, ClickHdl
) );
1183 m_sDefaultDesc
= m_xDescriptionText
->get_text();
1185 // Support style commands
1186 uno::Reference
<frame::XController
> xController
;
1187 uno::Reference
<frame::XModel
> xModel
;
1189 xController
= xFrame
->getController();
1190 if (xController
.is())
1191 xModel
= xController
->getModel();
1193 m_aStylesInfo
.init(aModuleName
, xModel
);
1194 m_xCategories
->SetStylesInfo(&m_aStylesInfo
);
1196 // The following call is a workaround to make scroll_to_row work as expected in kf5/x11
1197 m_xDialog
->resize_to_request();
1199 LoadLastUsedMacro();
1202 if (comphelper::LibreOfficeKit::isActive())
1203 m_xDescriptionFrame
->hide();
1206 SvxScriptSelectorDialog::~SvxScriptSelectorDialog()
1210 IMPL_LINK(SvxScriptSelectorDialog
, SelectHdl
, weld::TreeView
&, rCtrl
, void)
1212 if (&rCtrl
== &m_xCategories
->get_widget())
1214 m_xCategories
->GroupSelected();
1219 IMPL_LINK_NOARG(SvxScriptSelectorDialog
, FunctionDoubleClickHdl
, weld::TreeView
&, bool)
1221 if (m_xOKButton
->get_sensitive())
1222 ClickHdl(*m_xOKButton
);
1226 IMPL_LINK(SvxScriptSelectorDialog
, ContextMenuHdl
, const CommandEvent
&, rCEvt
, bool)
1228 weld::TreeView
& xTreeView
= m_xCommands
->get_widget();
1229 if (rCEvt
.GetCommand() != CommandEventId::ContextMenu
|| !xTreeView
.n_children())
1232 std::unique_ptr
<weld::Builder
> xBuilder(Application::CreateBuilder(&xTreeView
, u
"modules/BasicIDE/ui/sortmenu.ui"_ustr
));
1233 std::unique_ptr
<weld::Menu
> xPopup(xBuilder
->weld_menu(u
"sortmenu"_ustr
));
1234 std::unique_ptr
<weld::Menu
> xDropMenu(xBuilder
->weld_menu(u
"sortsubmenu"_ustr
));
1235 xDropMenu
->set_active(u
"alphabetically"_ustr
, xTreeView
.get_sort_order());
1236 xDropMenu
->set_active(u
"properorder"_ustr
, !xTreeView
.get_sort_order());
1238 OUString
sCommand(xPopup
->popup_at_rect(&xTreeView
, tools::Rectangle(rCEvt
.GetMousePosPixel(), Size(1,1))));
1239 if (sCommand
== "alphabetically")
1241 xTreeView
.make_sorted();
1243 else if (sCommand
== "properorder")
1245 xTreeView
.make_unsorted();
1246 m_xCategories
->GroupSelected();
1248 else if (!sCommand
.isEmpty())
1250 SAL_WARN("cui.customize", "Unknown context menu action: " << sCommand
);
1256 // Check if command is selected and enable the OK button accordingly
1257 // Grab the help text for this id if available and update the description field
1259 SvxScriptSelectorDialog::UpdateUI()
1261 OUString url
= GetScriptURL();
1262 if ( !url
.isEmpty() )
1264 OUString sMessage
= m_xCommands
->GetCommandHelpText();
1265 m_xDescriptionText
->set_text(sMessage
.isEmpty() ? m_sDefaultDesc
: sMessage
);
1266 m_xOKButton
->set_sensitive(true);
1270 m_xDescriptionText
->set_text(m_sDefaultDesc
);
1271 m_xOKButton
->set_sensitive(false);
1275 IMPL_LINK(SvxScriptSelectorDialog
, ClickHdl
, weld::Button
&, rButton
, void)
1277 if (&rButton
== m_xCancelButton
.get())
1279 m_xDialog
->response(RET_CANCEL
);
1281 else if (&rButton
== m_xOKButton
.get())
1283 SaveLastUsedMacro();
1284 m_xDialog
->response(RET_OK
);
1289 SvxScriptSelectorDialog::SetRunLabel()
1291 m_xOKButton
->set_label(CuiResId(RID_CUISTR_SELECTOR_RUN
));
1295 SvxScriptSelectorDialog::GetScriptURL() const
1299 std::unique_ptr
<weld::TreeIter
> xIter
= m_xCommands
->make_iterator();
1300 if (m_xCommands
->get_selected(xIter
.get()))
1302 SfxGroupInfo_Impl
*pData
= weld::fromId
<SfxGroupInfo_Impl
*>(m_xCommands
->get_id(*xIter
));
1303 if ( ( pData
->nKind
== SfxCfgKind::FUNCTION_SLOT
)
1304 || ( pData
->nKind
== SfxCfgKind::FUNCTION_SCRIPT
)
1305 || ( pData
->nKind
== SfxCfgKind::GROUP_STYLES
)
1308 result
= pData
->sCommand
;
1316 SvxScriptSelectorDialog::SaveLastUsedMacro()
1318 // Gets the current selection in the dialog as a series of selected entries
1319 OUString sMacroInfo
;
1320 sMacroInfo
= m_xCommands
->get_selected_text();
1321 weld::TreeView
& xCategories
= m_xCategories
->get_widget();
1322 std::unique_ptr
<weld::TreeIter
> xIter
= xCategories
.make_iterator();
1324 if (!xCategories
.get_selected(xIter
.get()))
1329 sMacroInfo
= xCategories
.get_text(*xIter
) + "|" + sMacroInfo
;
1330 } while (xCategories
.iter_parent(*xIter
));
1332 SvtViewOptions( EViewType::Dialog
, MACRO_SELECTOR_CONFIGNAME
).SetUserItem(
1333 LAST_RUN_MACRO_INFO
, Any(sMacroInfo
));
1337 SvxScriptSelectorDialog::LoadLastUsedMacro()
1339 SvtViewOptions
aDlgOpt( EViewType::Dialog
, MACRO_SELECTOR_CONFIGNAME
);
1340 if (!aDlgOpt
.Exists())
1343 OUString sMacroInfo
;
1344 aDlgOpt
.GetUserItem(LAST_RUN_MACRO_INFO
) >>= sMacroInfo
;
1345 if (sMacroInfo
.isEmpty())
1348 // Counts how many entries exist in the macro info string
1349 sal_Int16 nInfoParts
= 0;
1350 sal_Int16 nLastIndex
= sMacroInfo
.indexOf('|');
1351 if (nLastIndex
> -1)
1354 while ( nLastIndex
!= -1 )
1357 nLastIndex
= sMacroInfo
.indexOf('|', nLastIndex
+ 1);
1361 weld::TreeView
& xCategories
= m_xCategories
->get_widget();
1362 std::unique_ptr
<weld::TreeIter
> xIter
= xCategories
.make_iterator();
1363 if (!xCategories
.get_iter_first(*xIter
))
1366 // Expand the nodes in the category tree
1367 OUString sNodeToExpand
;
1369 sal_Int16 nOpenedNodes
= 0;
1370 for (sal_Int16 i
=0; i
<nInfoParts
- 1; i
++)
1372 sNodeToExpand
= sMacroInfo
.getToken(i
, '|');
1373 bIsIterValid
= true;
1374 while (bIsIterValid
&& xCategories
.get_text(*xIter
) != sNodeToExpand
)
1375 bIsIterValid
= xCategories
.iter_next_sibling(*xIter
);
1379 xCategories
.expand_row(*xIter
);
1382 if (xCategories
.iter_has_child(*xIter
))
1383 (void)xCategories
.iter_children(*xIter
);
1384 else if (nOpenedNodes
< nInfoParts
- 1)
1385 // If the number of levels in the tree is smaller than the
1386 // number of parts in the macro info string, then return
1389 xCategories
.select(*xIter
);
1390 xCategories
.scroll_to_row(*xIter
);
1391 m_xCategories
->GroupSelected();
1393 // Select the macro in the command tree
1394 weld::TreeView
& xCommands
= m_xCommands
->get_widget();
1395 xIter
= xCommands
.make_iterator();
1396 if (!xCommands
.get_iter_first(*xIter
))
1399 OUString sMacroName
= sMacroInfo
.getToken(nInfoParts
- 1, '|');
1400 bIsIterValid
= true;
1401 while (bIsIterValid
&& xCommands
.get_text(*xIter
) != sMacroName
)
1402 bIsIterValid
= xCommands
.iter_next_sibling(*xIter
);
1406 xCommands
.scroll_to_row(*xIter
);
1407 xCommands
.select(*xIter
);
1411 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */