CalcFunctionsList/fr

À propos du code proposé dans cette page : tous les changements par rapport au code original d'OpenOffice.org ayant servi de base, et fournis dans cette page, sont :


 * '''sous Licence LGPL V3, ( et vous pouvez-le redistribuer et / ou le modifier selon les termes de la licence GNU Lesser General Public License telle que publiée par la Free Software Foundation)
 * Copyright Eric Bachard 12th august 2009

Introduction
Ci-dessous, vous trouverez une description technique de l'implémentation de la fonctionnalité : Liste des fonctions mathématiques dans Calc, en fonction du niveau utilisateur. Il est ainsi question de code source (C++, objective C), mais aussi de l'utilisation de la boite de dialogue, de type flottante, et qui contient l'assistant pour les fonctions mathématiques dans les formules. Nous supposons que le lecteur possède les bases nécessaires pour lire et comprendre le contenu de ce qui est exposé.

Les pré-requis pour lire cet article sont encore à définir, mais si certaines notions ne vous sont pas familières, nous vous invitons à consulter le wiki d'OpenOffice.org pour compléter vos connaissances, afin de pouvoir lire cet article dans les meilleures conditions possibles.

'Module : sc
sc/source/ui/scfuncs.src :  contient la liste complète des fonctions existant avec l'assistant. Pour chacune d'entre elles, il y a un champ nommé ExtraData field (0 pour visible, 1 pour caché), que j'ai utilisé jusquà maintenant pour cache les fonctions que je ne voulais pas voir dans la liste.

Mais l'implémentation d'un mécanisme faisant la différence entre débutant ..etc posait problème, et j'ai préféré demander à Eike Rathke (un des principaux dévelopeurs de Calc), quel pourrait être le meilleur moyen de faire cela. Eike m'a gentiment expliqué comment procéder différemment.

L'énumération dont nous avons besoin, est RID_SC_FUNCTION_DESCRIPTIONS1, et celle-ci est appelée en fonctionnement dans global.cxx, précisémenet dans sc/source/core/data/global.cxx ScFunctionList::ScFunctionList if (bSuppressed) ...

Les choix qui ont été faits, sont :

Réutiliser la méthode statique getUserLevel

Si mode expert -> ne rien faire

Si débutant -> pour chaque ressource, comparer l'Id avec celui de la liste "Débutant". Si non inclus -> supprimer l"item

Si moyen -> pour chaque ressource, comparer l'Id avec celui de la liste "Moyen". Si non inclus -> supprimer l"item

L'idée consiste à faire la chose suivante : dans le cas !bSuppressed, vérifier dans les préférences, afin de savoir si la fonction en cours d'énumération devra être visible ou non.

D'abord inclure les bons fichiers d'en-tête, afin d'utiliser l'interface qui permettra de retrouver les valeurs dont nous avons besoin dans le fichier Common.xcu

Index: sc/source/core/data/global.cxx

=
====================================================== --- sc/source/core/data/global.cxx	(revision 275641) +++ sc/source/core/data/global.cxx	(working copy) @@ -70,6 +70,7 @@ + @@ -91,13 +92,27 @@ +#ifdef OOo4Kids +#include "vcl/unohelp.hxx" +#include  +#include  +#include  +#include  +#include  + // ---
 * 1) include 
 * 2) include 
 * 1) include "global.hxx"
 * 2) include "scresid.hxx"
 * 3) include "autoform.hxx"
 * 1) include "scmod.hxx"
 * 2) include "appoptio.hxx"

Définir les bonnes constantes, afin d'améliorer la lisibilité

+#define SC_USER_LEVEL_BEGINNER     1 +#define SC_USER_LEVEL_AVERAGE      2 +#define SC_USER_LEVEL_EXPERT       3 +#endif + + ScDocShellRef*	ScGlobal::pDrawClipDocShellRef = NULL; SvxSearchItem*	ScGlobal::pSearchItem = NULL; ScAutoFormat*	ScGlobal::pAutoFormat = NULL;
 * 1) define CLIPST_AVAILABLE	0
 * 2) define CLIPST_CAPTURED		1
 * 3) define CLIPST_DELETE		2
 * 4) define CLIPST_DRAW			3

'''Utiliser le bon espace de nom. Les commentaires ci-dessous expliquent ce qui est concerné dans l'API.'''

@@ -147,6 +162,75 @@ static USHORT nPPTZoom = 0;		// ScreenZoom used to determine nScreenPPTX/Y +#ifdef OOo4Kids +using namespace ::com::sun::star::uno; // Reference +using namespace ::com::sun::star::lang; // XMultiServiceFactory +using namespace ::com::sun::star::beans; // PropertyValue +using namespace ::com::sun::star::container; // XNameAccess +using ::rtl::OUString;

Below, some helpers ( for readability )

+ +static const OUString sULConfigSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider" ) ); +static const OUString sULAccessSrvc( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) );

The getUserLevel (the same as the one used in the svx part

+ +static short getUserLevel +{ +   short dUserLevel = 1; // default is beginner +   try +   { +	// get service provider +       Reference< XMultiServiceFactory > xSMgr( vcl::unohelper::GetMultiServiceFactory ); +       // create configuration hierachical access name +       if( xSMgr.is ) +	{ +	   try +           { +                Reference< XMultiServiceFactory > xConfigProvider( +                    Reference< XMultiServiceFactory >( +                       xSMgr->createInstance( sULConfigSrvc ), +                       UNO_QUERY ) +                    ); +               if( xConfigProvider.is ) +               { +                    Sequence< Any > aArgs(1); +                   PropertyValue aVal; +                   aVal.Name = OUString( RTL_CONSTASCII_USTRINGPARAM( "nodepath" ) ); +                   aVal.Value <<= OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/Misc" ) ); +                   aArgs.getArray[0] <<= aVal; +                   Reference< XNameAccess > xConfigAccess( +                        Reference< XNameAccess >( +                           xConfigProvider->createInstanceWithArguments( sULAccessSrvc, aArgs ), UNO_QUERY ) +                        ); +                   if( xConfigAccess.is ) +                   { +                        try +                       { +                            short bValue = 1; +                           Any aAny = xConfigAccess->getByName( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UserLevel" ) ) ); +                           if( aAny >>= bValue ) +                               dUserLevel = bValue; +                       } +                        catch( NoSuchElementException& ) +                       { +                        } +                        catch( WrappedTargetException& ) +                       { +                        } +                    } +                } +            } +            catch( Exception& ) +           { +            } +        } +    } +    catch( WrappedTargetException& ) +   { +    } +    return dUserLevel; +} +#endif +

Then we add our code in ScFuncUtil constructor 

+ // ... oder so? BOOL bOderSo; @@ -1250,6 +1334,9 @@ 	ScFuncDesc*		pDesc	= NULL; xub_StrLen		nStrLen = 0; FuncCollection*	pFuncColl; +#ifdef OOo4Kids +   short   nLevel = getUserLevel; +#endif USHORT i,j; USHORT nDescBlock[] = {

'''As announced, the algorithm is :
 * If expert -> do nothing
 * If Beginner -> for every ressource, compare the Id with the one in the list "Beginner". If not listed-> delete
 * If Average -> for every ressource, compare the Id with the one in the list "Average". If not listed-> delete '''

@@ -1277,10 +1364,71 @@ 				pDesc = new ScFuncDesc; bool bSuppressed = false; ScFuncRes aSubRes( aRes, pDesc, bSuppressed); +#ifdef OOo4Kids +               bool bIsNotForThisLevel = false; + +               if ( nLevel != SC_USER_LEVEL_EXPERT ) +               { +                    if ( SC_USER_LEVEL_BEGINNER == nLevel ) +                   { +                        switch ( aRes.GetId ) +                       { +                            // FIXME : define the right list for Beginner +                           case SC_OPCODE_RANDOM: +                           case SC_OPCODE_MAX: +                           case SC_OPCODE_MIN: +                           case SC_OPCODE_AVERAGE: +                           case SC_OPCODE_PI: +                           case SC_OPCODE_MOD: +                           case SC_OPCODE_SUM: +                           case SC_OPCODE_PRODUCT: +                               break; +                           default: +                               bIsNotForThisLevel = true; +                               break; +                       } +                    } +                    else if (  SC_USER_LEVEL_AVERAGE == nLevel ) +                   { +                        switch ( aRes.GetId ) +                       { +                            // FIXME : define the right list for Average +                           case SC_OPCODE_RANDOM: +                           case SC_OPCODE_MAX: +                           case SC_OPCODE_MIN: +                           case SC_OPCODE_AVERAGE: +                           case SC_OPCODE_PI: +                           case SC_OPCODE_MOD: +                           case SC_OPCODE_SUM: +                           case SC_OPCODE_PRODUCT: +                           case SC_OPCODE_SIN: +                           case SC_OPCODE_COS: +                           case SC_OPCODE_DEG: +                           case SC_OPCODE_RAD: +                           case SC_OPCODE_ABS: +                           case SC_OPCODE_SQRT: +                           case SC_OPCODE_NOT: +                           case SC_OPCODE_AND: +                           case SC_OPCODE_OR: +                           case SC_OPCODE_PLUS_MINUS: +                           case SC_OPCODE_GGT: +                           case SC_OPCODE_KGV: +                           case SC_OPCODE_POWER: +                               break; +                           default: +                               bIsNotForThisLevel = true; +                               break; +                       } +                    } +                } +                 // Instead of dealing with this exceptional case at 1001 places // we simply don't add an entirely suppressed function to the // list and delete it. -               if (bSuppressed) +               if ( bSuppressed || bIsNotForThisLevel ) +#else +               if ( bSuppressed ) +#endif delete pDesc; else {

Important : do not forget to remove sc addins, excepted in expert mode

@@ -1387,10 +1538,14 @@ 	//	StarOne AddIns -	ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection; -	long nUnoCount = pUnoAddIns->GetFuncCount; -	for (long nFunc=0; nFuncGetFuncCount; +	   for (long nFunc=0; nFuncnFIndex = nNextId++; @@ -1403,7 +1558,10 @@ 		} 		else delete pDesc; +	   } +#ifdef OOo4Kids } +#endif }

FIXED, see below : cannot be changed without restart OOo, probably because the list is cached and not deleted (even when closing the doc ?)

The trick was to reset the function list when the box is closed. The next time it will be used, the UserLevel is read, and if it is different, a new function list is filled. Tested working OK

ScFunctionList* ScGlobal::GetStarCalcFunctionList {       ResetFunctionList; if ( !pStarCalcFunctionList ) pStarCalcFunctionList = new	ScFunctionList;
 * 1) ifdef OOo4Kids
 * 1) else
 * 1) endif

return pStarCalcFunctionList; }