[Libreoffice-commits] core.git: 2 commits - framework/Library_fwk.mk framework/source framework/util officecfg/registry sfx2/sdi

Maxim Monastirsky momonasmon at gmail.com
Wed Nov 11 05:04:46 PST 2015


 framework/Library_fwk.mk                                             |    1 
 framework/source/uielement/menubarmanager.cxx                        |    7 
 framework/source/uielement/thesaurusmenucontroller.cxx               |  218 ++++++++++
 framework/source/uielement/uicommanddescription.cxx                  |   12 
 framework/util/fwk.component                                         |    4 
 officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu      |   11 
 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu |    8 
 officecfg/registry/schema/org/openoffice/Office/UI/Commands.xcs      |    5 
 sfx2/sdi/sfx.sdi                                                     |    2 
 9 files changed, 266 insertions(+), 2 deletions(-)

New commits:
commit a133053f94f7c5b05f4354bb4977c2250b470a8a
Author: Maxim Monastirsky <momonasmon at gmail.com>
Date:   Wed Nov 11 15:01:52 2015 +0200

    tdf#93837 Create Thesaurus popup menu controller
    
    The old context menu implementation adds the thesaurus
    sub-menu by manipulating the menu at runtime, which isn't a
    good idea in general. Since it's a sub-menu anyway, better
    to have it as a separate controller, so it can be added
    to the xml, and users could decide if they want it, and
    where.
    
    Most of the code adapted from sfx2 (menu/mnumgr.cxx,
    menu/thessubmenu.cxx), hence the Apache-based license
    header.
    
    Change-Id: I4f533fcdd5d6480fae8ebcf53ec7c69675025adb

diff --git a/framework/Library_fwk.mk b/framework/Library_fwk.mk
index d07f8b9..3efd330 100644
--- a/framework/Library_fwk.mk
+++ b/framework/Library_fwk.mk
@@ -153,6 +153,7 @@ $(eval $(call gb_Library_add_exception_objects,fwk,\
     framework/source/uielement/statusbarwrapper \
     framework/source/uielement/statusindicatorinterfacewrapper \
     framework/source/uielement/subtoolbarcontroller \
+    framework/source/uielement/thesaurusmenucontroller \
     framework/source/uielement/togglebuttontoolbarcontroller \
     framework/source/uielement/toolbarmanager \
     framework/source/uielement/toolbarmerger \
diff --git a/framework/source/uielement/thesaurusmenucontroller.cxx b/framework/source/uielement/thesaurusmenucontroller.cxx
new file mode 100644
index 0000000..b9457d7
--- /dev/null
+++ b/framework/source/uielement/thesaurusmenucontroller.cxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <comphelper/processfactory.hxx>
+#include <svl/lngmisc.hxx>
+#include <svtools/popupmenucontrollerbase.hxx>
+#include <unotools/lingucfg.hxx>
+#include <vcl/image.hxx>
+#include <vcl/menu.hxx>
+
+#include <com/sun/star/frame/theUICommandDescription.hpp>
+#include <com/sun/star/linguistic2/LinguServiceManager.hpp>
+
+class ThesaurusMenuController : public svt::PopupMenuControllerBase
+{
+public:
+    explicit ThesaurusMenuController( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+    virtual ~ThesaurusMenuController();
+
+    // XStatusListener
+    virtual void SAL_CALL statusChanged( const css::frame::FeatureStateEvent& rEvent ) throw ( css::uno::RuntimeException, std::exception ) override;
+
+    // XServiceInfo
+    virtual OUString SAL_CALL getImplementationName() throw ( css::uno::RuntimeException, std::exception ) override;
+    virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw ( css::uno::RuntimeException, std::exception ) override;
+
+private:
+    virtual void impl_setPopupMenu() override;
+    void getMeanings( std::vector< OUString >& rSynonyms, const OUString& rWord, const css::lang::Locale& rLocale, size_t nMaxSynonms );
+    OUString getThesImplName( const css::lang::Locale& rLocale ) const;
+    css::uno::Reference< css::linguistic2::XLinguServiceManager2 > m_xLinguServiceManager;
+    css::uno::Reference< css::linguistic2::XThesaurus > m_xThesaurus;
+    OUString m_aLastWord;
+};
+
+namespace {
+
+OUString RetrieveLabelFromCommand( const OUString& rCmdURL, const OUString& rModuleName )
+{
+    if ( rCmdURL.isEmpty() || rModuleName.isEmpty() )
+        return OUString();
+
+    css::uno::Any a;
+    css::uno::Sequence< css::beans::PropertyValue > aPropSeq;
+    try
+    {
+        css::uno::Reference< css::container::XNameAccess > const xNameAccess(
+            css::frame::theUICommandDescription::get( comphelper::getProcessComponentContext() ), css::uno::UNO_QUERY_THROW );
+        a = xNameAccess->getByName( rModuleName );
+        css::uno::Reference< css::container::XNameAccess > xUICommandLabels;
+        a >>= xUICommandLabels;
+        a = xUICommandLabels->getByName( rCmdURL );
+        a >>= aPropSeq;
+    }
+    catch ( const css::uno::Exception& )
+    {
+        SAL_WARN( "fwk.uielement", "Failed to get label for command " << rCmdURL );
+    }
+
+    OUString aLabel;
+    for ( const auto& aProp : aPropSeq )
+    {
+        if ( aProp.Name == "Label" )
+        {
+            aProp.Value >>= aLabel;
+        }
+        else if ( aProp.Name == "PopupLabel" )
+        {
+            OUString aStr;
+            if ( ( aProp.Value >>= aStr ) && !aStr.isEmpty() )
+                return aStr;
+        }
+    }
+    return aLabel;
+}
+
+}
+
+ThesaurusMenuController::ThesaurusMenuController( const css::uno::Reference< css::uno::XComponentContext >& rxContext ) :
+    svt::PopupMenuControllerBase( rxContext ),
+    m_xLinguServiceManager( css::linguistic2::LinguServiceManager::create( rxContext ) ),
+    m_xThesaurus( m_xLinguServiceManager->getThesaurus() )
+{
+}
+
+ThesaurusMenuController::~ThesaurusMenuController()
+{
+}
+
+void ThesaurusMenuController::statusChanged( const css::frame::FeatureStateEvent& rEvent )
+    throw ( css::uno::RuntimeException, std::exception )
+{
+    rEvent.State >>= m_aLastWord;
+    m_xPopupMenu->clear();
+    if ( rEvent.IsEnabled )
+        impl_setPopupMenu();
+}
+
+void ThesaurusMenuController::impl_setPopupMenu()
+{
+    OUString aText = m_aLastWord.getToken(0, '#');
+    OUString aIsoLang = m_aLastWord.getToken(1, '#');
+    if ( aText.isEmpty() || aIsoLang.isEmpty() )
+        return;
+
+    std::vector< OUString > aSynonyms;
+    css::lang::Locale aLocale = LanguageTag::convertToLocale( aIsoLang );
+    getMeanings( aSynonyms, aText, aLocale, 7 /*max number of synonyms to retrieve*/ );
+
+    VCLXMenu* pAwtMenu = VCLXMenu::GetImplementation( m_xPopupMenu );
+    Menu* pVCLMenu = pAwtMenu->GetMenu();
+    pVCLMenu->SetMenuFlags( MenuFlags::NoAutoMnemonics );
+    if ( aSynonyms.size() > 0 )
+    {
+        SvtLinguConfig aCfg;
+        Image aImage;
+        OUString aThesImplName( getThesImplName( aLocale ) );
+        OUString aSynonymsImageUrl( aCfg.GetSynonymsContextImage( aThesImplName ) );
+        if ( !aThesImplName.isEmpty() && !aSynonymsImageUrl.isEmpty() )
+            aImage = Image( aSynonymsImageUrl );
+
+        for ( const auto& aSynonym : aSynonyms )
+        {
+            const sal_uInt16 nId = pVCLMenu->GetItemCount() + 1;
+            OUString aItemText( linguistic::GetThesaurusReplaceText( aSynonym ) );
+            pVCLMenu->InsertItem( nId, aItemText );
+            pVCLMenu->SetItemCommand( nId, ".uno:ThesaurusFromContext?WordReplace:string=" + aItemText );
+
+            if ( !aSynonymsImageUrl.isEmpty() )
+                pVCLMenu->SetItemImage( nId, aImage );
+        }
+
+        pVCLMenu->InsertSeparator();
+        OUString aThesaurusDialogCmd( ".uno:ThesaurusDialog" );
+        pVCLMenu->InsertItem( 100, RetrieveLabelFromCommand( aThesaurusDialogCmd, m_aModuleName ) );
+        pVCLMenu->SetItemCommand( 100, aThesaurusDialogCmd );
+    }
+}
+
+void ThesaurusMenuController::getMeanings( std::vector< OUString >& rSynonyms, const OUString& rWord,
+                                           const css::lang::Locale& rLocale, size_t nMaxSynonms )
+{
+    rSynonyms.clear();
+    if ( m_xThesaurus.is() && m_xThesaurus->hasLocale( rLocale ) && !rWord.isEmpty() && nMaxSynonms > 0 )
+    {
+        try
+        {
+            const css::uno::Sequence< css::uno::Reference< css::linguistic2::XMeaning > > aMeaningSeq(
+                m_xThesaurus->queryMeanings( rWord, rLocale, css::uno::Sequence< css::beans::PropertyValue >() ) );
+
+            for ( const auto& xMeaning : aMeaningSeq )
+            {
+                const css::uno::Sequence< OUString > aSynonymSeq( xMeaning->querySynonyms() );
+                for ( const auto& aSynonym : aSynonymSeq )
+                {
+                    rSynonyms.push_back( aSynonym );
+                    if ( rSynonyms.size() == nMaxSynonms )
+                        return;
+                }
+            }
+        }
+        catch ( const css::uno::Exception& )
+        {
+            SAL_WARN( "fwk.uielement", "Failed to get synonyms" );
+        }
+    }
+}
+
+OUString ThesaurusMenuController::getThesImplName( const css::lang::Locale& rLocale ) const
+{
+    css::uno::Sequence< OUString > aServiceNames =
+        m_xLinguServiceManager->getConfiguredServices( "com.sun.star.linguistic2.Thesaurus", rLocale );
+    SAL_WARN_IF( aServiceNames.getLength() > 1, "fwk.uielement", "Only one thesaurus is allowed per locale, but found more!" );
+    if ( aServiceNames.getLength() == 1 )
+        return aServiceNames[0];
+
+    return OUString();
+}
+
+OUString ThesaurusMenuController::getImplementationName()
+    throw ( css::uno::RuntimeException, std::exception )
+{
+    return OUString( "com.sun.star.comp.framework.ThesaurusMenuController" );
+}
+
+css::uno::Sequence< OUString > ThesaurusMenuController::getSupportedServiceNames()
+    throw ( css::uno::RuntimeException, std::exception )
+{
+    css::uno::Sequence< OUString > aRet( 1 );
+    aRet[0] = "com.sun.star.frame.PopupMenuController";
+    return aRet;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
+com_sun_star_comp_framework_ThesaurusMenuController_get_implementation(
+    css::uno::XComponentContext* xContext,
+    css::uno::Sequence< css::uno::Any > const & )
+{
+    return cppu::acquire( new ThesaurusMenuController( xContext ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/framework/util/fwk.component b/framework/util/fwk.component
index ad16782..e1744fc 100644
--- a/framework/util/fwk.component
+++ b/framework/util/fwk.component
@@ -204,4 +204,8 @@
       constructor="com_sun_star_comp_framework_SubToolBarController_get_implementation">
     <service name="com.sun.star.frame.ToolbarController"/>
   </implementation>
+  <implementation name="com.sun.star.comp.framework.ThesaurusMenuController"
+      constructor="com_sun_star_comp_framework_ThesaurusMenuController_get_implementation">
+    <service name="com.sun.star.frame.PopupMenuController"/>
+  </implementation>
 </component>
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
index 5e885fd..c4f6711 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/Controller.xcu
@@ -185,6 +185,17 @@
           <value>com.sun.star.comp.framework.SaveAsMenuController</value>
         </prop>
       </node>
+      <node oor:name="c17" oor:op="replace">
+        <prop oor:name="Command">
+          <value>.uno:ThesaurusFromContext</value>
+        </prop>
+        <prop oor:name="Module">
+          <value/>
+        </prop>
+        <prop oor:name="Controller">
+          <value>com.sun.star.comp.framework.ThesaurusMenuController</value>
+        </prop>
+      </node>
     </node>
     <node oor:name="ToolBar">
       <node oor:name="ZoomToolBox" oor:op="replace">
diff --git a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
index 161b46c..cab5cbe 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
@@ -5632,6 +5632,14 @@
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:ThesaurusFromContext" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Synony~ms</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
     </node>
     <node oor:name="Popups">
       <node oor:name=".uno:HelpMenu" oor:op="replace">
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index e207e8b..f151bc7 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -7802,7 +7802,7 @@ SfxInt16Item ThesaurusFromContext SID_THES
 
     /* config: */
     AccelConfig = FALSE,
-    MenuConfig = FALSE,
+    MenuConfig = TRUE,
     StatusBarConfig = FALSE,
     ToolBoxConfig = FALSE,
     GroupId = GID_TEXT;
commit 737555eb2ff5f4f90b9794784e1ac8f0451b9b97
Author: Maxim Monastirsky <momonasmon at gmail.com>
Date:   Wed Oct 28 14:21:03 2015 +0200

    tdf#93837 Add a new PopupLabel property
    
    Some commands in context menus use different labels than in
    the menu bar. In the old resource format those labels are
    defined in the resource file itself. Note that the menu xml
    has the menu:label attribute, but we can't use it because it
    lacks localization support, and as such useful only for user
    customization.
    
    The order of consideration now is:
    
    1. Label - Used if Context/PopupLabel isn't defined. (It's
       also used as the base for toolbar tooltips.)
    
    2. ContextLabel - Overrides Label when in menu or context menu.
       Useful to drop the context, e.g. "Insert Image" should be only
       "Image" under "Insert" menu. If exists, that's what returned
       when asking for the "Label" property, instead of the full label.
    
    3. PopupLabel - Overrides Label/ContextLabel when in context menu.
       Used to give items in a context menu different labels than in
       the main menu, e.g. "Paste Special" from the main menu turns to
       "More Options" when in context menu. It doesn't affect the Label
       property, and should be asked separately.
    
    Change-Id: I7408fc2bfb8d384b0f1a72a78b8c5d7c50de38da

diff --git a/framework/source/uielement/menubarmanager.cxx b/framework/source/uielement/menubarmanager.cxx
index 2c0db7b..399c667 100644
--- a/framework/source/uielement/menubarmanager.cxx
+++ b/framework/source/uielement/menubarmanager.cxx
@@ -1096,6 +1096,13 @@ bool MenuBarManager::MustBeHidden( PopupMenu* pPopupMenu, const Reference< XURLT
 
 OUString MenuBarManager::RetrieveLabelFromCommand(const OUString& rCmdURL)
 {
+    if ( !m_bHasMenuBar )
+    {
+        // This is a context menu, prefer "PopupLabel" over "Label".
+        OUString aPopupLabel = framework::RetrieveLabelFromCommand(rCmdURL, m_xContext, m_xUICommandLabels,m_xFrame,m_aModuleIdentifier,m_bModuleIdentified,"PopupLabel");
+        if ( !aPopupLabel.isEmpty() )
+            return aPopupLabel;
+    }
     return framework::RetrieveLabelFromCommand(rCmdURL, m_xContext, m_xUICommandLabels,m_xFrame,m_aModuleIdentifier,m_bModuleIdentified,"Label");
 }
 
diff --git a/framework/source/uielement/uicommanddescription.cxx b/framework/source/uielement/uicommanddescription.cxx
index de99a7b..3f6bc54 100644
--- a/framework/source/uielement/uicommanddescription.cxx
+++ b/framework/source/uielement/uicommanddescription.cxx
@@ -59,11 +59,13 @@ static const char CONFIGURATION_CMD_ELEMENT_ACCESS[]    = "/UserInterface/Comman
 static const char CONFIGURATION_POP_ELEMENT_ACCESS[]    = "/UserInterface/Popups";
 static const char CONFIGURATION_PROPERTY_LABEL[]        = "Label";
 static const char CONFIGURATION_PROPERTY_CONTEXT_LABEL[] = "ContextLabel";
+static const char CONFIGURATION_PROPERTY_POPUP_LABEL[]   = "PopupLabel";
 
 // Property names of the resulting Property Set
 static const char PROPSET_LABEL[]                       = "Label";
 static const char PROPSET_NAME[]                        = "Name";
 static const char PROPSET_POPUP[]                       = "Popup";
+static const char PROPSET_POPUPLABEL[]                  = "PopupLabel";
 static const char PROPSET_PROPERTIES[]                  = "Properties";
 
 // Special resource URLs to retrieve additional information
@@ -123,6 +125,7 @@ class ConfigurationAccess_UICommand : // Order is necessary for right initializa
             OUString            aLabel;
             OUString            aContextLabel;
             OUString            aCommandName;
+            OUString            aPopupLabel;
             bool                bPopup : 1,
                                 bCommandNameCreated : 1;
             sal_Int32           nProperties;
@@ -151,9 +154,11 @@ class ConfigurationAccess_UICommand : // Order is necessary for right initializa
         OUString                     m_aConfigPopupAccess;
         OUString                     m_aPropUILabel;
         OUString                     m_aPropUIContextLabel;
+        OUString                     m_aPropUIPopupLabel;
         OUString                     m_aPropLabel;
         OUString                     m_aPropName;
         OUString                     m_aPropPopup;
+        OUString                     m_aPropPopupLabel;
         OUString                     m_aPropProperties;
         OUString                     m_aPrivateResourceURL;
         Reference< XNameAccess >          m_xGenericUICommands;
@@ -178,9 +183,11 @@ ConfigurationAccess_UICommand::ConfigurationAccess_UICommand( const OUString& aM
     m_aConfigPopupAccess( CONFIGURATION_ROOT_ACCESS ),
     m_aPropUILabel( CONFIGURATION_PROPERTY_LABEL ),
     m_aPropUIContextLabel( CONFIGURATION_PROPERTY_CONTEXT_LABEL ),
+    m_aPropUIPopupLabel( CONFIGURATION_PROPERTY_POPUP_LABEL ),
     m_aPropLabel( PROPSET_LABEL ),
     m_aPropName( PROPSET_NAME ),
     m_aPropPopup( PROPSET_POPUP ),
+    m_aPropPopupLabel( PROPSET_POPUPLABEL ),
     m_aPropProperties( PROPSET_PROPERTIES ),
     m_aPrivateResourceURL( PRIVATE_RESOURCE_URL ),
     m_xGenericUICommands( rGenericUICommands ),
@@ -299,7 +306,7 @@ Any ConfigurationAccess_UICommand::getSequenceFromCache( const OUString& aComman
         if ( !pIter->second.bCommandNameCreated )
             fillInfoFromResult( pIter->second, pIter->second.aLabel );
 
-        Sequence< PropertyValue > aPropSeq( 4 );
+        Sequence< PropertyValue > aPropSeq( 5 );
         aPropSeq[0].Name  = m_aPropLabel;
         aPropSeq[0].Value = !pIter->second.aContextLabel.isEmpty() ?
                 makeAny( pIter->second.aContextLabel ): makeAny( pIter->second.aLabel );
@@ -309,6 +316,8 @@ Any ConfigurationAccess_UICommand::getSequenceFromCache( const OUString& aComman
         aPropSeq[2].Value <<= pIter->second.bPopup;
         aPropSeq[3].Name  = m_aPropProperties;
         aPropSeq[3].Value <<= pIter->second.nProperties;
+        aPropSeq[4].Name  = m_aPropPopupLabel;
+        aPropSeq[4].Value <<= pIter->second.aPopupLabel;
         return makeAny( aPropSeq );
     }
 
@@ -335,6 +344,7 @@ void ConfigurationAccess_UICommand::impl_fill(const Reference< XNameAccess >& _x
                     aCmdToInfo.bPopup = _bPopup;
                     xNameAccess->getByName( m_aPropUILabel )        >>= aCmdToInfo.aLabel;
                     xNameAccess->getByName( m_aPropUIContextLabel ) >>= aCmdToInfo.aContextLabel;
+                    xNameAccess->getByName( m_aPropUIPopupLabel )   >>= aCmdToInfo.aPopupLabel;
                     xNameAccess->getByName( m_aPropProperties )     >>= aCmdToInfo.nProperties;
 
                     m_aCmdInfoCache.insert( CommandToInfoCache::value_type( aNameSeq[i], aCmdToInfo ));
diff --git a/officecfg/registry/schema/org/openoffice/Office/UI/Commands.xcs b/officecfg/registry/schema/org/openoffice/Office/UI/Commands.xcs
index f5e1224..85460d2 100644
--- a/officecfg/registry/schema/org/openoffice/Office/UI/Commands.xcs
+++ b/officecfg/registry/schema/org/openoffice/Office/UI/Commands.xcs
@@ -36,6 +36,11 @@
           <desc>A localized text that describes the identifier of a command in a structured menu.  </desc>
         </info>
       </prop>
+      <prop oor:name="PopupLabel" oor:type="xs:string" oor:localized="true">
+        <info>
+          <desc>A localized text that describes the identifier of a command in a popup menu.</desc>
+        </info>
+      </prop>
       <prop oor:name="Properties" oor:type="xs:int" oor:nillable="false">
         <info>
           <desc>


More information about the Libreoffice-commits mailing list