cui/source/customize/cfgutil.cxx | 779 ++++++++++++++++++++++++++++++++++- cui/source/customize/macropg.cxx | 11 cui/source/inc/cfgutil.hxx | 93 ++++ cui/source/inc/headertablistbox.hxx | 16 cui/source/inc/macroass.hxx | 14 cui/source/tabpages/macroass.cxx | 272 +++++------- cui/uiconfig/ui/eventassignpage.ui | 191 +++++--- include/sfx2/sfxhelp.hxx | 3 include/vcl/builder.hxx | 4 include/vcl/help.hxx | 3 include/vcl/weld.hxx | 3 sfx2/source/appl/sfxhelp.cxx | 43 + sfx2/source/dialog/filedlghelper.cxx | 2 vcl/source/app/help.cxx | 5 vcl/source/app/salvtables.cxx | 43 + vcl/source/treelist/treelistbox.cxx | 4 vcl/source/window/builder.cxx | 23 - vcl/source/window/menu.cxx | 4 vcl/unx/gtk/salprn-gtk.cxx | 2 vcl/unx/gtk3/gtk3gtkinst.cxx | 31 + 20 files changed, 1284 insertions(+), 262 deletions(-)
New commits: commit f27bfc190d4105b9d057980a5e6f0eac07f88aba Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Fri Nov 23 09:14:32 2018 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Fri Nov 23 21:28:16 2018 +0100 weld SfxMacroTabPage Change-Id: I167dd233c8af64e31f0e266bac5cf5b9c4658ca6 Reviewed-on: https://gerrit.libreoffice.org/63893 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> diff --git a/cui/source/customize/cfgutil.cxx b/cui/source/customize/cfgutil.cxx index 828205e31f93..d0900c2ccbab 100644 --- a/cui/source/customize/cfgutil.cxx +++ b/cui/source/customize/cfgutil.cxx @@ -330,7 +330,7 @@ OUString SfxConfigFunctionListBox::GetHelpText( bool bConsiderParent ) if (bConsiderParent) return Application::GetHelp()->GetHelpText( pData->sCommand, this ); else - return Application::GetHelp()->GetHelpText( pData->sCommand, nullptr ); + return Application::GetHelp()->GetHelpText( pData->sCommand, static_cast<weld::Widget*>(nullptr) ); } else if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) { @@ -365,6 +365,108 @@ OUString SfxConfigFunctionListBox::GetCurLabel() return pData->sCommand; } +CuiConfigFunctionListBox::CuiConfigFunctionListBox(std::unique_ptr<weld::TreeView> xTreeView) + : m_xTreeView(std::move(xTreeView)) +{ + m_xTreeView->make_sorted(); +} + +CuiConfigFunctionListBox::~CuiConfigFunctionListBox() +{ + ClearAll(); +} + +void CuiConfigFunctionListBox::ClearAll() +/* Description + Deletes all entries in the FunctionListBox, all UserData and all + possibly existing MacroInfo. +*/ +{ + sal_uInt16 nCount = aArr.size(); + for ( sal_uInt16 i=0; i<nCount; ++i ) + { + SfxGroupInfo_Impl *pData = aArr[i].get(); + + if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) + { + OUString* pScriptURI = static_cast<OUString*>(pData->pObject); + delete pScriptURI; + } + + if ( pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER ) + { + XInterface* xi = static_cast<XInterface *>(pData->pObject); + if (xi != nullptr) + { + xi->release(); + } + } + } + + aArr.clear(); + m_xTreeView->clear(); +} + +OUString CuiConfigFunctionListBox::GetSelectedScriptURI() +{ + int nSelected = m_xTreeView->get_selected_index(); + if (nSelected != -1) + { + SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64()); + if (pData && pData->nKind == SfxCfgKind::FUNCTION_SCRIPT) + return *static_cast<OUString*>(pData->pObject); + } + return OUString(); +} + +OUString CuiConfigFunctionListBox::GetHelpText( bool bConsiderParent ) +{ + int nSelected = m_xTreeView->get_selected_index(); + if (nSelected != -1) + { + SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64()); + if ( pData ) + { + if ( pData->nKind == SfxCfgKind::FUNCTION_SLOT ) + { + if (bConsiderParent) + return Application::GetHelp()->GetHelpText(pData->sCommand, m_xTreeView.get()); + else + return Application::GetHelp()->GetHelpText(pData->sCommand, static_cast<weld::Widget*>(nullptr)); + } + else if ( pData->nKind == SfxCfgKind::FUNCTION_SCRIPT ) + { + return pData->sHelpText; + } + } + } + return OUString(); +} + +OUString CuiConfigFunctionListBox::GetCurCommand() +{ + int nSelected = m_xTreeView->get_selected_index(); + if (nSelected == -1) + return OUString(); + SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64()); + if (!pData) + return OUString(); + return pData->sCommand; +} + +OUString CuiConfigFunctionListBox::GetCurLabel() +{ + int nSelected = m_xTreeView->get_selected_index(); + if (nSelected == -1) + return OUString(); + SfxGroupInfo_Impl *pData = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(nSelected).toInt64()); + if (!pData) + return OUString(); + if (!pData->sLabel.isEmpty()) + return pData->sLabel; + return pData->sCommand; +} + struct SvxConfigGroupBoxResource_Impl { Image m_hdImage; @@ -397,6 +499,34 @@ SvxConfigGroupBoxResource_Impl::SvxConfigGroupBoxResource_Impl() : { } +struct CuiConfigGroupBoxResource_Impl +{ + OUString m_hdImage; + OUString m_libImage; + OUString m_macImage; + OUString m_docImage; + OUString m_sMyMacros; + OUString m_sProdMacros; + OUString m_sMacros; + OUString m_sDlgMacros; + OUString m_aStrGroupStyles; + + CuiConfigGroupBoxResource_Impl(); +}; + +CuiConfigGroupBoxResource_Impl::CuiConfigGroupBoxResource_Impl() : + m_hdImage(RID_CUIBMP_HARDDISK), + m_libImage(RID_CUIBMP_LIB), + m_macImage(RID_CUIBMP_MACRO), + m_docImage(RID_CUIBMP_DOC), + m_sMyMacros(CuiResId(RID_SVXSTR_MYMACROS)), + m_sProdMacros(CuiResId(RID_SVXSTR_PRODMACROS)), + m_sMacros(CuiResId(RID_SVXSTR_BASICMACROS)), + m_sDlgMacros(CuiResId(RID_SVXSTR_PRODMACROS)), + m_aStrGroupStyles(CuiResId(RID_SVXSTR_GROUP_STYLES)) +{ +} + SfxConfigGroupListBox::SfxConfigGroupListBox(vcl::Window* pParent, WinBits nStyle) : SvTreeListBox(pParent, nStyle) , xImp(new SvxConfigGroupBoxResource_Impl()) @@ -1133,6 +1263,653 @@ void SfxConfigGroupListBox::SelectMacro( const OUString& rBasic, } } +CuiConfigGroupListBox::CuiConfigGroupListBox(std::unique_ptr<weld::TreeView> xTreeView) + : xImp(new CuiConfigGroupBoxResource_Impl()) + , m_pFunctionListBox(nullptr) + , m_pStylesInfo(nullptr) + , m_xTreeView(std::move(xTreeView)) +{ + m_xTreeView->connect_row_activated(LINK(this, CuiConfigGroupListBox, OpenCurrentHdl)); + m_xTreeView->connect_expanding(LINK(this, CuiConfigGroupListBox, ExpandingHdl)); +} + +IMPL_LINK_NOARG(CuiConfigGroupListBox, OpenCurrentHdl, weld::TreeView&, void) +{ + std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator()); + bool bValidIter = m_xTreeView->get_cursor(xIter.get()); + if (!bValidIter) + return; + m_xTreeView->expand_row(*xIter); +} + +CuiConfigGroupListBox::~CuiConfigGroupListBox() +{ + ClearAll(); +} + +void CuiConfigGroupListBox::ClearAll() +{ + sal_uInt16 nCount = aArr.size(); + for ( sal_uInt16 i=0; i<nCount; ++i ) + { + SfxGroupInfo_Impl *pData = aArr[i].get(); + if (pData->nKind == SfxCfgKind::GROUP_SCRIPTCONTAINER) + { + XInterface* xi = static_cast<XInterface *>(pData->pObject); + if (xi != nullptr) + { + xi->release(); + } + } + } + + aArr.clear(); + m_xTreeView->clear(); +} + +void CuiConfigGroupListBox::SetStylesInfo(SfxStylesInfo_Impl* pStyles) +{ + m_pStylesInfo = pStyles; +} + +void CuiConfigGroupListBox::InitModule() +{ + try + { + css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider(m_xFrame, css::uno::UNO_QUERY_THROW); + css::uno::Sequence< sal_Int16 > lGroups = xProvider->getSupportedCommandGroups(); + sal_Int32 c1 = lGroups.getLength(); + sal_Int32 i1 = 0; + + if ( c1 ) + { + // Add All Commands category + aArr.push_back(o3tl::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_ALLFUNCTIONS, 0)); + m_xTreeView->append(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get())), + CuiResId(RID_SVXSTR_ALLFUNCTIONS)); + } + + for (i1=0; i1<c1; ++i1) + { + sal_Int16& rGroupID = lGroups[i1]; + OUString sGroupID = OUString::number(rGroupID); + OUString sGroupName ; + + try + { + m_xModuleCategoryInfo->getByName(sGroupID) >>= sGroupName; + if (sGroupName.isEmpty()) + continue; + } + catch(const css::container::NoSuchElementException&) + { continue; } + + aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_FUNCTION, rGroupID ) ); + m_xTreeView->append(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get())), + sGroupName); + } + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + {} +} + +void CuiConfigGroupListBox::FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode, + weld::TreeIter* pParentEntry, bool bCheapChildrenOnDemand) +{ + try { + if ( xRootNode->hasChildNodes() ) + { + // tdf#120362: Don't ask to enable disabled Java when filling script list + css::uno::ContextLayer layer( + new comphelper::NoEnableJavaInteractionContext(css::uno::getCurrentContext())); + + Sequence< Reference< browse::XBrowseNode > > children = + xRootNode->getChildNodes(); + bool bIsRootNode = false; + + OUString user("user"); + OUString share("share"); + if ( xRootNode->getName() == "Root" ) + { + bIsRootNode = true; + } + + //To mimic current starbasic behaviour we + //need to make sure that only the current document + //is displayed in the config tree. Tests below + //set the bDisplay flag to FALSE if the current + //node is a first level child of the Root and is NOT + //either the current document, user or share + OUString currentDocTitle; + Reference< XModel > xDocument( lcl_getScriptableDocument_nothrow( m_xFrame ) ); + if ( xDocument.is() ) + { + currentDocTitle = ::comphelper::DocumentInfo::getDocumentTitle( xDocument ); + } + + for ( sal_Int32 n = 0; n < children.getLength(); ++n ) + { + Reference< browse::XBrowseNode >& theChild = children[n]; + bool bDisplay = true; + OUString uiName = theChild->getName(); + if ( bIsRootNode ) + { + if ( ! (theChild->getName() == user || theChild->getName() == share || + theChild->getName() == currentDocTitle ) ) + { + bDisplay=false; + } + else + { + if ( uiName == user ) + { + uiName = xImp->m_sMyMacros; + } + else if ( uiName == share ) + { + uiName = xImp->m_sProdMacros; + } + } + } + if (children[n]->getType() != browse::BrowseNodeTypes::SCRIPT && bDisplay ) + { +// We call acquire on the XBrowseNode so that it does not +// get autodestructed and become invalid when accessed later. + theChild->acquire(); + + bool bChildOnDemand = false; + if ( !bCheapChildrenOnDemand && children[n]->hasChildNodes() ) + { + Sequence< Reference< browse::XBrowseNode > > grandchildren = + children[n]->getChildNodes(); + + for ( sal_Int32 m = 0; m < grandchildren.getLength(); ++m ) + { + if ( grandchildren[m]->getType() == browse::BrowseNodeTypes::CONTAINER ) + { + bChildOnDemand = true; + m = grandchildren.getLength(); + } + } + } + else + { + /* i30923 - Would be nice if there was a better + * way to determine if a basic lib had children + * without having to ask for them (which forces + * the library to be loaded */ + bChildOnDemand = true; + } + + OUString aImage = GetImage(theChild, m_xContext, bIsRootNode); + + aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_SCRIPTCONTAINER, + 0, static_cast<void *>( theChild.get()))); + + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get()))); + m_xTreeView->insert(pParentEntry, -1, uiName, &sId, nullptr, nullptr, &aImage, bChildOnDemand); + } + } + } + } + catch (RuntimeException&) { + // do nothing, the entry will not be displayed in the UI + } +} + +void CuiConfigGroupListBox::FillFunctionsList(const css::uno::Sequence<DispatchInformation>& xCommands) +{ + for (const auto & rInfo : xCommands) + { + OUString sUIName = MapCommand2UIName(rInfo.Command); + aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SLOT, 0 ) ); + SfxGroupInfo_Impl* pGrpInfo = aArr.back().get(); + pGrpInfo->sCommand = rInfo.Command; + pGrpInfo->sLabel = sUIName; + m_pFunctionListBox->append(OUString::number(reinterpret_cast<sal_Int64>(pGrpInfo)), sUIName); + } +} + +void CuiConfigGroupListBox::Init(const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XFrame >& xFrame, + const OUString& sModuleLongName, + bool bEventMode) +{ + m_xTreeView->freeze(); + ClearAll(); // Remove all old entries from treelist box + + m_xContext = xContext; + m_xFrame = xFrame; + if( bEventMode ) + { + m_sModuleLongName = sModuleLongName; + m_xGlobalCategoryInfo = css::ui::theUICategoryDescription::get( m_xContext ); + m_xModuleCategoryInfo.set(m_xGlobalCategoryInfo->getByName(m_sModuleLongName), css::uno::UNO_QUERY_THROW); + m_xUICmdDescription = css::frame::theUICommandDescription::get( m_xContext ); + + InitModule(); + } + + SAL_INFO("cui.customize", "** ** About to initialise SF Scripts"); + // Add Scripting Framework entries + Reference< browse::XBrowseNode > rootNode; + try + { + Reference< browse::XBrowseNodeFactory > xFac = browse::theBrowseNodeFactory::get( m_xContext ); + rootNode.set( xFac->createView( browse::BrowseNodeFactoryViewTypes::MACROSELECTOR ) ); + } + catch( Exception& e ) + { + SAL_INFO("cui.customize", "Caught some exception whilst retrieving browse nodes from factory... Exception: " << e); + // TODO exception handling + } + + + if ( rootNode.is() ) + { + if ( bEventMode ) + { + //We call acquire on the XBrowseNode so that it does not + //get autodestructed and become invalid when accessed later. + rootNode->acquire(); + + aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_SCRIPTCONTAINER, 0, + static_cast<void *>(rootNode.get()))); + OUString aTitle(xImp->m_sDlgMacros); + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get()))); + m_xTreeView->insert(nullptr, -1, aTitle, &sId, nullptr, nullptr, nullptr, true); + } + else + { + //We are only showing scripts not slot APIs so skip + //Root node and show location nodes + FillScriptList(rootNode, nullptr, false); + } + } + + // add styles + if ( bEventMode ) + { + aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, nullptr ) ); // TODO last parameter should contain user data + OUString sStyle(xImp->m_aStrGroupStyles); + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get()))); + m_xTreeView->insert(nullptr, -1, sStyle, &sId, nullptr, nullptr, nullptr, true); + } + + m_xTreeView->scroll_to_row(0); + m_xTreeView->thaw(); + m_xTreeView->select(0); +} + +OUString CuiConfigGroupListBox::GetImage( + const Reference< browse::XBrowseNode >& node, + Reference< XComponentContext > const & xCtx, + bool bIsRootNode) +{ + OUString aImage; + if ( bIsRootNode ) + { + if (node->getName() == "user" || node->getName() == "share" ) + { + aImage = xImp->m_hdImage; + } + else + { + OUString factoryURL; + OUString nodeName = node->getName(); + Reference<XInterface> xDocumentModel = getDocumentModel(xCtx, nodeName ); + if ( xDocumentModel.is() ) + { + Reference< frame::XModuleManager2 > xModuleManager( frame::ModuleManager::create(xCtx) ); + // get the long name of the document: + OUString appModule( xModuleManager->identify( + xDocumentModel ) ); + Sequence<beans::PropertyValue> moduleDescr; + Any aAny = xModuleManager->getByName(appModule); + if( !( aAny >>= moduleDescr ) ) + { + throw RuntimeException("SFTreeListBox::Init: failed to get PropertyValue"); + } + beans::PropertyValue const * pmoduleDescr = + moduleDescr.getConstArray(); + for ( sal_Int32 pos = moduleDescr.getLength(); pos--; ) + { + if ( pmoduleDescr[ pos ].Name == "ooSetupFactoryEmptyDocumentURL" ) + { + pmoduleDescr[ pos ].Value >>= factoryURL; + SAL_INFO("cui.customize", "factory url for doc images is " << factoryURL); + break; + } + } + } + if( !factoryURL.isEmpty() ) + { + aImage = SvFileInformationManager::GetFileImageId(INetURLObject(factoryURL)); + } + else + { + aImage = xImp->m_docImage; + } + } + } + else + { + if( node->getType() == browse::BrowseNodeTypes::SCRIPT ) + aImage = xImp->m_macImage; + else + aImage = xImp->m_libImage; + } + return aImage; +} + +Reference< XInterface > +CuiConfigGroupListBox::getDocumentModel( Reference< XComponentContext > const & xCtx, OUString const & docName ) +{ + Reference< XInterface > xModel; + Reference< frame::XDesktop2 > desktop = frame::Desktop::create( xCtx ); + + Reference< container::XEnumerationAccess > componentsAccess = + desktop->getComponents(); + Reference< container::XEnumeration > components = + componentsAccess->createEnumeration(); + while (components->hasMoreElements()) + { + Reference< frame::XModel > model( + components->nextElement(), UNO_QUERY ); + if ( model.is() ) + { + OUString sTdocUrl = + ::comphelper::DocumentInfo::getDocumentTitle( model ); + if( sTdocUrl == docName ) + { + xModel = model; + break; + } + } + } + return xModel; +} + +OUString CuiConfigGroupListBox::MapCommand2UIName(const OUString& sCommand) +{ + OUString sUIName; + try + { + css::uno::Reference< css::container::XNameAccess > xModuleConf; + m_xUICmdDescription->getByName(m_sModuleLongName) >>= xModuleConf; + if (xModuleConf.is()) + { + ::comphelper::SequenceAsHashMap lProps(xModuleConf->getByName(sCommand)); + sUIName = lProps.getUnpackedValueOrDefault("Name", OUString()); + } + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(css::uno::Exception&) + { sUIName.clear(); } + + // fallback for missing UINames !? + if (sUIName.isEmpty()) + { + sUIName = sCommand; + } + + return sUIName; +} + +void CuiConfigGroupListBox::GroupSelected() +/* Description + A function group or a basic module has been selected. + All functions/macros are displayed in the functionlistbox. +*/ +{ + std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator()); + if (!m_xTreeView->get_selected(xIter.get())) + return; + + SfxGroupInfo_Impl *pInfo = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(*xIter).toInt64()); + m_pFunctionListBox->freeze(); + m_pFunctionListBox->ClearAll(); + + switch ( pInfo->nKind ) + { + case SfxCfgKind::GROUP_ALLFUNCTIONS: + { + css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider( m_xFrame, UNO_QUERY ); + bool bValidIter = m_xTreeView->get_iter_first(*xIter); + while (bValidIter) + { + SfxGroupInfo_Impl *pCurrentInfo = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(*xIter).toInt64()); + if (pCurrentInfo->nKind == SfxCfgKind::GROUP_FUNCTION) + { + css::uno::Sequence< css::frame::DispatchInformation > lCommands; + try + { + lCommands = xProvider->getConfigurableDispatchInformation( pCurrentInfo->nUniqueID ); + FillFunctionsList( lCommands ); + } + catch ( container::NoSuchElementException& ) + { + } + } + bValidIter = m_xTreeView->iter_next(*xIter); + } + break; + } + + case SfxCfgKind::GROUP_FUNCTION : + { + sal_uInt16 nGroup = pInfo->nUniqueID; + css::uno::Reference< css::frame::XDispatchInformationProvider > xProvider (m_xFrame, css::uno::UNO_QUERY_THROW); + css::uno::Sequence< css::frame::DispatchInformation > lCommands = xProvider->getConfigurableDispatchInformation(nGroup); + FillFunctionsList( lCommands ); + break; + } + + case SfxCfgKind::GROUP_SCRIPTCONTAINER: + { + if (!m_xTreeView->iter_has_child(*xIter)) + { + Reference< browse::XBrowseNode > rootNode( + static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; + + try { + if ( rootNode->hasChildNodes() ) + { + Sequence< Reference< browse::XBrowseNode > > children = + rootNode->getChildNodes(); + + for ( sal_Int32 n = 0; n < children.getLength(); ++n ) + { + if (children[n]->getType() == browse::BrowseNodeTypes::SCRIPT) + { + OUString uri, description; + + Reference < beans::XPropertySet >xPropSet( children[n], UNO_QUERY ); + if (!xPropSet.is()) + { + continue; + } + + Any value = + xPropSet->getPropertyValue("URI"); + value >>= uri; + + try + { + value = xPropSet->getPropertyValue("Description"); + value >>= description; + } + catch (Exception &) { + // do nothing, the description will be empty + } + + OUString* pScriptURI = new OUString( uri ); + + OUString aImage = GetImage(children[n], Reference< XComponentContext >(), false); + m_pFunctionListBox->aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::FUNCTION_SCRIPT, 0, pScriptURI )); + m_pFunctionListBox->aArr.back()->sCommand = uri; + m_pFunctionListBox->aArr.back()->sLabel = children[n]->getName(); + m_pFunctionListBox->aArr.back()->sHelpText = description; + + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(m_pFunctionListBox->aArr.back().get()))); + m_pFunctionListBox->append(sId, children[n]->getName(), aImage); + } + } + } + } + catch (RuntimeException&) { + // do nothing, the entry will not be displayed in the UI + } + } + break; + } + + case SfxCfgKind::GROUP_STYLES : + { + SfxStyleInfo_Impl* pFamily = static_cast<SfxStyleInfo_Impl*>(pInfo->pObject); + if (pFamily) + { + const std::vector< SfxStyleInfo_Impl > lStyles = m_pStylesInfo->getStyles(pFamily->sFamily); + for (auto const& lStyle : lStyles) + { + SfxStyleInfo_Impl* pStyle = new SfxStyleInfo_Impl(lStyle); + m_pFunctionListBox->aArr.push_back(o3tl::make_unique<SfxGroupInfo_Impl>(SfxCfgKind::GROUP_STYLES, 0, pStyle)); + m_pFunctionListBox->aArr.back()->sCommand = pStyle->sCommand; + m_pFunctionListBox->aArr.back()->sLabel = pStyle->sLabel; + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(m_pFunctionListBox->aArr.back().get()))); + m_pFunctionListBox->append(sId, pStyle->sLabel); + } + } + break; + } + + default: + // Do nothing, the list box will stay empty + SAL_INFO( "cui.customize", "Ignoring unexpected SfxCfgKind: " << static_cast<int>(pInfo->nKind) ); + break; + } + + m_pFunctionListBox->thaw(); + + if (m_pFunctionListBox->n_children()) + m_pFunctionListBox->select(0); +} + +/* Description + A basic or a library is opened. +*/ +IMPL_LINK(CuiConfigGroupListBox, ExpandingHdl, weld::TreeIter&, rIter, bool) +{ + SfxGroupInfo_Impl *pInfo = reinterpret_cast<SfxGroupInfo_Impl*>(m_xTreeView->get_id(rIter).toInt64()); + switch ( pInfo->nKind ) + { + case SfxCfgKind::GROUP_SCRIPTCONTAINER: + { + if (!m_xTreeView->iter_has_child(rIter)) + { + Reference< browse::XBrowseNode > rootNode( + static_cast< browse::XBrowseNode* >( pInfo->pObject ) ) ; + FillScriptList(rootNode, &rIter, true /* i30923 */ ); + } + break; + } + + case SfxCfgKind::GROUP_STYLES: + { + if (!m_xTreeView->iter_has_child(rIter)) + { + const std::vector<SfxStyleInfo_Impl> lStyleFamilies = m_pStylesInfo->getStyleFamilies(); + for (auto const& lStyleFamily : lStyleFamilies) + { + SfxStyleInfo_Impl* pFamily = new SfxStyleInfo_Impl(lStyleFamily); + aArr.push_back( o3tl::make_unique<SfxGroupInfo_Impl>( SfxCfgKind::GROUP_STYLES, 0, pFamily )); + OUString sId(OUString::number(reinterpret_cast<sal_Int64>(aArr.back().get()))); + m_xTreeView->insert(&rIter, -1, pFamily->sLabel, &sId, nullptr, nullptr, nullptr, false); + } + } + break; + } + + default: + OSL_FAIL( "Wrong group type!" ); + break; + } + return true; +} + +void CuiConfigGroupListBox::SelectMacro( const SfxMacroInfoItem *pItem ) +{ + SelectMacro( pItem->GetBasicManager()->GetName(), + pItem->GetQualifiedName() ); +} + +void CuiConfigGroupListBox::SelectMacro( const OUString& rBasic, + const OUString& rMacro ) +{ + const OUString aBasicName(rBasic + " " + xImp->m_sMacros); + const sal_Int32 nCount = comphelper::string::getTokenCount(rMacro, '.'); + const OUString aMethod( rMacro.copy(rMacro.lastIndexOf('.')+1) ); + OUString aLib; + OUString aModule; + if ( nCount > 2 ) + { + aLib = rMacro.getToken( 0, '.' ); + aModule = rMacro.getToken( nCount-2, '.' ); + } + + std::unique_ptr<weld::TreeIter> xIter(m_xTreeView->make_iterator()); + bool bValidIter = m_xTreeView->get_iter_first(*xIter); + while (bValidIter) + { + OUString aEntryBas = m_xTreeView->get_text(*xIter); + if (aEntryBas == aBasicName) + { + m_xTreeView->expand_row(*xIter); + std::unique_ptr<weld::TreeIter> xLibIter(m_xTreeView->make_iterator(xIter.get())); + bool bValidLibIter = m_xTreeView->iter_children(*xLibIter); + while (bValidLibIter) + { + OUString aEntryLib = m_xTreeView->get_text(*xLibIter); + if (aEntryLib == aLib) + { + m_xTreeView->expand_row(*xLibIter); + std::unique_ptr<weld::TreeIter> xModIter(m_xTreeView->make_iterator(xLibIter.get())); + bool bValidModIter = m_xTreeView->iter_children(*xModIter); + while (bValidModIter) + { + OUString aEntryMod = m_xTreeView->get_text(*xModIter); + if (aEntryMod == aModule) + { + m_xTreeView->expand_row(*xModIter); + m_xTreeView->scroll_to_row(*xModIter); + m_xTreeView->select(*xModIter); + std::unique_ptr<weld::TreeIter> xMethodIter(m_pFunctionListBox->make_iterator()); + bool bValidMethodIter = m_pFunctionListBox->get_iter_first(*xMethodIter); + while (bValidMethodIter) + { + OUString aEntryMethod = m_pFunctionListBox->get_text(*xMethodIter); + if (aEntryMethod == aMethod) + { + m_pFunctionListBox->scroll_to_row(*xMethodIter); + m_pFunctionListBox->select(*xMethodIter); + return; + } + bValidMethodIter = m_pFunctionListBox->iter_next(*xMethodIter); + } + } + bValidModIter = m_xTreeView->iter_next_sibling(*xModIter); + } + } + bValidLibIter = m_xTreeView->iter_next_sibling(*xLibIter); + } + } + bValidIter = m_xTreeView->iter_next_sibling(*xIter); + } +} + /* * Implementation of SvxScriptSelectorDialog * diff --git a/cui/source/customize/macropg.cxx b/cui/source/customize/macropg.cxx index 3defde6cce9f..3786f11c0692 100644 --- a/cui/source/customize/macropg.cxx +++ b/cui/source/customize/macropg.cxx @@ -195,6 +195,17 @@ void MacroEventListBox::Enable() maHeaderBar->Enable(); } +CuiMacroEventListBox::CuiMacroEventListBox(std::unique_ptr<weld::TreeView> xTreeView) + : m_xTreeView(std::move(xTreeView)) +{ + m_xTreeView->set_help_id(HID_MACRO_HEADERTABLISTBOX); + m_xTreeView->set_size_request(m_xTreeView->get_approximate_digit_width() * 40, m_xTreeView->get_height_rows(9)); +} + +CuiMacroEventListBox::~CuiMacroEventListBox() +{ +} + // assign button ("Add Command") is enabled only if it is not read only // delete button ("Remove Command") is enabled if a current binding exists // and it is not read only diff --git a/cui/source/inc/cfgutil.hxx b/cui/source/inc/cfgutil.hxx index 40661fc20733..1fb47405fd8f 100644 --- a/cui/source/inc/cfgutil.hxx +++ b/cui/source/inc/cfgutil.hxx @@ -34,6 +34,7 @@ #include <vcl/treelistbox.hxx> #include <vcl/dialog.hxx> #include <vcl/image.hxx> +#include <vcl/weld.hxx> class Button; class SaveInData; @@ -123,6 +124,46 @@ public: OUString GetHelpText( bool bConsiderParent = true ); }; +class CuiConfigFunctionListBox +{ + friend class CuiConfigGroupListBox; + SfxGroupInfoArr_Impl aArr; + + std::unique_ptr<weld::TreeView> m_xTreeView; + +public: + CuiConfigFunctionListBox(std::unique_ptr<weld::TreeView> xTreeView); + void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); } + void connect_changed(const Link<weld::TreeView&, void>& rLink) { m_xTreeView->connect_changed(rLink); } + void connect_row_activated(const Link<weld::TreeView&, void>& rLink) { m_xTreeView->connect_row_activated(rLink); } + void freeze() { m_xTreeView->freeze(); } + void thaw() { m_xTreeView->thaw(); } + void append(const OUString& rId, const OUString& rStr) { m_xTreeView->append(rId, rStr); } + void append(const OUString& rId, const OUString& rStr, const OUString& rImage) + { + m_xTreeView->insert(nullptr, -1, rStr, &rId, nullptr, nullptr, &rImage, false); + } + int n_children() const { return m_xTreeView->n_children(); } + void select(int pos) { m_xTreeView->select(pos); } + std::unique_ptr<weld::TreeIter> make_iterator(const weld::TreeIter* pOrig = nullptr) const { return m_xTreeView->make_iterator(pOrig); } + bool get_iter_first(weld::TreeIter& rIter) const { return m_xTreeView->get_iter_first(rIter); } + // set iter to point to next node at the current level + bool iter_next_sibling(weld::TreeIter& rIter) const { return m_xTreeView->iter_next_sibling(rIter); } + // set iter to point to next node, depth first, then sibling + bool iter_next(weld::TreeIter& rIter) const { return m_xTreeView->iter_next(rIter); } + OUString get_text(const weld::TreeIter& rIter) const { return m_xTreeView->get_text(rIter); } + void scroll_to_row(const weld::TreeIter& rIter) { return m_xTreeView->scroll_to_row(rIter); } + void select(const weld::TreeIter& rIter) { m_xTreeView->select(rIter); } + + ~CuiConfigFunctionListBox(); + + void ClearAll(); + OUString GetCurCommand(); + OUString GetCurLabel(); + OUString GetSelectedScriptURI(); + OUString GetHelpText( bool bConsiderParent = true ); +}; + struct SvxConfigGroupBoxResource_Impl; class SfxConfigGroupListBox : public SvTreeListBox { @@ -178,6 +219,58 @@ public: void SetStylesInfo(SfxStylesInfo_Impl* pStyles); }; +struct CuiConfigGroupBoxResource_Impl; +class CuiConfigGroupListBox +{ + std::unique_ptr<CuiConfigGroupBoxResource_Impl> xImp; + CuiConfigFunctionListBox* m_pFunctionListBox; + SfxGroupInfoArr_Impl aArr; + OUString m_sModuleLongName; + css::uno::Reference< css::uno::XComponentContext > m_xContext; + css::uno::Reference< css::frame::XFrame > m_xFrame; + css::uno::Reference< css::container::XNameAccess > m_xGlobalCategoryInfo; + css::uno::Reference< css::container::XNameAccess > m_xModuleCategoryInfo; + css::uno::Reference< css::container::XNameAccess > m_xUICmdDescription; + SfxStylesInfo_Impl* m_pStylesInfo; + std::unique_ptr<weld::TreeView> m_xTreeView; + + OUString GetImage( + const css::uno::Reference< css::script::browse::XBrowseNode >& node, + css::uno::Reference< css::uno::XComponentContext > const & xCtx, + bool bIsRootNode); + + static css::uno::Reference< css::uno::XInterface > getDocumentModel( + css::uno::Reference< css::uno::XComponentContext > const & xCtx, + OUString const & docName); + + void InitModule(); + void FillScriptList(const css::uno::Reference< css::script::browse::XBrowseNode >& xRootNode, + weld::TreeIter* pParentEntry, bool bCheapChildrenOnDemand); + void FillFunctionsList(const css::uno::Sequence< css::frame::DispatchInformation >& xCommands); + OUString MapCommand2UIName(const OUString& sCommand); + + DECL_LINK(ExpandingHdl, weld::TreeIter&, bool); + DECL_LINK(OpenCurrentHdl, weld::TreeView&, void); + +public: + CuiConfigGroupListBox(std::unique_ptr<weld::TreeView> xTreeView); + void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); } + void connect_changed(const Link<weld::TreeView&, void>& rLink) { m_xTreeView->connect_changed(rLink); } + ~CuiConfigGroupListBox(); + void ClearAll(); + + void Init(const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XFrame >& xFrame, + const OUString& sModuleLongName, + bool bEventMode); + void SetFunctionListBox( CuiConfigFunctionListBox *pBox ) + { m_pFunctionListBox = pBox; } + void GroupSelected(); + void SelectMacro( const SfxMacroInfoItem* ); + void SelectMacro( const OUString&, const OUString& ); + void SetStylesInfo(SfxStylesInfo_Impl* pStyles); +}; + class SvxScriptSelectorDialog : public ModalDialog { VclPtr<FixedText> m_pDialogDescription; diff --git a/cui/source/inc/headertablistbox.hxx b/cui/source/inc/headertablistbox.hxx index 16bad69f85d3..390600c3e6dc 100644 --- a/cui/source/inc/headertablistbox.hxx +++ b/cui/source/inc/headertablistbox.hxx @@ -54,6 +54,22 @@ public: void Enable(); ///< same meaning as Windows::Enable() }; +class CuiMacroEventListBox final +{ +private: + std::unique_ptr<weld::TreeView> m_xTreeView; +public: + CuiMacroEventListBox(std::unique_ptr<weld::TreeView> xTreeView); + void set_sensitive(bool bSensitive) { m_xTreeView->set_sensitive(bSensitive); } + void show() { m_xTreeView->show(); } + ~CuiMacroEventListBox(); + + weld::TreeView& GetListBox() + { + return *m_xTreeView; + } +}; + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/cui/source/inc/macroass.hxx b/cui/source/inc/macroass.hxx index 3a37af149639..3a7231b374e7 100644 --- a/cui/source/inc/macroass.hxx +++ b/cui/source/inc/macroass.hxx @@ -36,13 +36,13 @@ class SfxMacroTabPage_Impl; class SfxMacroTabPage final : public SfxTabPage { SvxMacroTableDtor aTbl; - DECL_LINK( SelectEvent_Impl, SvTreeListBox*, void ); - DECL_LINK( SelectGroup_Impl, SvTreeListBox*, void ); - DECL_LINK( SelectMacro_Impl, SvTreeListBox*, void ); + DECL_LINK(SelectEvent_Impl, weld::TreeView&, void); + DECL_LINK(SelectGroup_Impl, weld::TreeView&, void); + DECL_LINK(SelectMacro_Impl, weld::TreeView&, void); - DECL_LINK( AssignDeleteHdl_Impl, SvTreeListBox*, bool ); - DECL_LINK( AssignDeleteClickHdl_Impl, Button *, void ); - void AssignDeleteHdl(Control const *); + DECL_LINK(AssignDeleteHdl_Impl, weld::TreeView&, void); + DECL_LINK(AssignDeleteClickHdl_Impl, weld::Button&, void); + void AssignDeleteHdl(const weld::Widget*); DECL_LINK( TimeOut_Impl, Timer*, void ); std::unique_ptr<SfxMacroTabPage_Impl> mpImpl; @@ -53,7 +53,7 @@ class SfxMacroTabPage final : public SfxTabPage public: SfxMacroTabPage( - vcl::Window* pParent, + TabPageParent pParent, const css::uno::Reference< css::frame::XFrame >& rxDocumentFrame, const SfxItemSet& rSet ); diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx index 343783b8ccef..e1a3f9060378 100644 --- a/cui/source/tabpages/macroass.cxx +++ b/cui/source/tabpages/macroass.cxx @@ -44,31 +44,22 @@ class SfxMacroTabPage_Impl public: SfxMacroTabPage_Impl(); - OUString maStaticMacroLBLabel; - VclPtr<PushButton> pAssignPB; - VclPtr<PushButton> pDeletePB; - OUString sStrEvent; - OUString sAssignedMacro; - VclPtr<MacroEventListBox> pEventLB; - VclPtr<VclFrame> pGroupFrame; - VclPtr<SfxConfigGroupListBox> pGroupLB; - VclPtr<VclFrame> pMacroFrame; - VclPtr<SfxConfigFunctionListBox> pMacroLB; - - Idle maFillGroupIdle; - bool bGotEvents; + OUString m_aStaticMacroLBLabel; + std::unique_ptr<weld::Button> m_xAssignPB; + std::unique_ptr<weld::Button> m_xDeletePB; + std::unique_ptr<CuiMacroEventListBox> m_xEventLB; + std::unique_ptr<weld::Widget> m_xGroupFrame; + std::unique_ptr<CuiConfigGroupListBox> m_xGroupLB; + std::unique_ptr<weld::Frame> m_xMacroFrame; + std::unique_ptr<CuiConfigFunctionListBox> m_xMacroLB; + + Idle m_aFillGroupIdle; + bool m_bGotEvents; bool m_bDummyActivated; ///< has this tab page already been activated }; SfxMacroTabPage_Impl::SfxMacroTabPage_Impl() - : pAssignPB(nullptr) - , pDeletePB(nullptr) - , pEventLB(nullptr) - , pGroupFrame(nullptr) - , pGroupLB(nullptr) - , pMacroFrame(nullptr) - , pMacroLB(nullptr) - , bGotEvents(false) + : m_bGotEvents(false) , m_bDummyActivated(false) { } @@ -78,19 +69,6 @@ static sal_uInt16 aPageRg[] = { 0 }; -// attention, this array is indexed directly (0, 1, ...) in the code -static long const nTabs[] = - { - 0, 90 - }; - -// IDs for items in HeaderBar of EventLB -#define ITEMID_EVENT 1 -#define ITMEID_ASSMACRO 2 - - -#define LB_MACROS_ITEMPOS 2 - static OUString ConvertToUIName_Impl( SvxMacro const *pMacro ) { OUString aName( pMacro->GetMacName() ); @@ -112,41 +90,40 @@ static OUString ConvertToUIName_Impl( SvxMacro const *pMacro ) void SfxMacroTabPage::EnableButtons() { // don't do anything as long as the eventbox is empty - const SvTreeListEntry* pE = mpImpl->pEventLB->GetListBox().FirstSelected(); - if ( pE ) + weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rTreeView.get_selected_index(); + if (nSelected != -1) { // get bound macro - const SvxMacro* pM = aTbl.Get( static_cast<SvMacroItemId>(reinterpret_cast<sal_uLong>(pE->GetUserData())) ); - mpImpl->pDeletePB->Enable( nullptr != pM ); + const SvxMacro* pM = aTbl.Get(static_cast<SvMacroItemId>(rTreeView.get_selected_id().toInt32())); + mpImpl->m_xDeletePB->set_sensitive(nullptr != pM); - OUString sEventMacro = static_cast<const SvLBoxString&>(pE->GetItem( LB_MACROS_ITEMPOS )).GetText(); + OUString sEventMacro = rTreeView.get_text(nSelected, 1); - OUString sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI(); - mpImpl->pAssignPB->Enable( !sScriptURI.equalsIgnoreAsciiCase( sEventMacro ) ); + OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); + mpImpl->m_xAssignPB->set_sensitive(!sScriptURI.equalsIgnoreAsciiCase(sEventMacro)); } else - mpImpl->pAssignPB->Enable( false ); + mpImpl->m_xAssignPB->set_sensitive(false); } -SfxMacroTabPage::SfxMacroTabPage(vcl::Window* pParent, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rAttrSet ) - : SfxTabPage(pParent, "EventAssignPage", "cui/ui/eventassignpage.ui", &rAttrSet) +SfxMacroTabPage::SfxMacroTabPage(TabPageParent pParent, const Reference< XFrame >& rxDocumentFrame, const SfxItemSet& rAttrSet ) + : SfxTabPage(pParent, "cui/ui/eventassignpage.ui", "EventAssignPage", &rAttrSet) { mpImpl.reset(new SfxMacroTabPage_Impl); - mpImpl->maFillGroupIdle.SetInvokeHandler( LINK( this, SfxMacroTabPage, TimeOut_Impl ) ); - mpImpl->maFillGroupIdle.SetPriority( TaskPriority::HIGHEST ); - mpImpl->maFillGroupIdle.SetDebugName( "SfxMacroTabPage maFillGroupIdle" ); - - mpImpl->sStrEvent = get<FixedText>("eventft")->GetText(); - mpImpl->sAssignedMacro = get<FixedText>("assignft")->GetText(); - get(mpImpl->pEventLB , "assignments"); - get(mpImpl->pAssignPB, "assign"); - get(mpImpl->pDeletePB, "delete"); - get(mpImpl->pGroupFrame, "groupframe"); - get(mpImpl->pGroupLB, "libraries"); - get(mpImpl->pMacroFrame, "macroframe"); - mpImpl->maStaticMacroLBLabel = mpImpl->pMacroFrame->get_label(); - get(mpImpl->pMacroLB, "macros"); + mpImpl->m_aFillGroupIdle.SetInvokeHandler( LINK( this, SfxMacroTabPage, TimeOut_Impl ) ); + mpImpl->m_aFillGroupIdle.SetPriority( TaskPriority::HIGHEST ); + mpImpl->m_aFillGroupIdle.SetDebugName( "SfxMacroTabPage m_aFillGroupIdle" ); + + mpImpl->m_xEventLB.reset(new CuiMacroEventListBox(m_xBuilder->weld_tree_view("assignments"))); + mpImpl->m_xAssignPB = m_xBuilder->weld_button("assign"); + mpImpl->m_xDeletePB = m_xBuilder->weld_button("delete"); + mpImpl->m_xGroupFrame = m_xBuilder->weld_widget("groupframe"); + mpImpl->m_xGroupLB.reset(new CuiConfigGroupListBox(m_xBuilder->weld_tree_view("libraries"))); + mpImpl->m_xMacroFrame = m_xBuilder->weld_frame("macroframe"); + mpImpl->m_aStaticMacroLBLabel = mpImpl->m_xMacroFrame->get_label(); + mpImpl->m_xMacroLB.reset(new CuiConfigFunctionListBox(m_xBuilder->weld_tree_view("macros"))); SetFrame( rxDocumentFrame ); @@ -166,27 +143,25 @@ void SfxMacroTabPage::dispose() SfxTabPage::dispose(); } -void SfxMacroTabPage::AddEvent( const OUString & rEventName, SvMacroItemId nEventId ) +void SfxMacroTabPage::AddEvent(const OUString& rEventName, SvMacroItemId nEventId) { - OUString sTmp = rEventName + "\t"; + weld::TreeView& rTreeView = mpImpl->m_xEventLB->GetListBox(); + rTreeView.append(OUString::number(static_cast<sal_Int32>(nEventId)), rEventName); // if the table is valid already - SvxMacro* pM = aTbl.Get( nEventId ); - if( pM ) + SvxMacro* pM = aTbl.Get(nEventId); + if (pM) { - OUString sNew( ConvertToUIName_Impl( pM ) ); - sTmp += sNew; + OUString sNew(ConvertToUIName_Impl(pM)); + rTreeView.set_text(rTreeView.n_children() - 1, sNew, 1); } - - SvTreeListEntry* pE = mpImpl->pEventLB->GetListBox().InsertEntry( sTmp ); - pE->SetUserData( reinterpret_cast< void* >( sal::static_int_cast< sal_IntPtr >( nEventId )) ); } void SfxMacroTabPage::ScriptChanged() { // get new areas and their functions - mpImpl->pGroupFrame->Show(); - mpImpl->pMacroFrame->Show(); + mpImpl->m_xGroupFrame->show(); + mpImpl->m_xMacroFrame->show(); EnableButtons(); } @@ -208,8 +183,8 @@ bool SfxMacroTabPage::FillItemSet( SfxItemSet* rSet ) void SfxMacroTabPage::LaunchFillGroup() { - if (! mpImpl->maFillGroupIdle.IsActive() ) - mpImpl->maFillGroupIdle.Start(); + if (! mpImpl->m_aFillGroupIdle.IsActive() ) + mpImpl->m_aFillGroupIdle.Start(); } void SfxMacroTabPage::ActivatePage( const SfxItemSet& ) @@ -227,9 +202,9 @@ void SfxMacroTabPage::ActivatePage( const SfxItemSet& ) void SfxMacroTabPage::PageCreated(const SfxAllItemSet& aSet) { const SfxPoolItem* pEventsItem; - if( !mpImpl->bGotEvents && SfxItemState::SET == aSet.GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) ) + if( !mpImpl->m_bGotEvents && SfxItemState::SET == aSet.GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) ) { - mpImpl->bGotEvents = true; + mpImpl->m_bGotEvents = true; const SfxEventNamesList& rList = static_cast<const SfxEventNamesItem*>(pEventsItem)->GetEvents(); for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo ) { @@ -246,9 +221,9 @@ void SfxMacroTabPage::Reset( const SfxItemSet* rSet ) aTbl = static_cast<const SvxMacroItem*>(pItem)->GetMacroTable(); const SfxPoolItem* pEventsItem; - if( !mpImpl->bGotEvents && SfxItemState::SET == rSet->GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) ) + if( !mpImpl->m_bGotEvents && SfxItemState::SET == rSet->GetItemState( SID_EVENTCONFIG, true, &pEventsItem ) ) { - mpImpl->bGotEvents = true; + mpImpl->m_bGotEvents = true; const SfxEventNamesList& rList = static_cast<const SfxEventNamesItem*>(pEventsItem)->GetEvents(); for ( size_t nNo = 0, nCnt = rList.size(); nNo < nCnt; ++nNo ) { @@ -259,10 +234,10 @@ void SfxMacroTabPage::Reset( const SfxItemSet* rSet ) FillEvents(); - SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox(); - SvTreeListEntry* pE = rListBox.GetEntry( 0 ); - if( pE ) - rListBox.SetCurEntry( pE ); + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + std::unique_ptr<weld::TreeIter> xIter(rListBox.make_iterator()); + if (rListBox.get_iter_first(*xIter)) + rListBox.set_cursor(*xIter); } bool SfxMacroTabPage::IsReadOnly() const @@ -270,13 +245,13 @@ bool SfxMacroTabPage::IsReadOnly() const return false; } -IMPL_LINK_NOARG( SfxMacroTabPage, SelectEvent_Impl, SvTreeListBox*, void) +IMPL_LINK_NOARG(SfxMacroTabPage, SelectEvent_Impl, weld::TreeView&, void) { - SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox(); - SvTreeListEntry* pE = rListBox.FirstSelected(); - if( !pE || LISTBOX_ENTRY_NOTFOUND == rListBox.GetModel()->GetAbsPos( pE ) ) + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rListBox.get_selected_index(); + if (nSelected == -1) { - DBG_ASSERT( pE, "Where does the empty entry come from?" ); + DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?"); return; } @@ -284,54 +259,53 @@ IMPL_LINK_NOARG( SfxMacroTabPage, SelectEvent_Impl, SvTreeListBox*, void) EnableButtons(); } -IMPL_LINK_NOARG( SfxMacroTabPage, SelectGroup_Impl, SvTreeListBox*, void) +IMPL_LINK_NOARG(SfxMacroTabPage, SelectGroup_Impl, weld::TreeView&, void) { - mpImpl->pGroupLB->GroupSelected(); - const OUString sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI(); + mpImpl->m_xGroupLB->GroupSelected(); + const OUString sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); OUString aLabelText; if( !sScriptURI.isEmpty() ) - aLabelText = mpImpl->maStaticMacroLBLabel; - mpImpl->pMacroFrame->set_label( aLabelText ); + aLabelText = mpImpl->m_aStaticMacroLBLabel; + mpImpl->m_xMacroFrame->set_label( aLabelText ); EnableButtons(); } -IMPL_LINK_NOARG( SfxMacroTabPage, SelectMacro_Impl, SvTreeListBox*, void) +IMPL_LINK_NOARG(SfxMacroTabPage, SelectMacro_Impl, weld::TreeView&, void) { EnableButtons(); } -IMPL_LINK( SfxMacroTabPage, AssignDeleteClickHdl_Impl, Button*, pBtn, void ) +IMPL_LINK(SfxMacroTabPage, AssignDeleteClickHdl_Impl, weld::Button&, rBtn, void) { - AssignDeleteHdl(pBtn); + AssignDeleteHdl(&rBtn); } -IMPL_LINK( SfxMacroTabPage, AssignDeleteHdl_Impl, SvTreeListBox*, pBtn, bool ) +IMPL_LINK(SfxMacroTabPage, AssignDeleteHdl_Impl, weld::TreeView&, rBtn, void) { - AssignDeleteHdl(pBtn); - return false; + AssignDeleteHdl(&rBtn); } -void SfxMacroTabPage::AssignDeleteHdl(Control const * pBtn) +void SfxMacroTabPage::AssignDeleteHdl(const weld::Widget* pBtn) { - SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox(); - SvTreeListEntry* pE = rListBox.FirstSelected(); - if( !pE || LISTBOX_ENTRY_NOTFOUND == rListBox.GetModel()->GetAbsPos( pE ) ) + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + int nSelected = rListBox.get_selected_index(); + if (nSelected == -1) { - DBG_ASSERT( pE, "Where does the empty entry come from?" ); + DBG_ASSERT(nSelected != -1, "Where does the empty entry come from?"); return; } - const bool bAssEnabled = pBtn != mpImpl->pDeletePB && mpImpl->pAssignPB->IsEnabled(); + const bool bAssEnabled = pBtn != mpImpl->m_xDeletePB.get() && mpImpl->m_xAssignPB->get_sensitive(); // remove from the table - SvMacroItemId nEvent = static_cast<SvMacroItemId>(reinterpret_cast<sal_uLong>(pE->GetUserData())); + SvMacroItemId nEvent = static_cast<SvMacroItemId>(rListBox.get_selected_id().toInt32()); aTbl.Erase( nEvent ); OUString sScriptURI; if( bAssEnabled ) { - sScriptURI = mpImpl->pMacroLB->GetSelectedScriptURI(); + sScriptURI = mpImpl->m_xMacroLB->GetSelectedScriptURI(); if( sScriptURI.startsWith( "vnd.sun.star.script:" ) ) { aTbl.Insert( @@ -345,12 +319,7 @@ void SfxMacroTabPage::AssignDeleteHdl(Control const * pBtn) } } - mpImpl->pEventLB->SetUpdateMode( false ); - pE->ReplaceItem(o3tl::make_unique<SvLBoxString>(sScriptURI), LB_MACROS_ITEMPOS); - rListBox.GetModel()->InvalidateEntry( pE ); - rListBox.Select( pE ); - rListBox.MakeVisible( pE ); - rListBox.SetUpdateMode( true ); + rListBox.set_text(nSelected, sScriptURI, 1); EnableButtons(); } @@ -366,7 +335,7 @@ IMPL_LINK( SfxMacroTabPage, TimeOut_Impl, Timer*,, void ) pTabDlg->EnableInput( false ); } // fill macro list - mpImpl->pGroupLB->Init( + mpImpl->m_xGroupLB->Init( comphelper::getProcessComponentContext(), GetFrame(), OUString(), false); @@ -379,64 +348,49 @@ IMPL_LINK( SfxMacroTabPage, TimeOut_Impl, Timer*,, void ) void SfxMacroTabPage::InitAndSetHandler() { - SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox(); - HeaderBar& rHeaderBar = mpImpl->pEventLB->GetHeaderBar(); - Link<SvTreeListBox*,bool> aLnk(LINK(this, SfxMacroTabPage, AssignDeleteHdl_Impl )); - mpImpl->pMacroLB->SetDoubleClickHdl( aLnk ); - mpImpl->pDeletePB->SetClickHdl( LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl ) ); - mpImpl->pAssignPB->SetClickHdl( LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl ) ); - rListBox.SetDoubleClickHdl( aLnk ); - - rListBox.SetSelectHdl( LINK( this, SfxMacroTabPage, SelectEvent_Impl )); - mpImpl->pGroupLB->SetSelectHdl( LINK( this, SfxMacroTabPage, SelectGroup_Impl )); - mpImpl->pMacroLB->SetSelectHdl( LINK( this, SfxMacroTabPage, SelectMacro_Impl )); - - rListBox.SetSelectionMode( SelectionMode::Single ); - rListBox.SetTabs( SAL_N_ELEMENTS(nTabs), nTabs ); - Size aSize( nTabs[ 1 ], 0 ); - rHeaderBar.InsertItem( ITEMID_EVENT, mpImpl->sStrEvent, LogicToPixel( aSize, MapMode( MapUnit::MapAppFont ) ).Width() ); - aSize.setWidth( 1764 ); // don't know what, so 42^2 is best to use... - rHeaderBar.InsertItem( ITMEID_ASSMACRO, mpImpl->sAssignedMacro, LogicToPixel( aSize, MapMode( MapUnit::MapAppFont ) ).Width() ); - rListBox.SetSpaceBetweenEntries( 0 ); - - mpImpl->pEventLB->Show(); - mpImpl->pEventLB->ConnectElements(); - - mpImpl->pEventLB->Enable(); - mpImpl->pGroupLB->Enable(); - mpImpl->pMacroLB->Enable(); - - mpImpl->pGroupLB->SetFunctionListBox( mpImpl->pMacroLB ); + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); + Link<weld::TreeView&,void> aLnk(LINK(this, SfxMacroTabPage, AssignDeleteHdl_Impl)); + mpImpl->m_xMacroLB->connect_row_activated( aLnk); + mpImpl->m_xDeletePB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl)); + mpImpl->m_xAssignPB->connect_clicked(LINK(this, SfxMacroTabPage, AssignDeleteClickHdl_Impl)); + rListBox.connect_row_activated(aLnk); + rListBox.connect_changed(LINK(this, SfxMacroTabPage, SelectEvent_Impl)); + mpImpl->m_xGroupLB->connect_changed(LINK(this, SfxMacroTabPage, SelectGroup_Impl)); + mpImpl->m_xMacroLB->connect_changed(LINK(this, SfxMacroTabPage, SelectMacro_Impl)); + + std::vector<int> aWidths; + aWidths.push_back(rListBox.get_approximate_digit_width() * 35); + rListBox.set_column_fixed_widths(aWidths); + + mpImpl->m_xEventLB->show(); + + mpImpl->m_xEventLB->set_sensitive(true); + mpImpl->m_xGroupLB->set_sensitive(true); + mpImpl->m_xMacroLB->set_sensitive(true); + + mpImpl->m_xGroupLB->SetFunctionListBox(mpImpl->m_xMacroLB.get()); } void SfxMacroTabPage::FillEvents() { - SvHeaderTabListBox& rListBox = mpImpl->pEventLB->GetListBox(); + weld::TreeView& rListBox = mpImpl->m_xEventLB->GetListBox(); - sal_uLong nEntryCnt = rListBox.GetEntryCount(); + int nEntryCnt = rListBox.n_children(); // get events from the table and fill the EventListBox respectively - for( sal_uLong n = 0 ; n < nEntryCnt ; ++n ) + for (int n = 0 ; n < nEntryCnt; ++n) { - SvTreeListEntry* pE = rListBox.GetEntry( n ); - if( pE ) - { - SvLBoxString& rLItem = static_cast<SvLBoxString&>( pE->GetItem( LB_MACROS_ITEMPOS ) ); - DBG_ASSERT( SvLBoxItemType::String == rLItem.GetType(), "SfxMacroTabPage::FillEvents(): no LBoxString" ); - - const OUString& sOld( rLItem.GetText() ); - OUString sNew; - SvMacroItemId nEventId = static_cast<SvMacroItemId>(reinterpret_cast<sal_uLong>( pE->GetUserData() )); - if( aTbl.IsKeyValid( nEventId ) ) - sNew = ConvertToUIName_Impl( aTbl.Get( nEventId ) ); - - if( sOld != sNew ) - { - pE->ReplaceItem(o3tl::make_unique<SvLBoxString>(sNew), LB_MACROS_ITEMPOS); - rListBox.GetModel()->InvalidateEntry( pE ); - } - } + OUString sOld = rListBox.get_text(n, 1); + OUString sNew; + SvMacroItemId nEventId = static_cast<SvMacroItemId>(rListBox.get_id(n).toInt32()); + if (aTbl.IsKeyValid(nEventId)) + sNew = ConvertToUIName_Impl(aTbl.Get(nEventId)); + + if (sOld == sNew) + continue; + + rListBox.set_text(n, sNew, 1); } } diff --git a/cui/uiconfig/ui/eventassignpage.ui b/cui/uiconfig/ui/eventassignpage.ui index 48dbbc0bf1b1..3eb926ed88d6 100644 --- a/cui/uiconfig/ui/eventassignpage.ui +++ b/cui/uiconfig/ui/eventassignpage.ui @@ -1,8 +1,35 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.16.1 --> +<!-- Generated with glade 3.22.1 --> <interface domain="cui"> <requires lib="gtk+" version="3.18"/> - <requires lib="LibreOffice" version="1.0"/> + <object class="GtkTreeStore" id="liststore1"> + <columns> + <!-- column-name expander --> + <column type="GdkPixbuf"/> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkTreeStore" id="liststore2"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> + <object class="GtkTreeStore" id="liststore3"> + <columns> + <!-- column-name text --> + <column type="gchararray"/> + <!-- column-name text2 --> + <column type="gchararray"/> + <!-- column-name id --> + <column type="gchararray"/> + </columns> + </object> <object class="GtkGrid" id="EventAssignPage"> <property name="visible">True</property> <property name="can_focus">False</property> @@ -27,14 +54,37 @@ <property name="top_padding">6</property> <property name="left_padding">12</property> <child> - <object class="cuilo-SfxConfigFunctionListBox" id="macros:border"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="Tree List-selection"/> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="macros"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore2</property> + <property name="headers_visible">False</property> + <property name="search_column">0</property> + <property name="show_expanders">False</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="Tree List-selection1"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn1"> + <child> + <object class="GtkCellRendererText" id="cellrenderertext1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> + </object> + </child> + </object> </child> </object> </child> @@ -55,8 +105,6 @@ <packing> <property name="left_attach">1</property> <property name="top_attach">1</property> - <property name="width">1</property> - <property name="height">1</property> </packing> </child> <child> @@ -76,14 +124,46 @@ <property name="top_padding">6</property> <property name="left_padding">12</property> <child> - <object class="cuilo-SfxConfigGroupListBox" id="libraries:border"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="receives_default">True</property> <property name="hexpand">True</property> <property name="vexpand">True</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="Macro Library List-selection"/> + <property name="shadow_type">in</property> + <child> + <object class="GtkTreeView" id="libraries"> + <property name="width_request">-1</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> + <property name="model">liststore1</property> + <property name="headers_visible">False</property> + <property name="search_column">1</property> + <property name="show_expanders">True</property> + <property name="enable_tree_lines">True</property> + <child internal-child="selection"> + <object class="GtkTreeSelection" id="Macro Library List-selection1"/> + </child> + <child> + <object class="GtkTreeViewColumn" id="treeviewcolumn2"> + <property name="spacing">6</property> + <child> + <object class="GtkCellRendererPixbuf" id="cellrenderertext4"/> + <attributes> + <attribute name="pixbuf">0</attribute> + </attributes> + </child> + <child> + <object class="GtkCellRendererText" id="cellrenderertext2"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> + </object> + </child> + </object> </child> </object> </child> @@ -93,8 +173,8 @@ <object class="GtkLabel" id="macrotoft"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="xalign">0</property> <property name="label" translatable="yes" context="eventassignpage|macrotoft">Macro From</property> + <property name="xalign">0</property> <attributes> <attribute name="weight" value="bold"/> </attributes> @@ -104,8 +184,6 @@ <packing> <property name="left_attach">0</property> <property name="top_attach">1</property> - <property name="width">1</property> - <property name="height">1</property> </packing> </child> <child> @@ -125,66 +203,52 @@ <property name="top_padding">6</property> <property name="left_padding">12</property> <child> - <object class="GtkGrid" id="grid1"> + <object class="GtkScrolledWindow"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can_focus">True</property> <property name="hexpand">True</property> <property name="vexpand">True</property> + <property name="shadow_type">in</property> <child> - <object class="cuilo-MacroEventListBox" id="assignments:border"> + <object class="GtkTreeView" id="assignments"> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> <property name="hexpand">True</property> <property name="vexpand">True</property> + <property name="model">liststore3</property> + <property name="search_column">0</property> + <property name="show_expanders">False</property> <child internal-child="selection"> - <object class="GtkTreeSelection" id="Macro EventListBox-selection1"/> + <object class="GtkTreeSelection" id="Macro Library List-selection2"/> </child> - </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">1</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> - </child> - <child> - <object class="GtkGrid" id="grid2"> - <property name="can_focus">False</property> - <property name="no_show_all">True</property> - <property name="column_homogeneous">True</property> <child> - <object class="GtkLabel" id="eventft"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes" context="eventassignpage|eventft">Event</property> + <object class="GtkTreeViewColumn" id="treeviewcolumn3"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="eventassignpage|eventft">Event</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer1"/> + <attributes> + <attribute name="text">0</attribute> + </attributes> + </child> </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> </child> <child> - <object class="GtkLabel" id="assignft"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes" context="eventassignpage|assignft">Assigned Action</property> + <object class="GtkTreeViewColumn" id="treeviewcolumn4"> + <property name="resizable">True</property> + <property name="spacing">6</property> + <property name="title" translatable="yes" context="eventassignpage|assignft">Assigned Action</property> + <child> + <object class="GtkCellRendererText" id="cellrenderer2"/> + <attributes> + <attribute name="text">1</attribute> + </attributes> + </child> </object> - <packing> - <property name="left_attach">1</property> - <property name="top_attach">0</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> </child> </object> - <packing> - <property name="left_attach">0</property> - <property name="top_attach">0</property> - <property name="width">1</property> - <property name="height">1</property> - </packing> </child> </object> </child> @@ -205,7 +269,6 @@ <property name="left_attach">0</property> <property name="top_attach">0</property> <property name="width">2</property> - <property name="height">1</property> </packing> </child> <child> @@ -219,6 +282,7 @@ <object class="GtkButton" id="assign"> <property name="label" translatable="yes" context="eventassignpage|assign">Assign</property> <property name="visible">True</property> + <property name="sensitive">False</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_underline">True</property> @@ -247,7 +311,6 @@ <packing> <property name="left_attach">2</property> <property name="top_attach">0</property> - <property name="width">1</property> <property name="height">2</property> </packing> </child> @@ -261,9 +324,9 @@ <object class="GtkSizeGroup" id="sizegroup2"> <property name="mode">vertical</property> <widgets> - <widget name="macros:border"/> - <widget name="libraries:border"/> - <widget name="assignments:border"/> + <widget name="macros"/> + <widget name="libraries"/> + <widget name="assignments"/> </widgets> </object> </interface> diff --git a/include/sfx2/sfxhelp.hxx b/include/sfx2/sfxhelp.hxx index bdfaaf867143..99ca1a062f04 100644 --- a/include/sfx2/sfxhelp.hxx +++ b/include/sfx2/sfxhelp.hxx @@ -45,7 +45,8 @@ public: SfxHelp(); virtual ~SfxHelp() override; - virtual OUString GetHelpText( const OUString&, const vcl::Window* pWindow ) override; + virtual OUString GetHelpText(const OUString&, const vcl::Window* pWindow) override; + virtual OUString GetHelpText(const OUString&, const weld::Widget* pWindow) override; static OUString CreateHelpURL( const OUString& aCommandURL, const OUString& rModuleName ); static OUString GetDefaultHelpModule(); diff --git a/include/vcl/builder.hxx b/include/vcl/builder.hxx index a1a47b9f7047..5fdb061f7b1e 100644 --- a/include/vcl/builder.hxx +++ b/include/vcl/builder.hxx @@ -38,7 +38,7 @@ class PopupMenu; class SalInstanceBuilder; class ScreenshotTest; class ScrollBar; -class SvHeaderTabListBox; +class SvTabListBox; class Slider; class DateField; class TimeField; @@ -220,7 +220,7 @@ private: const ListStore* get_model_by_name(const OString& sID) const; void mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId); void mungeModel(ComboBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId); - void mungeModel(SvHeaderTabListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId); + void mungeModel(SvTabListBox &rTarget, const ListStore &rStore, sal_uInt16 nActiveId); typedef stringmap TextBuffer; const TextBuffer* get_buffer_by_name(const OString& sID) const; diff --git a/include/vcl/help.hxx b/include/vcl/help.hxx index 80353b263c09..2c467974fdc5 100644 --- a/include/vcl/help.hxx +++ b/include/vcl/help.hxx @@ -69,7 +69,8 @@ public: virtual bool Start(const OUString& rHelpId, const vcl::Window* pWindow); virtual bool Start(const OUString& rHelpId, weld::Widget* pWidget); virtual void SearchKeyword( const OUString& rKeyWord ); - virtual OUString GetHelpText( const OUString& aHelpURL, const vcl::Window* pWindow ); + virtual OUString GetHelpText(const OUString& aHelpURL, const vcl::Window* pWindow); + virtual OUString GetHelpText(const OUString& aHelpURL, const weld::Widget* pWidget); static void EnableContextHelp(); static void DisableContextHelp(); diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index f05e3408e207..1b9726ac556e 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -382,6 +382,7 @@ class VCL_DLLPUBLIC TreeView : virtual public Container protected: Link<TreeView&, void> m_aChangeHdl; Link<TreeView&, void> m_aRowActivatedHdl; + // if handler returns false, the expansion of the row is refused Link<TreeIter&, bool> m_aExpandingHdl; void signal_changed() { m_aChangeHdl.Call(*this); } @@ -438,6 +439,7 @@ public: virtual void set_top_entry(int pos) = 0; virtual std::vector<int> get_selected_rows() const = 0; virtual void set_font_color(int pos, const Color& rColor) const = 0; + virtual void scroll_to_row(int pos) = 0; //by text virtual OUString get_text(int row, int col = -1) const = 0; @@ -488,6 +490,7 @@ public: virtual void expand_row(TreeIter& rIter) = 0; virtual OUString get_text(const TreeIter& rIter) const = 0; virtual OUString get_id(const TreeIter& rIter) const = 0; + virtual void scroll_to_row(const TreeIter& rIter) = 0; void connect_expanding(const Link<TreeIter&, bool>& rLink) { m_aExpandingHdl = rLink; } diff --git a/sfx2/source/appl/sfxhelp.cxx b/sfx2/source/appl/sfxhelp.cxx index 30aa68b840f4..4a8929af5a31 100644 --- a/sfx2/source/appl/sfxhelp.cxx +++ b/sfx2/source/appl/sfxhelp.cxx @@ -620,6 +620,49 @@ OUString SfxHelp::GetHelpText( const OUString& aCommandURL, const vcl::Window* p return sHelpText; } +OUString SfxHelp::GetHelpText(const OUString& aCommandURL, const weld::Widget* pWidget) +{ + OUString sModuleName = GetHelpModuleName_Impl(aCommandURL); + OUString sRealCommand = vcl::CommandInfoProvider::GetRealCommandForCommand( aCommandURL, getCurrentModuleIdentifier_Impl() ); + OUString sHelpText = SfxHelp_Impl::GetHelpText( sRealCommand.isEmpty() ? aCommandURL : sRealCommand, sModuleName ); + + OString aNewHelpId; + + if (pWidget && sHelpText.isEmpty()) + { + // no help text found -> try with parent help id. + std::unique_ptr<weld::Widget> xParent(pWidget->weld_parent()); + while (xParent) + { + aNewHelpId = xParent->get_help_id(); + sHelpText = SfxHelp_Impl::GetHelpText( OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8), sModuleName ); + if (!sHelpText.isEmpty()) + xParent.reset(); + else + xParent.reset(xParent->weld_parent()); + } + + if (bIsDebug && sHelpText.isEmpty()) + aNewHelpId.clear(); + } + + // add some debug information? + if ( bIsDebug ) + { + sHelpText += "\n-------------\n"; + sHelpText += sModuleName; + sHelpText += ": "; + sHelpText += aCommandURL; + if ( !aNewHelpId.isEmpty() ) + { + sHelpText += " - "; + sHelpText += OStringToOUString(aNewHelpId, RTL_TEXTENCODING_UTF8); + } + } + + return sHelpText; +} + void SfxHelp::SearchKeyword( const OUString& rKeyword ) { Start_Impl(OUString(), static_cast<vcl::Window*>(nullptr), rKeyword); diff --git a/sfx2/source/dialog/filedlghelper.cxx b/sfx2/source/dialog/filedlghelper.cxx index d0e885c506fa..0e5a3610ee3e 100644 --- a/sfx2/source/dialog/filedlghelper.cxx +++ b/sfx2/source/dialog/filedlghelper.cxx @@ -276,7 +276,7 @@ OUString FileDialogHelper_Impl::handleHelpRequested( const FilePickerEvent& aEve OUString aHelpText; Help* pHelp = Application::GetHelp(); if ( pHelp ) - aHelpText = pHelp->GetHelpText( OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), nullptr ); + aHelpText = pHelp->GetHelpText(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), static_cast<weld::Widget*>(nullptr)); return aHelpText; } diff --git a/vcl/source/app/help.cxx b/vcl/source/app/help.cxx index b7143be84d20..ab6767b39adb 100644 --- a/vcl/source/app/help.cxx +++ b/vcl/source/app/help.cxx @@ -73,6 +73,11 @@ OUString Help::GetHelpText( const OUString&, const vcl::Window* ) return OUString(); } +OUString Help::GetHelpText( const OUString&, const weld::Widget* ) +{ + return OUString(); +} + void Help::EnableContextHelp() { ImplGetSVData()->maHelpData.mbContextHelp = true; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index c04ca82d1a37..259622b38399 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -1765,7 +1765,7 @@ class SalInstanceTreeView : public SalInstanceContainer, public virtual weld::Tr private: // owner for UserData std::vector<std::unique_ptr<OUString>> m_aUserData; - VclPtr<SvHeaderTabListBox> m_xTreeView; + VclPtr<SvTabListBox> m_xTreeView; DECL_LINK(SelectHdl, SvTreeListBox*, void); DECL_LINK(DoubleClickHdl, SvTreeListBox*, bool); @@ -1773,7 +1773,7 @@ private: DECL_LINK(EndDragHdl, HeaderBar*, void); public: - SalInstanceTreeView(SvHeaderTabListBox* pTreeView, bool bTakeOwnership) + SalInstanceTreeView(SvTabListBox* pTreeView, bool bTakeOwnership) : SalInstanceContainer(pTreeView, bTakeOwnership) , m_xTreeView(pTreeView) { @@ -1783,7 +1783,8 @@ public: m_xTreeView->SetExpandingHdl(LINK(this, SalInstanceTreeView, ExpandingHdl)); const long aTabPositions[] = { 0 }; m_xTreeView->SetTabs(SAL_N_ELEMENTS(aTabPositions), aTabPositions); - if (HeaderBar* pHeaderBar = m_xTreeView->GetHeaderBar()) + SvHeaderTabListBox* pHeaderBox = dynamic_cast<SvHeaderTabListBox*>(m_xTreeView.get()); + if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr) { //make the last entry fill available space pHeaderBar->SetItemSize(pHeaderBar->GetItemId(pHeaderBar->GetItemCount() - 1 ), HEADERBAR_FULLSIZE); @@ -1797,7 +1798,8 @@ public: aTabPositions.push_back(0); aTabPositions.insert(aTabPositions.end(), rWidths.begin(), rWidths.end()); m_xTreeView->SetTabs(aTabPositions.size(), aTabPositions.data(), MapUnit::MapPixel); - if (HeaderBar* pHeaderBar = m_xTreeView->GetHeaderBar()) + SvHeaderTabListBox* pHeaderBox = dynamic_cast<SvHeaderTabListBox*>(m_xTreeView.get()); + if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr) { for (size_t i = 0; i < rWidths.size(); ++i) pHeaderBar->SetItemSize(pHeaderBar->GetItemId(i), rWidths[i]); @@ -1914,6 +1916,14 @@ public: enable_notify_events(); } + virtual void scroll_to_row(int pos) override + { + disable_notify_events(); + SvTreeListEntry* pEntry = m_xTreeView->GetEntry(nullptr, pos); + m_xTreeView->MakeVisible(pEntry); + enable_notify_events(); + } + virtual void unselect(int pos) override { assert(m_xTreeView->IsUpdateMode() && "don't select when frozen"); @@ -1945,6 +1955,8 @@ public: if (col == -1) return SvTabListBox::GetEntryText(pEntry, 0); + ++col; //skip dummy/expander column + if (static_cast<size_t>(col) == pEntry->ItemCount()) return OUString(); @@ -2095,6 +2107,14 @@ public: enable_notify_events(); } + virtual void scroll_to_row(const weld::TreeIter& rIter) override + { + disable_notify_events(); + const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); + m_xTreeView->MakeVisible(rVclIter.iter); + enable_notify_events(); + } + virtual void unselect(const weld::TreeIter& rIter) override { assert(m_xTreeView->IsUpdateMode() && "don't unselect when frozen"); @@ -2112,8 +2132,12 @@ public: virtual bool iter_has_child(const weld::TreeIter& rIter) const override { - const SalInstanceTreeIter& rVclIter = static_cast<const SalInstanceTreeIter&>(rIter); - return rVclIter.iter->HasChildren(); + weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter); + SalInstanceTreeIter& rVclIter = static_cast<SalInstanceTreeIter&>(rNonConstIter); + SvTreeListEntry* restore(rVclIter.iter); + bool ret = iter_children(rNonConstIter); + rVclIter.iter = restore; + return ret; } virtual bool get_row_expanded(const weld::TreeIter& rIter) const override @@ -2172,14 +2196,15 @@ public: m_xTreeView->SetStyle(m_xTreeView->GetStyle() | WB_SORT); } - SvHeaderTabListBox& getTreeView() + SvTabListBox& getTreeView() { return *m_xTreeView; } virtual ~SalInstanceTreeView() override { - if (HeaderBar* pHeaderBar = m_xTreeView->GetHeaderBar()) + SvHeaderTabListBox* pHeaderBox = dynamic_cast<SvHeaderTabListBox*>(m_xTreeView.get()); + if (HeaderBar* pHeaderBar = pHeaderBox ? pHeaderBox->GetHeaderBar() : nullptr) { pHeaderBar->SetEndDragHdl(Link<HeaderBar*, void>()); } @@ -3318,7 +3343,7 @@ public: virtual std::unique_ptr<weld::TreeView> weld_tree_view(const OString &id, bool bTakeOwnership) override { - SvHeaderTabListBox* pTreeView = m_xBuilder->get<SvHeaderTabListBox>(id); + SvTabListBox* pTreeView = m_xBuilder->get<SvTabListBox>(id); return pTreeView ? o3tl::make_unique<SalInstanceTreeView>(pTreeView, bTakeOwnership) : nullptr; } diff --git a/vcl/source/treelist/treelistbox.cxx b/vcl/source/treelist/treelistbox.cxx index c1269b26c174..dbf1af9566b0 100644 --- a/vcl/source/treelist/treelistbox.cxx +++ b/vcl/source/treelist/treelistbox.cxx @@ -3679,6 +3679,10 @@ bool SvTreeListBox::set_property(const OString &rKey, const OUString &rValue) nStyle |= (WB_HASBUTTONS | WB_HASBUTTONSATROOT); SetStyle(nStyle); } + else if (rKey == "enable-search") + { + SetQuickSearch(toBool(rValue)); + } else return Control::set_property(rKey, rValue); return true; diff --git a/vcl/source/window/builder.cxx b/vcl/source/window/builder.cxx index 25e7e36e5c03..ee257ada29fb 100644 --- a/vcl/source/window/builder.cxx +++ b/vcl/source/window/builder.cxx @@ -519,7 +519,7 @@ VclBuilder::VclBuilder(vcl::Window *pParent, const OUString& sUIDir, const OUStr vcl::Window* pTarget = get<vcl::Window>(elem.m_sID); ListBox *pListBoxTarget = dynamic_cast<ListBox*>(pTarget); ComboBox *pComboBoxTarget = dynamic_cast<ComboBox*>(pTarget); - SvHeaderTabListBox *pTreeBoxTarget = dynamic_cast<SvHeaderTabListBox*>(pTarget); + SvTabListBox *pTreeBoxTarget = dynamic_cast<SvTabListBox*>(pTarget); // pStore may be empty const ListStore *pStore = get_model_by_name(elem.m_sValue.toUtf8()); SAL_WARN_IF(!pListBoxTarget && !pComboBoxTarget && !pTreeBoxTarget, "vcl", "missing elements of combobox"); @@ -1899,9 +1899,9 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString & //window we want to apply the packing props for this GtkTreeView to VclPtr<vcl::Window> xWindowForPackingProps; //To-Do - //a) make SvHeaderTabListBox the default target for GtkTreeView + //a) make SvHeaderTabListBox/SvTabListBox the default target for GtkTreeView //b) remove the non-drop down mode of ListBox and convert - // everything over to SvHeaderTabListBox + // everything over to SvHeaderTabListBox/SvTabListBox //c) remove the users of makeSvTabListBox and makeSvTreeListBox extractModel(id, rMap); WinBits nWinStyle = WB_CLIPCHILDREN|WB_LEFT|WB_VCENTER|WB_3DLOOK|WB_SIMPLEMODE; @@ -1922,7 +1922,7 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString & } else { - VclPtr<SvHeaderTabListBox> xBox; + VclPtr<SvTabListBox> xBox; bool bHeadersVisible = extractHeadersVisible(rMap); if (bHeadersVisible) { @@ -1932,24 +1932,27 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString & m_aChildren.emplace_back(containerid, xContainer, true); VclPtrInstance<HeaderBar> xHeader(xContainer, WB_BUTTONSTYLE | WB_BORDER | WB_TABSTOP | WB_3DLOOK); + xHeader->set_width_request(0); // let the headerbar width not affect the size requistion OString headerid(id + "-header"); xHeader->SetHelpId(m_sHelpRoot + headerid); m_aChildren.emplace_back(headerid, xHeader, true); - xBox = VclPtr<SvHeaderTabListBox>::Create(xContainer, nWinStyle); - xBox->InitHeaderBar(xHeader); + VclPtr<SvHeaderTabListBox> xHeaderBox = VclPtr<SvHeaderTabListBox>::Create(xContainer, nWinStyle); + xHeaderBox->InitHeaderBar(xHeader); xContainer->set_expand(true); xHeader->Show(); xContainer->Show(); + xBox = xHeaderBox; xWindowForPackingProps = xContainer; } else { - xBox = VclPtr<SvHeaderTabListBox>::Create(pRealParent, nWinStyle); + xBox = VclPtr<SvTabListBox>::Create(pRealParent, nWinStyle); xWindowForPackingProps = xBox; } xWindow = xBox; xBox->SetNoAutoCurEntry(true); + xBox->SetQuickSearch(true); xBox->SetHighlightRange(); // select over the whole width } if (pRealParent != pParent) @@ -1959,8 +1962,8 @@ VclPtr<vcl::Window> VclBuilder::makeObject(vcl::Window *pParent, const OString & { if (!m_bLegacy) { - SvHeaderTabListBox* pTreeView = static_cast<SvHeaderTabListBox*>(pParent); - if (HeaderBar* pHeaderBar = pTreeView->GetHeaderBar()) + SvHeaderTabListBox* pTreeView = dynamic_cast<SvHeaderTabListBox*>(pParent); + if (HeaderBar* pHeaderBar = pTreeView ? pTreeView->GetHeaderBar() : nullptr) { OUString sTitle(extractTitle(rMap)); auto nItemId = pHeaderBar->GetItemCount() + 1; @@ -4149,7 +4152,7 @@ void VclBuilder::mungeModel(ListBox &rTarget, const ListStore &rStore, sal_uInt1 rTarget.SelectEntryPos(nActiveId); } -void VclBuilder::mungeModel(SvHeaderTabListBox& rTarget, const ListStore &rStore, sal_uInt16 nActiveId) +void VclBuilder::mungeModel(SvTabListBox& rTarget, const ListStore &rStore, sal_uInt16 nActiveId) { for (auto const& entry : rStore.m_aEntries) { diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx index ebeb2a970e69..b9833ae4a503 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -1099,9 +1099,9 @@ OUString Menu::ImplGetHelpText( sal_uInt16 nItemId ) const if ( pHelp ) { if (!pData->aCommandStr.isEmpty()) - pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, nullptr ); + pData->aHelpText = pHelp->GetHelpText( pData->aCommandStr, static_cast<weld::Widget*>(nullptr) ); if (pData->aHelpText.isEmpty() && !pData->aHelpId.isEmpty()) - pData->aHelpText = pHelp->GetHelpText( OStringToOUString( pData->aHelpId, RTL_TEXTENCODING_UTF8 ), nullptr ); + pData->aHelpText = pHelp->GetHelpText( OStringToOUString( pData->aHelpId, RTL_TEXTENCODING_UTF8 ), static_cast<weld::Widget*>(nullptr) ); } } diff --git a/vcl/unx/gtk/salprn-gtk.cxx b/vcl/unx/gtk/salprn-gtk.cxx index 235d3ccb005b..eab182ecb4c5 100644 --- a/vcl/unx/gtk/salprn-gtk.cxx +++ b/vcl/unx/gtk/salprn-gtk.cxx @@ -473,7 +473,7 @@ GtkPrintDialog::impl_initCustomTab() const int nLen = aHelpIds.getLength(); aHelpTexts.realloc(nLen); for (int j = 0; j != nLen; ++j) - aHelpTexts[j] = pHelp->GetHelpText(aHelpIds[j], nullptr); + aHelpTexts[j] = pHelp->GetHelpText(aHelpIds[j], static_cast<weld::Widget*>(nullptr)); } else // fallback aHelpTexts = aHelpIds; diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index c35088723a29..1fefb9db0169 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -4386,6 +4386,15 @@ public: enable_notify_events(); } + virtual void scroll_to_row(int pos) override + { + disable_notify_events(); + GtkTreePath* path = gtk_tree_path_new_from_indices(pos, -1); + gtk_tree_view_scroll_to_cell(m_pTreeView, path, nullptr, false, 0, 0); + gtk_tree_path_free(path); + enable_notify_events(); + } + virtual void unselect(int pos) override { assert(gtk_tree_view_get_model(m_pTreeView) && "don't select when frozen"); @@ -4572,6 +4581,17 @@ public: enable_notify_events(); } + virtual void scroll_to_row(const weld::TreeIter& rIter) override + { + disable_notify_events(); + const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); + GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); + GtkTreePath* path = gtk_tree_model_get_path(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + gtk_tree_view_scroll_to_cell(m_pTreeView, path, nullptr, false, 0, 0); + gtk_tree_path_free(path); + enable_notify_events(); + } + virtual void unselect(const weld::TreeIter& rIter) override { assert(gtk_tree_view_get_model(m_pTreeView) && "don't select when frozen"); @@ -4593,9 +4613,12 @@ public: virtual bool iter_has_child(const weld::TreeIter& rIter) const override { - const GtkInstanceTreeIter& rGtkIter = static_cast<const GtkInstanceTreeIter&>(rIter); - GtkTreeModel *pModel = GTK_TREE_MODEL(m_pTreeStore); - return gtk_tree_model_iter_has_child(pModel, const_cast<GtkTreeIter*>(&rGtkIter.iter)); + weld::TreeIter& rNonConstIter = const_cast<weld::TreeIter&>(rIter); + GtkInstanceTreeIter& rGtkIter = static_cast<GtkInstanceTreeIter&>(rNonConstIter); + GtkTreeIter restore(rGtkIter.iter); + bool ret = iter_children(rNonConstIter); + rGtkIter.iter = restore; + return ret; } virtual bool get_row_expanded(const weld::TreeIter& rIter) const override @@ -6356,7 +6379,7 @@ namespace Help* pHelp = !sHelpId.isEmpty() ? Application::GetHelp() : nullptr; if (pHelp) { - OUString sHelpText = pHelp->GetHelpText(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), nullptr); + OUString sHelpText = pHelp->GetHelpText(OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8), static_cast<weld::Widget*>(nullptr)); if (!sHelpText.isEmpty()) { gtk_tooltip_set_text(tooltip, OUStringToOString(sHelpText, RTL_TEXTENCODING_UTF8).getStr()); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits