LicenseDialog/de

From Wiki.ooo4kids.org
Jump to: navigation, search


License Dialog

All the changes added to the original OpenOffice.org source code provided in this page, are :

  • Under LGPL License V3, ( and you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation)
  • Copyright Eric Bachard 12th august 2009


Introduction

Below, you'll find a technical description of the License menu entry feature. It is question of OpenOffice.org source code (mainly C++ and Objective C), e.g. the internal source code organisation in OpenOffice.org framework, the interaction with the graphical part aka vcl, .. and so on. Thus, we suppose the reader has the mandatory bases to understand the content of what is proposed.

The pre-requisites to read this article still have to be defined, but if the reader is not used with some notions, we invite him to have a look at the OpenOffice.org wiki to complete his knowledge, and read this article in the best conditions.

State of the Implementation

  • TAG DONE.png Mac OS X (Aqua) part
  • TAG DONE.png Write the .xcu
  • TAG DONE.png Create the dialog box
  • TAG TODO.png Description of the ShowLicenseDialog Class
  • TAG DONE.png Connect to vcl
  • TAG DONE.png Connect to svx
  • TAG DONE.png Connect to sfx2
  • TAG DONE.png Connect to framework
  • TAG DONE.png Connect to unotools
  • TAG DONE.png Debug
  • TAG PROGRESS.png Document



Specifications


  • Add an entry in all applications menus, allowing to check the OOo4Kids license.



Show License02 13rdAugust2009.jpg



  • Expected behavior:
    • click on the menu entry opens a modal window, explaining the OOo4Kids licence, and giving a link where to read it.
    • click OK closes the window



Way used

  • A new entry will be added in some menu

The menu will send an event, the application will receive, and turn into a uno command ( .uno:ShowLicense). the command will be dispatched, and the modal window, showing the text, will be open. Ok will close it

Other ways:

  • The GenericCommands.xcu will have an .uno:ShowLicense entry ( a command will be dispatched )

So either a new menu entry will be available in the list, or a new button "License ..." can be added to any toolbar, through the Options ->Customize menu.

As test, the menubar.xml of all applications will have the command available (for testing purpose)

How things work

1) starting from vcl

The description in this part is for the Mac OS X Aqua version only


On Mac OS X, Aqua version :

The string "License ..." (en-US) is created in vcl/source/src/stdtext.src (I have added the fr string, so it will appear localized in the menu)

String SV_STDTEXT_LICENSE                                                                                                               
{                                                                                                                                       
    Text [ en-US ] = "License ...";                                                                                                     
    Text [ fr ] = "Licence ...";                                                                                                        
};

At build time, the strings will be added in the vclfr.res (fr ) or vcl.res (en-US, default), and delivered, packaged .. and so on


Select the main Aqua menu : " File -> License... "

=> will send a "SHOW_DIALOG" event type, containing the string "LICENSE"

In the code: see vcl/aqua/source/window/salmenu.cxx

       else if( nDialog == SHOWDIALOG_ID_LICENSE )                                                                                     
           aDialog = String( RTL_CONSTASCII_USTRINGPARAM( "LICENSE" ) );                                                               
       const ApplicationEvent* pAppEvent = new ApplicationEvent( String(),                                                             
                                                                 ApplicationAddress(),                                                 
                                                                 ByteString( "SHOWDIALOG" ),                                           
                                                                 aDialog );                                                            
       AquaSalInstance::aAppEventList.push_back( pAppEvent );                    


2) ...in framework

Next step : since this is a system event, the Application (see the next point, in desktop) cannot catch the event, and the workaround is to start an eventlistener in framework, to catch all the hardcoded SHOWDIALOG events. This is exactly achieved in framework/source/dispatch/windowcommanddispatch.cxx

First a listener is launched ( void WindowCommandDispatch::impl_startListening() ) in the Ctor.

Second, we create an OUString :

 const ::rtl::OUString WindowCommandDispatch::COMMAND_LICENSEBOX    = ::rtl::OUString::createFromAscii(".uno:ShowLicense");

Once the event is catched, we use a callback to dispatch it, using :

IMPL_LINK(WindowCommandDispatch, impl_notifyCommand, void*, pParam) 

Who does :

   switch (nCommand)                                                                                             
    {                                                                                                             
 
...                            
        case SHOWDIALOG_ID_LICENSE :                                                                              
                sCommand = WindowCommandDispatch::COMMAND_LICENSEBOX;

and finishes with :

    impl_dispatchCommand(sCommand);     

Next step -> the command is catched and executed in sfx2


Suggestion :

=> see the full description in : framework/source/inc/dispatch/windowcommanddispatch.cxx

/** @short  internal helper to bind e.g. MAC-Menu events to our internal dispatch API.                            
                                                                                                                  
    @descr  On e.g. MAC platform system menus are merged together with some fix entries as                        
            e.g. "Preferences" or "About". These menu entries trigger hard coded commands.                        
            Here we map these commands to the right URLs and dispatch them.                                       

3) from desktop to (unotools ?)

TODO : is the API already able to use it ?

4) officefg

What happens in officecfg ?

  • A new menu entry is created, with the name .uno:ShowLicense. If matching with a real slot id, the menu entry will become active, else it will stay greyed.


The changes have been made in GenericCommand.xcu, and respect .xml syntax. We added the "node" .uno:ShowLicense :

			<node oor:name=".uno:ShowLicense" oor:op="replace">
				<prop oor:name="Label" oor:type="xs:string">
					<value xml:lang="en-US">L~icense ...</value>
					<value xml:lang="fr">L~icence ...</value>
				</prop>
			</node>

In Tools -> Customize, the user will have the possibility to add either a new "License ..." menu entry, or a new "License ..." button in any toolbar.

As example, the image below describes the case of adding a new "License ..." menu entry :



Insert License Menu Entry fr.jpg



5) what happens in sfx2

  • A slot, seen as a new command, will become active (else the menu entry will be greyed). The rôle of the sfx2, is to dispatch the menu entry when clicked
  • Any "event" seen as SID_LICENSE will be dispatched, and forwarded to framework, and will be treated as .uno:ShowLicense command in appserv.cxx


Be carefull: what follows, has maybe some wrong changes. Please contact me (and explain me what is wrong, and should be modified).

e.g. : I have randomly choosen some values  ;-)

Define the new constants

What are the best values ?

=> it seems there is no exact rule (just take care there is no overlap)

  • in sfx2/inc/sfx2/sfx.hrc:

Added :

// ressource ID used in appserv.cxx

#define RID_DEFAULTLICENSE                                      (RID_SFX_START+20)                                                       


// constants used to define the dialog box content
                                                                                
#define LICENSE_BTN_OK                        6                                                                                         
                                                                                                                                        
#define LICENSE_FTXT_VERSION                  6                                                                                         
#define LICENSE_FTXT_COPYRIGHT                7                                                                                         
                                                                                                                                        
#define LICENSE_STR_DEVELOPER_ARY             6                                                                                         
#define LICENSE_STR_FRENCH_COPYRIGHT          7                                                                                         
#define LICENSE_STR_ACCEL                     8
  • in sfx2/inc/sfx2/sfxsids.hrc:
// added SID_LICENSE constant 

// default-ids for application                                                                                                          
#define SID_QUITAPP                         (SID_SFX_START + 300)                                                                       
#define SID_ABOUT                           (SID_SFX_START + 301)                                                                       
#define SID_SETUPPRINTER                    (SID_SFX_START + 302)                                                                       
#define SID_EXITANDRETURN                   (SID_SFX_START + 303)                                                                       
#define SID_LICENSE                         (SID_SFX_START + 304) 
Define the new slot

First, add a new item in sfx2/sdi/sfx.sdi:SfxVoidItem ShowLicense SID_LICENSE

Please notice the syntax : SfxVoidItem ShowLicense SID_LICENSE

  • Type is SfxVoidItem
  • The name of the slot method is ShowLicense
  • the associated constant is SID_LICENSE

Note : obviously inspired from SID_ABOUT

//--------------------------------------------------------------------------                                                            
SfxVoidItem ShowLicense SID_LICENSE                                                                                                           
()                                                                                                                                      
[                                                                                                                                       
        /* flags: */                                                                                                                    
        AutoUpdate = FALSE,                                                                                                             
        Cachable = Cachable,                                                                                                            
        FastCall = FALSE,                                                                                                               
        HasCoreId = FALSE,                                                                                                              
        HasDialog = TRUE,                                                                                                               
        ReadOnlyDoc = TRUE,                                                                                                             
        Toggle = FALSE,                                                                                                                 
        Container = FALSE,                                                                                                              
        RecordAbsolute = FALSE,                                                                                                         
        RecordPerSet;                                                                                                                   
        Synchron;                                                                                                                       
                                                                                                                                        
        /* config: */                                                                                                                   
        AccelConfig = TRUE,                                                                                                             
        MenuConfig = TRUE,                                                                                                              
        StatusBarConfig = FALSE,                                                                                                        
        ToolBoxConfig = TRUE,                                                                                                           
        GroupId = GID_APPLICATION;                                                                                                      
]                                                                                                            

And now, define the interface. Means in the appserv.cxx, the real implementation will use the MiscExec() method.

If you read other interfaces definitions in the same file, you'll see other possibilities.

Index: sfx2/sdi/appslots.sdi                                                                                       
===================================================================                                                
--- sfx2/sdi/appslots.sdi       (revision 274625)                                                                  
+++ sfx2/sdi/appslots.sdi       (working copy)                                                                     
@@ -52,6 +52,10 @@                                                                                                 
        [                                                                                                          
                ExecMethod = MiscExec_Impl ;                                                                       
        ]                                                                                                          
+       SID_LICENSE // ole(no) api(final/play/rec)                                                                 
+       [                                                                                                          
+               ExecMethod = MiscExec_Impl ;                                                                       
+       ]                                                                                                          
        SID_SETOPTIONS                                                                                             
        [                                                                                                          
                ExecMethod = MiscExec_Impl ;

Implement the method

Now, we are in sfx2/source/appl/appserv.cxx

First, include the showlicence.hxx (new header file, derived from the about.hxx )

Then, as expected, in void SfxApplication::MiscExec_Impl( SfxRequest& rReq ) , add the new case SID_LICENSE


+       case SID_LICENSE:
+       {                                                                                                                 
+                                                                                                                         
+           String sBuildId( String::CreateFromAscii( "This text will explain the license OOo4Kids will use


What follows will contain "License ..."


+                                                                                                                         
+           rtl::OUString aLicenseContent( DEFINE_CONST_OUSTRING( "SHOW_LICENSE" ) );                                                                          

Retrieve the resource ID

                                                                                                                        
+            // search for the resource of the license box                                                                
+            ResId aDialogResId( RID_DEFAULTLICENSE, *pAppData_Impl->pLabelResMgr );                                      
+            ResMgr* pResMgr = pAppData_Impl->pLabelResMgr;                                                               
+            if( ! pResMgr->IsAvailable( aDialogResId.SetRT( RSC_MODALDIALOG ) ) )                                        
+                pResMgr = GetOffResManager_Impl();                                                                       
+                                                                                                                         

... verify that's ok

+            aDialogResId.SetResMgr( pResMgr );                                                                           
+            if ( !pResMgr->IsAvailable( aDialogResId ) )                                                                 
+            {                                                                                                            
+                DBG_ERRORFILE( "No RID_DEFAULTLICENSE in label-resource-dll" );                                          
+            }                                                                                                            
+                                                                                                                         

Once everything is ok, then display the dialog box :

+            // then show the license box                                                                                 
+            ShowLicenseDialog* pDlg = new ShowLicenseDialog( 0, aDialogResId, sBuildId );
                                                        pDlg->Execute();
                                                        delete pDlg;
                                                        bDone = TRUE;                                                                                     
+           break;                                                                                                        
+       }   

6) The "ShowLicense" modal dialog box

TODO : describe

7) note about what happens in desktop

FIXME : why do we never hit that ?

In desktop, Desktop::HandleAppEvent() should normaly catch the event, in app.cxx:2830 ( see desktop/source/app/app.cxx ) , and if the catched string does contain "LICENSE". But for a reason I still ignore, we never hit this method ?? If ever we can reach the place, w<hat should happen is described below :


First, the string ".uno:ShowLicense", means the command label, will be created :


In the code :

app.cxx:2837, in void Desktop::HandleAppEvent( const ApplicationEvent& rAppEvent ) :

          else if( rAppEvent.GetData().EqualsAscii( "LICENSE" ) )                                                                     
               aCommand.Complete = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ".uno:ShowLicense" ) );

Then, once completed, the command is dispatched :

           if( aCommand.Complete.getLength() )                                                                                         
           {                                                                                                                           
               xParser->parseStrict(aCommand);                                                                                         
                                                                                                                                       
               css::uno::Reference< css::frame::XDispatch > xDispatch = xDesktop->queryDispatch(aCommand, rtl::OUString(), 0);         
               if (xDispatch.is())                                                                                                     
                   xDispatch->dispatch(aCommand, css::uno::Sequence< css::beans::PropertyValue >());                                   
           }

Mac OS X (Aqua) part

TAG DONE.png

License Aqua fr.jpg

Changes in the code :

1) vcl :


  1. HUNK1

Add the constant in vcl/inc/vcl/cmdevt.hxx

+#if defined( OOo4Kids )                                                                                          
+#define SHOWDIALOG_ID_LICENCE          3                                                                         
+#endif                                                                                                           

  1. HUNK 2

Add the new Cocoa menu entry, as a string, in vcl/source/src/stdtxt.src

String SV_STDTEXT_LICENSE                                                                                               
{                                                                                                                       
    Text [ en-US ] = "License ";                                                                
    Text [ fr ] = "Licence ";                                                                
};                                                                                                                      

  1. HUNK 3


Add the new constant in vcl/inc/vcl/menu.hxx :

Index: vcl/inc/vcl/menu.hxx                                                                                             
===================================================================                                                     
--- vcl/inc/vcl/menu.hxx        (revision 274625)                                                                       
+++ vcl/inc/vcl/menu.hxx        (working copy)                                                                          
@@ -90,6 +90,7 @@                                                                                                       
 #define MIB_AUTOCHECK                  ((MenuItemBits)0x0004)                                                          
 #define MIB_ABOUT                              ((MenuItemBits)0x0008)                                                  
 #define MIB_HELP                               ((MenuItemBits)0x0010)                                                  
 +#define MIB_SHOWLICENSE                                ((MenuItemBits)0x0016)                                          
 #define MIB_POPUPSELECT                ((MenuItemBits)0x0020)                                                          
 // not in rsc/vclsrc.hxx because only a prelimitary solution                                                           
 #define MIB_NOSELECT               ((MenuItemBits)0x0040)                                                              

Add a new constant in vcl/inc/vcl/svids.hrc :

Index: vcl/inc/vcl/svids.hrc

===================================================================                                                     
--- vcl/inc/vcl/svids.hrc       (revision 274625)                                                                       
+++ vcl/inc/vcl/svids.hrc       (working copy)                                                                          
@@ -108,6 +108,7 @@                                                                                                     
 #define SV_STDTEXT_ABOUT                    10204                                                                      
 #define SV_STDTEXT_PREFERENCES              10205                                                                      
 #define SV_MAC_SCREENNNAME                  10206                                                                      
 +#define SV_STDTEXT_LICENSE                 10207                                                                       
 #define SV_STDTEXT_LAST                                        SV_MAC_SCREENNNAME                                      
                                                                                                                        
 #define SV_ACCESSERROR_FIRST                           SV_ACCESSERROR_WRONG_VERSION                                    


Add the new entry in the Aqua menu ( vcl/aqua/source/window/salmenu.cxx )

@@ -146,11 +153,25 @@                                                                                                   
                         [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 3];                                  
                     }                                                                                                  
                                                                                                                        
+                    // insert license entry                                                                            
+                    String aLicense( ResId( SV_STDTEXT_LICENSE, *pMgr ) );                                             
+                    pString = CreateNSString( aLicense );                                                              
+                    pNewItem = [pAppMenu insertItemWithTitle: pString                                                  
+                                         action: @selector(showLicense:)                                               
+                                         keyEquivalent: @","                                                           
+                                         atIndex: 4];                                                                  
+                    if (pString)                                                                                       
+                        [pString release];                                                                             
+                    if( pNewItem )                                                                                     
+                    {                                                                                                  
+                        [pNewItem setTarget: pMainMenuSelector];                                                       
+                        [pAppMenu insertItem: [NSMenuItem separatorItem] atIndex: 5];                                  
+                    }                                                                                                  

+ define the method to receive the events :

Interface :

-(void)showLicense: (id)sender; 

Implementation :

-(void)showLicense: (id) sender                                                                                        
{                                                                                                                      
    [self showDialog: SHOWDIALOG_ID_LICENSE];                                                                          
}                                                                                                                      

IMPORTANT : do not forget to add +2 to all indexes  !! (else other menu entries will overlap :-) )




2) svx:

dans svx/inc/globlmn_tmpl.hrc


-> ajouter l'item .uno:ShowLicence

As example :

  1. define ITEM_HELP_ABOUT \
   Identifier = SID_ABOUT ; \                                                                                    
       Command = ".uno:About" ; \                                                                                
   HelpID = SID_ABOUT ; \                                                                                        
   Text [ en-US ] = "A~bout %PRODUCTNAME..." ; \                                                                 


3) desktop

desktop/source/app/app.cxx



  1. HUNK 1


  361     struct AboutBoxVersion
   362     	: public rtl::Static< String, AboutBoxVersion > {};

  1. HUNK 2

+ see ReplaceStringHookProc( UniString& rStr )


=>

void ReplaceStringHookProc( UniString& rStr )

   374 {
   375     static int nAll = 0, nPro = 0;
   376 
   377 	nAll++;
   378     if ( rStr.SearchAscii( "%PRODUCT" ) != STRING_NOTFOUND )
   379     {
   380         String &rBrandName = BrandName::get();
   381         String &rVersion = Version::get();
   382         String &rAboutBoxVersion = AboutBoxVersion::get();

  1. HUNK 3

+ see  : void Desktop::HandleAppEvent(


5) unotools

unotools/inc/unotools/configmgr.hxx#ABOUTBOXPRODUCTVERSION

See line around 90 : enum ConfigProperty


And :

           //direct readonly access to some special configuration elements
   108             static com::sun::star::uno::Any GetDirectConfigProperty(ConfigProperty eProp);
   109 
   110             sal_Bool        IsLocalConfigProvider();
   111             com::sun::star::uno::Reference< com::sun::star::container::XHierarchicalNameAccess>
   112                 GetHierarchyAccess(const rtl::OUString& rFullPath);
   113             com::sun::star::uno::Any GetLocalProperty(const rtl::OUString& rProperty);
   114             void PutLocalProperty(const rtl::OUString& , const com::sun::star::uno::Any& rValue);
   115 


DRF Globe.png External links


DRF Public.png To do

  • The background image
  • Put a mockup here.

DRF Star.png Ideas

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox