diff options
author | Muhammet Kara <muhammet.kara@pardus.org.tr> | 2017-11-27 21:10:21 +0300 |
---|---|---|
committer | Muhammet Kara <muhammet.kara@pardus.org.tr> | 2017-12-04 12:55:54 +0100 |
commit | 3b12778af71951bfce321c73509e8b0c59b02853 (patch) | |
tree | e109782bf0d037be3ca4d565140192d45eaaf319 /cui | |
parent | 5ea28efc864b0b064512f2049a9acd82aeaae808 (diff) |
tdf#112207: Allow assigning macros to ui elements
* Adds "Macros" category to the categories list
* Search/filter feature now works also on the macros category
* Since macros category has multiple trees and subtrees, and many leaf
elements (macros). I chose to implement the behavior like this:
If there is no filter/search term, the trees will be presented as in the old
macro selector dialog (collapsed), but if user types a search term, then
filtering happens: non-matching elements and empty containers/(sub)trees
are removed and everything is expanded so that user easily sees what
(s)he is looking for.
Change-Id: I1a93f156a7293c7e61baac882a10ff631961e2af
Reviewed-on: https://gerrit.libreoffice.org/44938
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Heiko Tietze <tietze.heiko@googlemail.com>
Reviewed-by: Katarina Behrens <Katarina.Behrens@cib.de>
(cherry picked from commit 3f2915c40fcc42ac91f2019fd506bfbdd1e5933f)
Reviewed-on: https://gerrit.libreoffice.org/45779
Diffstat (limited to 'cui')
-rw-r--r-- | cui/inc/strings.hrc | 2 | ||||
-rw-r--r-- | cui/source/customize/CommandCategoryListBox.cxx | 215 | ||||
-rw-r--r-- | cui/source/inc/CommandCategoryListBox.hxx | 5 |
3 files changed, 211 insertions, 11 deletions
diff --git a/cui/inc/strings.hrc b/cui/inc/strings.hrc index dca50c2cd57a..27dd89ba48d1 100644 --- a/cui/inc/strings.hrc +++ b/cui/inc/strings.hrc @@ -89,8 +89,10 @@ #define RID_SVXSTR_ERR_TEXTNOTFOUND NC_("RID_SVXSTR_ERR_TEXTNOTFOUND", "No alternatives found.") #define RID_SVXSTR_SELECT_FILE_IFRAME NC_("RID_SVXSTR_SELECT_FILE_IFRAME", "Select File for Floating Frame") #define RID_SVXSTR_ALLFUNCTIONS NC_("RID_SVXSTR_ALLFUNCTIONS", "All categories") +#define RID_SVXSTR_MACROS NC_("RID_SVXSTR_MACROS", "Macros") #define RID_SVXSTR_MYMACROS NC_("RID_SVXSTR_MYMACROS", "My Macros") #define RID_SVXSTR_PRODMACROS NC_("RID_SVXSTR_PRODMACROS", "%PRODUCTNAME Macros") +#define RID_SVXSTR_NOMACRODESC NC_("RID_SVXSTR_NOMACRODESC", "There is no description available for this macro.") #define RID_SVXSTR_SELECTOR_ADD_COMMANDS NC_("RID_SVXSTR_SELECTOR_ADD_COMMANDS", "Add Commands") #define RID_SVXSTR_SELECTOR_RUN NC_("RID_SVXSTR_SELECTOR_RUN", "Run") #define RID_SVXSTR_ROW NC_("RID_SVXSTR_ROW", "Insert Rows") diff --git a/cui/source/customize/CommandCategoryListBox.cxx b/cui/source/customize/CommandCategoryListBox.cxx index 1763196db5ab..ae100bf0bc03 100644 --- a/cui/source/customize/CommandCategoryListBox.cxx +++ b/cui/source/customize/CommandCategoryListBox.cxx @@ -20,9 +20,15 @@ #include <CommandCategoryListBox.hxx> #include <svtools/treelistentry.hxx> +#include <com/sun/star/uno/XInterface.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/frame/XDispatchInformationProvider.hpp> #include <com/sun/star/frame/theUICommandDescription.hpp> #include <com/sun/star/ui/theUICategoryDescription.hpp> +#include <com/sun/star/script/browse/XBrowseNode.hpp> +#include <com/sun/star/script/browse/BrowseNodeTypes.hpp> +#include <com/sun/star/script/browse/theBrowseNodeFactory.hpp> +#include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp> #include <vcl/builderfactory.hxx> // include search util @@ -65,8 +71,7 @@ void CommandCategoryListBox::dispose() void CommandCategoryListBox::ClearAll() { - //TODO: Handle SfxCfgKind::GROUP_SCRIPTCONTAINER when it gets added to Init - // Clear style info objects from m_aGroupInfo vector to avoid memory leak + // Clear objects from m_aGroupInfo vector to avoid memory leak for (const auto & It : m_aGroupInfo) { if ( It->nKind == SfxCfgKind::GROUP_STYLES && It->pObject ) @@ -74,6 +79,19 @@ void CommandCategoryListBox::ClearAll() SfxStyleInfo_Impl* pStyle = static_cast<SfxStyleInfo_Impl*>(It->pObject); delete pStyle; } + else if ( It->nKind == SfxCfgKind::FUNCTION_SCRIPT && It->pObject ) + { + OUString* pScriptURI = static_cast<OUString*>(It->pObject); + delete pScriptURI; + } + else if ( It->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER && It->pObject) + { + css::uno::XInterface* xi = static_cast<css::uno::XInterface *>(It->pObject); + if (xi != nullptr) + { + xi->release(); + } + } } m_aGroupInfo.clear(); @@ -85,6 +103,7 @@ void CommandCategoryListBox::Init( const css::uno::Reference< css::frame::XFrame >& xFrame, const OUString& sModuleLongName) { + // User will not see incomplete UI SetUpdateMode(false); ClearAll(); @@ -107,7 +126,6 @@ void CommandCategoryListBox::Init( m_aStylesInfo.init(sModuleLongName, xModel); SetStylesInfo(&m_aStylesInfo); -/**** InitModule Start ****/ try { css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider(m_xFrame, css::uno::UNO_QUERY_THROW); @@ -143,23 +161,32 @@ void CommandCategoryListBox::Init( } nEntryPos = InsertEntry( sGroupName ); - m_aGroupInfo.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_FUNCTION, rGroupID ) ); + m_aGroupInfo.push_back( + o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_FUNCTION, rGroupID ) ); SetEntryData( nEntryPos, m_aGroupInfo.back().get() ); } - // Add styles + // Add macros category + OUString sMacros( CuiResId(RID_SVXSTR_MACROS) ); + nEntryPos = InsertEntry( sMacros ); + m_aGroupInfo.push_back( + o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, nullptr) ); + SetEntryData( nEntryPos, m_aGroupInfo.back().get() ); + + // Add styles category OUString sStyle( CuiResId(RID_SVXSTR_GROUP_STYLES) ); nEntryPos = InsertEntry( sStyle ); //TODO: last param should contain user data? - m_aGroupInfo.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); + m_aGroupInfo.push_back( + o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); SetEntryData( nEntryPos, m_aGroupInfo.back().get() ); } catch(const css::uno::RuntimeException&) { throw; } catch(const css::uno::Exception&) {} -/**** InitModule End ****/ + // Reveal the updated UI to user SetUpdateMode(true); SelectEntryPos(0); } @@ -258,7 +285,6 @@ void CommandCategoryListBox::categorySelected( const VclPtr<SfxConfigFunctionLi } } - break; } case SfxCfgKind::GROUP_FUNCTION: @@ -271,9 +297,85 @@ void CommandCategoryListBox::categorySelected( const VclPtr<SfxConfigFunctionLi FillFunctionsList( lCommands, pFunctionListBox, filterTerm ); break; } - case SfxCfgKind::GROUP_SCRIPTCONTAINER: + case SfxCfgKind::GROUP_SCRIPTCONTAINER: //Macros { - //TODO:Implement + SAL_INFO("cui.customize", "** ** About to initialise SF Scripts"); + // Add Scripting Framework entries + css::uno::Reference< css::script::browse::XBrowseNode > rootNode; + try + { + css::uno::Reference< css::script::browse::XBrowseNodeFactory > xFac + = css::script::browse::theBrowseNodeFactory::get( m_xContext ); + rootNode.set( xFac->createView( css::script::browse::BrowseNodeFactoryViewTypes::MACROSELECTOR ) ); + } + catch( css::uno::Exception& e ) + { + SAL_WARN("cui.customize", "Caught some exception whilst retrieving browse nodes from factory... Exception: " << e); + // TODO exception handling + } + + if ( rootNode.is() && rootNode.get()->hasChildNodes() ) + { + //We call acquire on the XBrowseNode so that it does not + //get autodestructed and become invalid when accessed later. + rootNode->acquire(); + + m_aGroupInfo.push_back( + o3tl::make_unique<SfxGroupInfo_Impl>( + SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, static_cast<void *>(rootNode.get()) ) ); + + // Add main macro groups + for ( auto const & childGroup : rootNode.get()->getChildNodes() ) + { + OUString sUIName; + childGroup.get()->acquire(); + + if ( childGroup.get()->hasChildNodes() ) + { + if ( childGroup.get()->getName() == "user" ) + { + sUIName = CuiResId( RID_SVXSTR_MYMACROS ); + } + else if ( childGroup.get()->getName() == "share" ) + { + sUIName = CuiResId( RID_SVXSTR_PRODMACROS ); + } + else + { + sUIName = childGroup.get()->getName(); + } + + if (sUIName.isEmpty()) + { + continue; + } + + SvTreeListEntry* pMacroGroup = pFunctionListBox->InsertEntry( + sUIName, + Image( BitmapEx(RID_CUIBMP_EXPANDED) ), Image( BitmapEx(RID_CUIBMP_COLLAPSED) ) ); + m_aGroupInfo.push_back( + o3tl::make_unique<SfxGroupInfo_Impl>( + SfxCfgKind::GROUP_SCRIPTCONTAINER, 0 ) ); + SfxGroupInfo_Impl* pGrpInfo = m_aGroupInfo.back().get(); + pMacroGroup->SetUserData(pGrpInfo); + pMacroGroup->EnableChildrenOnDemand(); + + //Add the children and the grand children + addChildren( pMacroGroup, childGroup, pFunctionListBox, filterTerm ); + + // Remove the main group if empty + if (!pMacroGroup->HasChildren()) + { + pFunctionListBox->RemoveEntry( pMacroGroup ); + } + else if (!filterTerm.isEmpty()) + { + pFunctionListBox->Expand( pMacroGroup ); + } + } + } + } + break; } case SfxCfgKind::GROUP_STYLES: @@ -335,7 +437,7 @@ void CommandCategoryListBox::categorySelected( const VclPtr<SfxConfigFunctionLi { pFunctionListBox->RemoveEntry(pFuncEntry); } - else + else if (!filterTerm.isEmpty()) { pFunctionListBox->Expand(pFuncEntry); } @@ -360,4 +462,95 @@ void CommandCategoryListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles) pStylesInfo = pStyles; } +void CommandCategoryListBox::addChildren( + SvTreeListEntry* parentEntry, const css::uno::Reference< css::script::browse::XBrowseNode > &parentNode, + const VclPtr<SfxConfigFunctionListBox>& pFunctionListBox, const OUString& filterTerm ) +{ + // Setup search filter parameters + m_searchOptions.searchString = filterTerm; + utl::TextSearch textSearch( m_searchOptions ); + + for (auto const & child : parentNode.get()->getChildNodes()) + { + // Acquire to prevent auto-destruction + child.get()->acquire(); + + if (child.get()->hasChildNodes()) + { + OUString sUIName = child.get()->getName(); + + SvTreeListEntry* pNewEntry = pFunctionListBox->InsertEntry( sUIName, parentEntry ); + + m_aGroupInfo.push_back( o3tl::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_SCRIPTCONTAINER, + 0, static_cast<void *>( child.get()))); + pNewEntry->SetUserData( m_aGroupInfo.back().get() ); + + + + pFunctionListBox->SetExpandedEntryBmp(pNewEntry, Image( BitmapEx(RID_CUIBMP_EXPANDED) ) ); + pFunctionListBox->SetCollapsedEntryBmp(pNewEntry, Image( BitmapEx(RID_CUIBMP_COLLAPSED) ) ); + pNewEntry->EnableChildrenOnDemand(); + + addChildren(pNewEntry, child, pFunctionListBox, filterTerm); + + // Remove the group if empty + if (!pNewEntry->HasChildren()) + pFunctionListBox->RemoveEntry( pNewEntry ); + else + pFunctionListBox->Expand( pNewEntry ); + + } + else if ( child.get()->getType() == css::script::browse::BrowseNodeTypes::SCRIPT ) + { + // Prepare for filtering + OUString sUIName = child.get()->getName(); + sal_Int32 aStartPos = 0; + sal_Int32 aEndPos = sUIName.getLength(); + + // Apply the search filter + if (!filterTerm.isEmpty() + && !textSearch.SearchForward( sUIName, &aStartPos, &aEndPos ) ) + { + continue; + } + + OUString uri, description; + + css::uno::Reference < css::beans::XPropertySet >xPropSet( child.get(), css::uno::UNO_QUERY ); + + if (!xPropSet.is()) + { + continue; + } + + css::uno::Any value = xPropSet->getPropertyValue("URI"); + value >>= uri; + + try + { + value = xPropSet->getPropertyValue("Description"); + value >>= description; + } + catch (css::uno::Exception &) { + // do nothing, the description will be empty + } + + if (description.isEmpty()) + { + description = CuiResId( RID_SVXSTR_NOMACRODESC ); + } + + OUString* pScriptURI = new OUString( uri ); + + SvTreeListEntry* pNewEntry = pFunctionListBox->InsertEntry( sUIName, parentEntry ); + + m_aGroupInfo.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI )); + m_aGroupInfo.back()->sCommand = uri; + m_aGroupInfo.back()->sLabel = sUIName; + m_aGroupInfo.back()->sHelpText = description; + pNewEntry->SetUserData( m_aGroupInfo.back().get() ); + } + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/cui/source/inc/CommandCategoryListBox.hxx b/cui/source/inc/CommandCategoryListBox.hxx index a80f80a6f5be..8149cc6f261c 100644 --- a/cui/source/inc/CommandCategoryListBox.hxx +++ b/cui/source/inc/CommandCategoryListBox.hxx @@ -64,6 +64,11 @@ public: const OUString& filterTerm = OUString() ); void SetStylesInfo(SfxStylesInfo_Impl* pStyles); + + // Adds children of the given macro group to the functions list + void addChildren( + SvTreeListEntry* parentEntry, const css::uno::Reference<com::sun::star::script::browse::XBrowseNode> &parentNode, + const VclPtr<SfxConfigFunctionListBox> &pFunctionListBox, const OUString &filterTerm); }; #endif // INCLUDED_CUI_SOURCE_INC_COMMANDCATEGORYLISTBOX_HXX |