CalcFunctionsList

From OOo4Kids

Jump to: navigation, search

OOo4Kids

Calc Functions list in the Wizard, depending on the User's Level



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

  • Under LGPL v3 license ( 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 3rd September 2009


Calc source code modifications

Module : sc

sc/source/ui/scfuncs.src  : does contain the complete list of the existing functions. There is an ExtraData field (0 for visible, 1 fot hidden), I used until now to hide the functions I didn't want to see listed.

But that's not easy to implement a mecanism doing the difference between beginner .. and so on from there, and I prefered ask Eike Rathke (one of the main Calc developers), what could be the best way to achieve that. Eike kindly explained me that I should proceed differently.

The enumeration, is RID_SC_FUNCTION_DESCRIPTIONS1 , and it is called at runtime in global.cxx, more precisely in sc/source/core/data/global.cxx ScFunctionList::ScFunctionList() if (bSuppressed) ...

The choice who has been made is :

re-use the static getUserLevel()

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

The idea is: in the !bSuppressed case, check for the prefs, to know whether the function currently checked is visible or not

TODO : define a list of the functions we'll have in the 3 levels.



First, include the right headers, for retrieving the value in the 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 @@
 #include <svtools/syslocale.hxx>
 #include <unotools/transliterationwrapper.hxx>
 
+
 #include "global.hxx"
 #include "scresid.hxx"
 #include "autoform.hxx"
@@ -91,13 +92,27 @@
 #include "scmod.hxx"
 #include "appoptio.hxx"
 
+#ifdef OOo4Kids
+#include "vcl/unohelp.hxx"
+#include <com/sun/star/container/XContentEnumerationAccess.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/lang/XComponent.hpp>
+
 // -----------------------------------------------------------------------


Define the constants, to improve the readability

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


Use the right namespace. Comments below give what is concerned.


@@ -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 export mode


@@ -1387,10 +1538,14 @@
 
 	//	StarOne AddIns
 
-	ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection();
-	long nUnoCount = pUnoAddIns->GetFuncCount();
-	for (long nFunc=0; nFunc<nUnoCount; nFunc++)
+#ifdef OOo4Kids
+        if ( SC_USER_LEVEL_EXPERT == nLevel )
 	{
+#endif
+	    ScUnoAddInCollection* pUnoAddIns = ScGlobal::GetAddInCollection();
+	    long nUnoCount = pUnoAddIns->GetFuncCount();
+	    for (long nFunc=0; nFunc<nUnoCount; nFunc++)
+	    {
 		pDesc = new ScFuncDesc;
 		pDesc->nFIndex = 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()
{
#ifdef OOo4Kids
        ResetFunctionList();
#else
	if ( !pStarCalcFunctionList )
#endif
		pStarCalcFunctionList = new	ScFunctionList;

	return pStarCalcFunctionList;
}
Personal tools