[Libreoffice-commits] core.git: wizards/source

Jean-Pierre Ledure (via logerrit) logerrit at kemper.freedesktop.org
Tue Apr 20 08:21:34 UTC 2021


 wizards/source/scriptforge/SF_Exception.xba      |    8 
 wizards/source/scriptforge/SF_PythonHelper.xba   |    2 
 wizards/source/scriptforge/SF_Root.xba           |   10 
 wizards/source/scriptforge/SF_UI.xba             |   26 +
 wizards/source/scriptforge/python/scriptforge.py |  431 +++++++++++++++--------
 wizards/source/sfdialogs/SF_Dialog.xba           |    5 
 wizards/source/sfdialogs/SF_DialogControl.xba    |   84 +++-
 wizards/source/sfdialogs/SF_Register.xba         |   47 +-
 8 files changed, 413 insertions(+), 200 deletions(-)

New commits:
commit 49f6c9d8c132f250b34191b992cede24672a8c0e
Author:     Jean-Pierre Ledure <jp at ledure.be>
AuthorDate: Mon Apr 19 16:51:31 2021 +0200
Commit:     Jean-Pierre Ledure <jp at ledure.be>
CommitDate: Tue Apr 20 10:20:59 2021 +0200

    ScriptForge - (scriptforge.py) Dialog and DialogControl classes
    
    New classes to manage Basic dialogs and their controls from
    Python.
    
    The use of UNO interfaces has been reviewed in Basic:
     replacement of
      CreateUnoDialog()
    by
      XDialogProvider.createDialog()
    The latter allows to run dialogs in non-modal mode.
    
    SF_UI.ShowProgressBar() and SF_Console() have been reviewed
    to incorporate the XSCRIPTCONTEXT shipped with Python
    Now the console and the progress bar are able to run
    in non-modal mode.
    
    Change-Id: I49b09aa41ee6f50e6d205f44fc329f91bce76beb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114296
    Tested-by: Jean-Pierre Ledure <jp at ledure.be>
    Tested-by: Jenkins
    Reviewed-by: Jean-Pierre Ledure <jp at ledure.be>

diff --git a/wizards/source/scriptforge/SF_Exception.xba b/wizards/source/scriptforge/SF_Exception.xba
index 650f14164a02..aae74fe98d42 100644
--- a/wizards/source/scriptforge/SF_Exception.xba
+++ b/wizards/source/scriptforge/SF_Exception.xba
@@ -243,11 +243,14 @@ Catch:
 End Sub    '   ScriptForge.SF_Exception.Clear
 
 REM -----------------------------------------------------------------------------
-Public Sub Console(Optional ByVal Modal As Variant)
+Public Sub Console(Optional ByVal Modal As Variant, _
+					Optional ByRef _Context As Variant _
+					)
 '''	Display the console messages in a modal or non-modal dialog
 '''	If the dialog is already active, when non-modal, it is brought to front
 '''	Args:
 '''		Modal: Boolean. Default = True
+'''		_Context: From Python, the XComponentXontext (FOR INTERNAL USE ONLY)
 '''	Example:
 '''		SF_Exception.Console()
 
@@ -262,6 +265,7 @@ Const cstSubArgs = "[Modal=True]"
 
 Check:
 	If IsMissing(Modal) Or IsEmpty(Modal) Then Modal = True
+	If IsMissing(_Context) Or IsEmpty(_Context) Then _Context = Nothing
 	If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
 		If Not SF_Utils._Validate(Modal, "Modal", V_BOOLEAN) Then GoTo Finally
 	End If
@@ -278,7 +282,7 @@ Try:
 			'	The dual modes (modal and non-modal) require to have 2 close buttons o/w only 1 is visible
 			'		- a usual OK button
 			'		- a Default button triggering the Close action
-			Set .ConsoleDialog = CreateScriptService("SFDialogs.Dialog", "GlobalScope", "ScriptForge", "dlgConsole")
+			Set .ConsoleDialog = CreateScriptService("SFDialogs.Dialog", "GlobalScope", "ScriptForge", "dlgConsole", _Context)
 			'	Setup labels and visibility
 			sClose = .Interface.GetText("CLOSEBUTTON")
 			Set oModalBtn = .ConsoleDialog.Controls("CloseModalButton")
diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba b/wizards/source/scriptforge/SF_PythonHelper.xba
index 69306d1f8884..b083e86b1db4 100644
--- a/wizards/source/scriptforge/SF_PythonHelper.xba
+++ b/wizards/source/scriptforge/SF_PythonHelper.xba
@@ -710,6 +710,8 @@ Try:
 				Select Case sServiceName
 					Case "SFDatabases.Database"
 						If Script = "GetRows" Then		vReturn = vBasicObject.GetRows(vArgs(0), vArgs(1), vArgs(2), vArgs(3))
+					Case "SFDialogs.Dialog"
+						If Script = "Controls" Then		vReturn = vBasicObject.Controls(vArgs(0))
 					Case "SFDocuments.Document"
 						If Script = "Forms" Then		vReturn = vBasicObject.Forms(vArgs(0))
 					Case "SFDocuments.Base"
diff --git a/wizards/source/scriptforge/SF_Root.xba b/wizards/source/scriptforge/SF_Root.xba
index 7ba27eb3c4ec..7f07109dc055 100644
--- a/wizards/source/scriptforge/SF_Root.xba
+++ b/wizards/source/scriptforge/SF_Root.xba
@@ -38,6 +38,12 @@ Private DisplayEnabled		As Boolean	' When True, display of console or error
 Private StopWhenError		As Boolean	' When True, process stops after error > "WARNING"
 Private DebugMode			As Boolean	' When True, log enter/exit each official Sub
 
+'	Progress and status bars
+Private ProgressBarDialog	As Object	' SFDialogs.Dialog object
+Private ProgressBarText		As Object	' SFDialogs.DialogControl object
+Private ProgressBarBar		As Object	' SFDialogs.DialogControl object
+Private Statusbar			As Object
+
 '	Services management
 Private ServicesList		As Variant	' Dictionary of provided services
 
@@ -93,6 +99,10 @@ Private Sub Class_Initialize()
 	DisplayEnabled = True
 	StopWhenError = True
 	DebugMode = False
+	Set ProgressBarDialog = Nothing
+	Set ProgressBarText = Nothing
+	Set progressBarBar = Nothing
+	Set Statusbar = Nothing
 	ServicesList = Empty
 	Set FunctionAccess = Nothing
 	Set PathSettings = Nothing
diff --git a/wizards/source/scriptforge/SF_UI.xba b/wizards/source/scriptforge/SF_UI.xba
index 38bcb7645b4c..c865c703e8b4 100644
--- a/wizards/source/scriptforge/SF_UI.xba
+++ b/wizards/source/scriptforge/SF_UI.xba
@@ -907,7 +907,7 @@ Public Sub SetStatusbar(Optional ByVal Text As Variant _
 
 Dim oComp As Object
 Dim oControl As Object
-Static oStatusbar As Object
+Dim oStatusbar As Object
 Const cstThisSub = "UI.SetStatusbar"
 Const cstSubArgs = "[Text], [Percentage]"
 
@@ -922,6 +922,7 @@ Check:
 	End If
 
 Try:
+	Set oStatusbar = _SF_.Statusbar
 	With oStatusbar
 		If IsNull(oStatusbar) Then		'	Initial call
 			Set oComp = StarDesktop.CurrentComponent
@@ -939,6 +940,7 @@ Try:
 		If Not IsNull(oStatusbar) Then
 			If Len(Text) = 0 And Percentage = -1 Then
 				.end()
+				Set oStatusbar = Nothing
 			Else
 				If Len(Text) > 0 Then .setText(Text)
 				If Percentage >= 0 And Percentage <= 100 Then .setValue(Percentage)
@@ -947,6 +949,7 @@ Try:
 	End With
 
 Finally:
+	Set _SF_.Statusbar = oStatusbar
 	SF_Utils._ExitFunction(cstThisSub)
 	Exit Sub
 Catch:
@@ -957,6 +960,7 @@ REM ----------------------------------------------------------------------------
 Public Sub ShowProgressBar(Optional Title As Variant _
 					, Optional ByVal Text As Variant _
 					, Optional ByVal Percentage As Variant _
+					, Optional ByRef _Context As Variant _
 					)
 ''' Display a non-modal dialog box. Specify its title, an explicatory text and the progress on a progressbar
 '''	A call without arguments erases the progress bar dialog.
@@ -965,6 +969,7 @@ Public Sub ShowProgressBar(Optional Title As Variant _
 '''		Title: the title appearing on top of the dialog box (Default = "ScriptForge")
 '''		Text: the optional text to be displayed above the progress bar (default = zero-length string)
 '''		Percentage: the degree of progress between 0 and 100. Default = 0
+'''		_Context: from Python, the XComponentXontext (FOR INTERNAL USE ONLY)
 '''	Examples:
 '''		Dim i As Integer
 '''			For i = 0 To 100
@@ -974,9 +979,9 @@ Public Sub ShowProgressBar(Optional Title As Variant _
 '''			ui.ShowProgressBar
 
 Dim bFirstCall As Boolean				'	True at first invocation of method
-Static oDialog As Object				'	SFDialogs.Dialog object
-Static oFixedText As Object				'	SFDialogs.DialogControl object
-Static oProgressBar As Object			'	SFDialogs.DialogControl object
+Dim oDialog As Object					'	SFDialogs.Dialog object
+Dim oFixedText As Object				'	SFDialogs.DialogControl object
+Dim oProgressBar As Object				'	SFDialogs.DialogControl object
 Dim sTitle As String					'	Alias of Title
 Const cstThisSub = "UI.ShowProgressBar"
 Const cstSubArgs = "[Title], [Text], [Percentage]"
@@ -987,6 +992,7 @@ Check:
 	If IsMissing(Title) Or IsEmpty(Title) Then Title = ""
 	If IsMissing(Text) Or IsEmpty(Text) Then Text = ""
 	If IsMissing(Percentage) Or IsEmpty(Percentage) Then Percentage = -1
+	If IsMissing(_Context) Or IsEmpty(_Context) Then _Context = Nothing
 	If SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
 		If Not SF_Utils._Validate(Title, "Title", V_STRING) Then GoTo Finally
 		If Not SF_Utils._Validate(Text, "Text", V_STRING) Then GoTo Finally
@@ -994,10 +1000,15 @@ Check:
 	End If
 
 Try:
+	With _SF_
+		Set oDialog = .ProgressBarDialog
+		Set oFixedText = .ProgressBarText
+		Set oProgressBar = .ProgressBarBar
+	End With
 	With oDialog
 		bFirstCall = ( IsNull(oDialog) )
 		If Not bFirstCall Then bFirstCall = Not ._IsStillAlive(False)	'	False to not raise an error
-		If bFirstCall Then Set oDialog = CreateScriptService("SFDialogs.Dialog", "GlobalScope", "ScriptForge", "dlgProgress")
+		If bFirstCall Then Set oDialog = CreateScriptService("SFDialogs.Dialog", "GlobalScope", "ScriptForge", "dlgProgress", _Context)
 
 		If Not IsNull(oDialog) Then
 			If Len(Title) = 0 And Len(Text) = 0 And Percentage = -1 Then
@@ -1017,6 +1028,11 @@ Try:
 	End With
 
 Finally:
+	With _SF_
+		Set .ProgressBarDialog = oDialog
+		Set .ProgressBarText = oFixedText
+		Set .ProgressBarBar = oProgressBar
+	End With
 	SF_Utils._ExitFunction(cstThisSub)
 	Exit Sub
 Catch:
diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py
index d722b3ca2f1a..94fe0fe5a7bd 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -315,8 +315,8 @@ class ScriptForge(object, metaclass = _Singleton):
             if isinstance(returntuple[cstValue], uno.ByteSequence):
                 return ()
         elif returntuple[cstVarType] == ScriptForge.V_DATE:
+            dat = None
             try:    # Anticipate fromisoformat('00:00:00') and alike
-                dat = None
                 dat = datetime.datetime.fromisoformat(returntuple[cstValue])
             finally:
                 return dat
@@ -528,10 +528,10 @@ class SFServices(object):
     def Dispose(self):
         if self.serviceimplementation == 'basic':
             if self.objectreference >= len(ScriptForge.servicesmodules):    # Do not dispose predefined module objects
-                self.Execute(self.vbMethod, 'Dispose')
+                self.ExecMethod(self.vbMethod, 'Dispose')
                 self.objectreference = -1
 
-    def Execute(self, flags = 0, methodname = '', *args):
+    def ExecMethod(self, flags = 0, methodname = '', *args):
         if flags == 0:
             flags = self.vbMethod
         if len(methodname) > 0:
@@ -558,6 +558,8 @@ class SFServices(object):
             Set the given property to a new value in the Basic world
             """
         if self.serviceimplementation == 'basic':
+            if isinstance(value, datetime.datetime):
+                value = value.isoformat()
             return self.EXEC(self.objectreference, self.vbLet + self.flgDateArg, propertyname, value)
 
 
@@ -588,7 +590,8 @@ class SFScriptForge:
                 Difference with the Basic version: dates are returned in their iso format,
                 not as any of the datetime objects.
                 """
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'ImportFromCSVFile', filename, delimiter, dateformat)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'ImportFromCSVFile',
+                                   filename, delimiter, dateformat)
 
     # #########################################################################
     # SF_Basic CLASS
@@ -840,14 +843,14 @@ class SFScriptForge:
         serviceproperties = dict()
 
         def Console(self, modal = True):
-            # Modal is always True in Python: Basic execution lasts only the time to display the box
-            return self.Execute(self.vbMethod, 'Console', True)
+            # From Python, the current XComponentContext must be added as last argument
+            return self.ExecMethod(self.vbMethod, 'Console', modal, ScriptForge.componentcontext)
 
         def ConsoleClear(self, keep = 0):
-            return self.Execute(self.vbMethod, 'ConsoleClear', keep)
+            return self.ExecMethod(self.vbMethod, 'ConsoleClear', keep)
 
         def ConsoleToFile(self, filename):
-            return self.Execute(self.vbMethod, 'ConsoleToFile', filename)
+            return self.ExecMethod(self.vbMethod, 'ConsoleToFile', filename)
 
         def DebugDisplay(self, *args):
             # Arguments are concatenated in a single string similar to what the Python print() function would produce
@@ -859,7 +862,7 @@ class SFScriptForge:
         def DebugPrint(self, *args):
             # Arguments are concatenated in a single string similar to what the Python print() function would produce
             param = '\t'.join(list(map(repr, args))).expandtabs(tabsize = 4)
-            return self.Execute(self.vbMethod, 'DebugPrint', param)
+            return self.ExecMethod(self.vbMethod, 'DebugPrint', param)
 
         def RaiseFatal(self, errorcode, *args):
             """
@@ -870,6 +873,16 @@ class SFScriptForge:
             # Direct call because RaiseFatal forces an execution stop in Basic
             return self.SIMPLEEXEC('SF_Exception.RaiseFatal', errorcode, *args)
 
+        def _RaiseFatal(self, sub, subargs, errorcode, *args):
+            """
+                Wrapper of RaiseFatal(). Includes method and syntax of the failed Python routine
+                to simulate the exact behaviour of the Basic RaiseFatal() method
+                For INTERNAL USE only
+                """
+            ScriptForge.InvokeSimpleScript('ScriptForge.SF_Utils._EnterFunction', sub, subargs)
+            self.RaiseFatal(errorcode, *args)
+            raise RuntimeError("The execution of the method '" + sub.split('.')[-1] + "' failed. Execution stops.")
+
     # #########################################################################
     # SF_FileSystem CLASS
     # #########################################################################
@@ -890,7 +903,7 @@ class SFScriptForge:
         ForReading, ForWriting, ForAppending = 1, 2, 8
 
         def BuildPath(self, foldername, name):
-            return self.Execute(self.vbMethod, 'BuildPath', foldername, name)
+            return self.ExecMethod(self.vbMethod, 'BuildPath', foldername, name)
 
         def CompareFiles(self, filename1, filename2, comparecontents = False):
             py = ScriptForge.pythonhelpermodule + '$' + '_SF_FileSystem__CompareFiles'
@@ -902,37 +915,37 @@ class SFScriptForge:
                 return False
 
         def CopyFile(self, source, destination, overwrite = True):
-            return self.Execute(self.vbMethod, 'CopyFile', source, destination, overwrite)
+            return self.ExecMethod(self.vbMethod, 'CopyFile', source, destination, overwrite)
 
         def CopyFolder(self, source, destination, overwrite = True):
-            return self.Execute(self.vbMethod, 'CopyFolder', source, destination, overwrite)
+            return self.ExecMethod(self.vbMethod, 'CopyFolder', source, destination, overwrite)
 
         def CreateFolder(self, foldername):
-            return self.Execute(self.vbMethod, 'CreateFolder', foldername)
+            return self.ExecMethod(self.vbMethod, 'CreateFolder', foldername)
 
         def CreateTextFile(self, filename, overwrite = True, encoding = 'UTF-8'):
-            return self.Execute(self.vbMethod, 'CreateTextFile', filename, overwrite, encoding)
+            return self.ExecMethod(self.vbMethod, 'CreateTextFile', filename, overwrite, encoding)
 
         def DeleteFile(self, filename):
-            return self.Execute(self.vbMethod, 'DeleteFile', filename)
+            return self.ExecMethod(self.vbMethod, 'DeleteFile', filename)
 
         def DeleteFolder(self, foldername):
-            return self.Execute(self.vbMethod, 'DeleteFolder', foldername)
+            return self.ExecMethod(self.vbMethod, 'DeleteFolder', foldername)
 
         def FileExists(self, filename):
-            return self.Execute(self.vbMethod, 'FileExists', filename)
+            return self.ExecMethod(self.vbMethod, 'FileExists', filename)
 
         def Files(self, foldername, filter = ''):
-            return self.Execute(self.vbMethod, 'Files', foldername, filter)
+            return self.ExecMethod(self.vbMethod, 'Files', foldername, filter)
 
         def FolderExists(self, foldername):
-            return self.Execute(self.vbMethod, 'FolderExists', foldername)
+            return self.ExecMethod(self.vbMethod, 'FolderExists', foldername)
 
         def GetBaseName(self, filename):
-            return self.Execute(self.vbMethod, 'GetBaseName', filename)
+            return self.ExecMethod(self.vbMethod, 'GetBaseName', filename)
 
         def GetExtension(self, filename):
-            return self.Execute(self.vbMethod, 'GetExtension', filename)
+            return self.ExecMethod(self.vbMethod, 'GetExtension', filename)
 
         def GetFileLen(self, filename):
             py = ScriptForge.pythonhelpermodule + '$' + '_SF_FileSystem__GetFilelen'
@@ -943,16 +956,16 @@ class SFScriptForge:
                 return 0
 
         def GetFileModified(self, filename):
-            return self.Execute(self.vbMethod + self.flgDateRet, 'GetFileModified', filename)
+            return self.ExecMethod(self.vbMethod + self.flgDateRet, 'GetFileModified', filename)
 
         def GetName(self, filename):
-            return self.Execute(self.vbMethod, 'GetName', filename)
+            return self.ExecMethod(self.vbMethod, 'GetName', filename)
 
         def GetParentFolderName(self, filename):
-            return self.Execute(self.vbMethod, 'GetParentFolderName', filename)
+            return self.ExecMethod(self.vbMethod, 'GetParentFolderName', filename)
 
         def GetTempName(self):
-            return self.Execute(self.vbMethod, 'GetTempName')
+            return self.ExecMethod(self.vbMethod, 'GetTempName')
 
         def HashFile(self, filename, algorithm):
             py = ScriptForge.pythonhelpermodule + '$' + '_SF_FileSystem__HashFile'
@@ -963,22 +976,22 @@ class SFScriptForge:
                 return ''
 
         def MoveFile(self, source, destination):
-            return self.Execute(self.vbMethod, 'MoveFile', source, destination)
+            return self.ExecMethod(self.vbMethod, 'MoveFile', source, destination)
 
         def MoveFolder(self, source, destination):
-            return self.Execute(self.vbMethod, 'MoveFolder', source, destination)
+            return self.ExecMethod(self.vbMethod, 'MoveFolder', source, destination)
 
         def OpenTextFile(self, filename, iomode = 1, create = False, encoding = 'UTF-8'):
-            return self.Execute(self.vbMethod, 'OpenTextFile', filename, iomode, create, encoding)
+            return self.ExecMethod(self.vbMethod, 'OpenTextFile', filename, iomode, create, encoding)
 
         def PickFile(self, defaultfile = ScriptForge.cstSymEmpty, mode = 'OPEN', filter = ''):
-            return self.Execute(self.vbMethod, 'PickFile', defaultfile, mode, filter)
+            return self.ExecMethod(self.vbMethod, 'PickFile', defaultfile, mode, filter)
 
         def PickFolder(self, defaultfolder = ScriptForge.cstSymEmpty, freetext = ''):
-            return self.Execute(self.vbMethod, 'PickFolder', defaultfolder, freetext)
+            return self.ExecMethod(self.vbMethod, 'PickFolder', defaultfolder, freetext)
 
         def SubFolders(self, foldername, filter = ''):
-            return self.Execute(self.vbMethod, 'SubFolders', foldername, filter)
+            return self.ExecMethod(self.vbMethod, 'SubFolders', foldername, filter)
 
         def _ConvertFromUrl(self, filename):
             # Alias for same function in FileSystem Basic module
@@ -1002,13 +1015,13 @@ class SFScriptForge:
         serviceproperties = dict(Folder = False, Languages = False, Locale = False)
 
         def AddText(self, context = '', msgid = '', comment = ''):
-            return self.Execute(self.vbMethod, 'AddText', context, msgid, comment)
+            return self.ExecMethod(self.vbMethod, 'AddText', context, msgid, comment)
 
         def ExportToPOTFile(self, filename, header = '', encoding= 'UTF-8'):
-            return self.Execute(self.vbMethod, 'ExportToPOTFile', filename, header, encoding)
+            return self.ExecMethod(self.vbMethod, 'ExportToPOTFile', filename, header, encoding)
 
         def GetText(self, msgid, *args):
-            return self.Execute(self.vbMethod, 'GetText', msgid, *args)
+            return self.ExecMethod(self.vbMethod, 'GetText', msgid, *args)
         _ = GetText
 
     # #########################################################################
@@ -1122,32 +1135,32 @@ class SFScriptForge:
             return self.SIMPLEEXEC(scope + ':' + script, *args)
 
         def HasUnoMethod(self, unoobject, methodname):
-            return self.Execute(self.vbMethod, 'HasUnoMethod', unoobject, methodname)
+            return self.ExecMethod(self.vbMethod, 'HasUnoMethod', unoobject, methodname)
 
         def HasUnoProperty(self, unoobject, propertyname):
-            return self.Execute(self.vbMethod, 'HasUnoProperty', unoobject, propertyname)
+            return self.ExecMethod(self.vbMethod, 'HasUnoProperty', unoobject, propertyname)
 
         def OpenURLInBrowser(self, url):
             py = ScriptForge.pythonhelpermodule + '$' + '_SF_Session__OpenURLInBrowser'
             return self.SIMPLEEXEC(py, url)
 
         def RunApplication(self, command, parameters):
-            return self.Execute(self.vbMethod, 'RunApplication', command, parameters)
+            return self.ExecMethod(self.vbMethod, 'RunApplication', command, parameters)
 
         def SendMail(self, recipient, cc = '', bcc = '', subject = '', body = '', filenames = '', editmessage = True):
-            return self.Execute(self.vbMethod, 'SendMail', recipient, cc, bcc, subject, body, filenames, editmessage)
+            return self.ExecMethod(self.vbMethod, 'SendMail', recipient, cc, bcc, subject, body, filenames, editmessage)
 
         def UnoObjectType(self, unoobject):
-            return self.Execute(self.vbMethod, 'UnoObjectType', unoobject)
+            return self.ExecMethod(self.vbMethod, 'UnoObjectType', unoobject)
 
         def UnoMethods(self, unoobject):
-            return self.Execute(self.vbMethod, 'UnoMethods', unoobject)
+            return self.ExecMethod(self.vbMethod, 'UnoMethods', unoobject)
 
         def UnoProperties(self, unoobject):
-            return self.Execute(self.vbMethod, 'UnoProperties', unoobject)
+            return self.ExecMethod(self.vbMethod, 'UnoProperties', unoobject)
 
         def WebService(self, uri):
-            return self.Execute(self.vbMethod, 'WebService', uri)
+            return self.ExecMethod(self.vbMethod, 'WebService', uri)
 
     # #########################################################################
     # SF_String CLASS
@@ -1169,34 +1182,34 @@ class SFScriptForge:
             return self.SIMPLEEXEC(py, inputstr, algorithm.lower())
 
         def IsADate(self, inputstr, dateformat = 'YYYY-MM-DD'):
-            return self.Execute(self.vbMethod, 'IsADate', inputstr, dateformat)
+            return self.ExecMethod(self.vbMethod, 'IsADate', inputstr, dateformat)
 
         def IsEmail(self, inputstr):
-            return self.Execute(self.vbMethod, 'IsEmail', inputstr)
+            return self.ExecMethod(self.vbMethod, 'IsEmail', inputstr)
 
         def IsFileName(self, inputstr, osname = ScriptForge.cstSymEmpty):
-            return self.Execute(self.vbMethod, 'IsFileName', inputstr, osname)
+            return self.ExecMethod(self.vbMethod, 'IsFileName', inputstr, osname)
 
         def IsIBAN(self, inputstr):
-            return self.Execute(self.vbMethod, 'IsIBAN', inputstr)
+            return self.ExecMethod(self.vbMethod, 'IsIBAN', inputstr)
 
         def IsIPv4(self, inputstr):
-            return self.Execute(self.vbMethod, 'IsIPv4', inputstr)
+            return self.ExecMethod(self.vbMethod, 'IsIPv4', inputstr)
 
         def IsLike(self, inputstr, pattern, casesensitive = False):
-            return self.Execute(self.vbMethod, 'IsLike', inputstr, pattern, casesensitive)
+            return self.ExecMethod(self.vbMethod, 'IsLike', inputstr, pattern, casesensitive)
 
         def IsSheetName(self, inputstr):
-            return self.Execute(self.vbMethod, 'IsSheetName', inputstr)
+            return self.ExecMethod(self.vbMethod, 'IsSheetName', inputstr)
 
         def IsUrl(self, inputstr):
-            return self.Execute(self.vbMethod, 'IsUrl', inputstr)
+            return self.ExecMethod(self.vbMethod, 'IsUrl', inputstr)
 
         def SplitNotQuoted(self, inputstr, delimiter = ' ', occurrences = 0, quotechar = '"'):
-            return self.Execute(self.vbMethod, 'SplitNotQuoted', inputstr, delimiter, occurrences, quotechar)
+            return self.ExecMethod(self.vbMethod, 'SplitNotQuoted', inputstr, delimiter, occurrences, quotechar)
 
         def Wrap(self, inputstr, width = 70, tabsize = 8):
-            return self.Execute(self.vbMethod, 'Wrap', inputstr, width, tabsize)
+            return self.ExecMethod(self.vbMethod, 'Wrap', inputstr, width, tabsize)
 
     # #########################################################################
     # SF_TextStream CLASS
@@ -1224,22 +1237,22 @@ class SFScriptForge:
         line = Line
 
         def CloseFile(self):
-            return self.Execute(self.vbMethod, 'CloseFile')
+            return self.ExecMethod(self.vbMethod, 'CloseFile')
 
         def ReadAll(self):
-            return self.Execute(self.vbMethod, 'ReadAll')
+            return self.ExecMethod(self.vbMethod, 'ReadAll')
 
         def ReadLine(self):
-            return self.Execute(self.vbMethod, 'ReadLine')
+            return self.ExecMethod(self.vbMethod, 'ReadLine')
 
         def SkipLine(self):
-            return self.Execute(self.vbMethod, 'SkipLine')
+            return self.ExecMethod(self.vbMethod, 'SkipLine')
 
         def WriteBlankLines(self, lines):
-            return self.Execute(self.vbMethod, 'WriteBlankLines', lines)
+            return self.ExecMethod(self.vbMethod, 'WriteBlankLines', lines)
 
         def WriteLine(self, line):
-            return self.Execute(self.vbMethod, 'WriteLine', line)
+            return self.ExecMethod(self.vbMethod, 'WriteLine', line)
 
     # #########################################################################
     # SF_Timer CLASS
@@ -1258,19 +1271,19 @@ class SFScriptForge:
         forceGetProperty = True
 
         def Continue(self):
-            return self.Execute(self.vbMethod, 'Continue')
+            return self.ExecMethod(self.vbMethod, 'Continue')
 
         def Restart(self):
-            return self.Execute(self.vbMethod, 'Restart')
+            return self.ExecMethod(self.vbMethod, 'Restart')
 
         def Start(self):
-            return self.Execute(self.vbMethod, 'Start')
+            return self.ExecMethod(self.vbMethod, 'Start')
 
         def Suspend(self):
-            return self.Execute(self.vbMethod, 'Suspend')
+            return self.ExecMethod(self.vbMethod, 'Suspend')
 
         def Terminate(self):
-            return self.Execute(self.vbMethod, 'Terminate')
+            return self.ExecMethod(self.vbMethod, 'Terminate')
 
     # #########################################################################
     # SF_UI CLASS
@@ -1298,47 +1311,50 @@ class SFScriptForge:
 
         @property
         def ActiveWindow(self):
-            return self.Execute(self.vbMethod, 'ActiveWindow')
+            return self.ExecMethod(self.vbMethod, 'ActiveWindow')
 
         def Activate(self, windowname = ''):
-            return self.Execute(self.vbMethod, 'Activate', windowname)
+            return self.ExecMethod(self.vbMethod, 'Activate', windowname)
 
         def CreateBaseDocument(self, filename, embeddeddatabase = 'HSQLDB', registrationname = ''):
-            return self.Execute(self.vbMethod, 'CreateBaseDocument', filename, embeddeddatabase, registrationname)
+            return self.ExecMethod(self.vbMethod, 'CreateBaseDocument', filename, embeddeddatabase, registrationname)
 
         def CreateDocument(self, documenttype = '', templatefile = '', hidden = False):
-            return self.Execute(self.vbMethod, 'CreateDocument', documenttype, templatefile, hidden)
+            return self.ExecMethod(self.vbMethod, 'CreateDocument', documenttype, templatefile, hidden)
 
         def Documents(self):
-            return self.Execute(self.vbMethod, 'Documents')
+            return self.ExecMethod(self.vbMethod, 'Documents')
 
         def GetDocument(self, windowname = ''):
-            return self.Execute(self.vbMethod, 'GetDocument', windowname)
+            return self.ExecMethod(self.vbMethod, 'GetDocument', windowname)
 
         def Maximize(self, windowname = ''):
-            return self.Execute(self.vbMethod, 'Maximize', windowname)
+            return self.ExecMethod(self.vbMethod, 'Maximize', windowname)
 
         def Minimize(self, windowname = ''):
-            return self.Execute(self.vbMethod, 'Minimize', windowname)
+            return self.ExecMethod(self.vbMethod, 'Minimize', windowname)
 
         def OpenBaseDocument(self, filename = '', registrationname = '', macroexecution = MACROEXECNORMAL):
-            return self.Execute(self.vbMethod, 'OpenBaseDocument', filename, registrationname, macroexecution)
+            return self.ExecMethod(self.vbMethod, 'OpenBaseDocument', filename, registrationname, macroexecution)
 
         def OpenDocument(self, filename, password = '', readonly = False, hidden = False,
                          macroexecution = MACROEXECNORMAL, filtername = '', filteroptions = ''):
-            return self.Execute(self.vbMethod, 'OpenDocument', filename, password, readonly, hidden,
-                                macroexecution, filtername, filteroptions)
+            return self.ExecMethod(self.vbMethod, 'OpenDocument', filename, password, readonly, hidden,
+                                   macroexecution, filtername, filteroptions)
 
         def Resize(self, left = -1, top = -1, width = -1, height = -1):
-            return self.Execute(self.vbMethod, 'Resize', left, top, width, height)
+            return self.ExecMethod(self.vbMethod, 'Resize', left, top, width, height)
 
         def SetStatusbar(self, text = '', percentage = -1):
-            return self.Execute(self.vbMethod, 'SetStatusbar', text, percentage)
+            return self.ExecMethod(self.vbMethod, 'SetStatusbar', text, percentage)
 
-        # ShowProgressBar - not supported in Python
+        def ShowProgressBar(self, title = '', text = '', percentage = -1):
+            # From Python, the current XComponentContext must be added as last argument
+            return self.ExecMethod(self.vbMethod, 'ShowProgressBar', title, text, percentage,
+                                   ScriptForge.componentcontext)
 
         def WindowExists(self, windowname):
-            return self.Execute(self.vbMethod, 'WindowExists', windowname)
+            return self.ExecMethod(self.vbMethod, 'WindowExists', windowname)
 
 
 # #####################################################################################################################
@@ -1370,31 +1386,141 @@ class SFDatabases:
         serviceproperties = dict(Queries = False, Tables = False, XConnection = False, XMetaData = False)
 
         def CloseDatabase(self):
-            return self.Execute(self.vbMethod, 'CloseDatabase')
+            return self.ExecMethod(self.vbMethod, 'CloseDatabase')
 
         def DAvg(self, expression, tablename, criteria = ''):
-            return self.Execute(self.vbMethod, 'DAvg', expression, tablename, criteria)
+            return self.ExecMethod(self.vbMethod, 'DAvg', expression, tablename, criteria)
 
         def DCount(self, expression, tablename, criteria = ''):
-            return self.Execute(self.vbMethod, 'DCount', expression, tablename, criteria)
+            return self.ExecMethod(self.vbMethod, 'DCount', expression, tablename, criteria)
 
         def DLookup(self, expression, tablename, criteria = '', orderclause = ''):
-            return self.Execute(self.vbMethod, 'DLookup', expression, tablename, criteria, orderclause)
+            return self.ExecMethod(self.vbMethod, 'DLookup', expression, tablename, criteria, orderclause)
 
         def DMax(self, expression, tablename, criteria = ''):
-            return self.Execute(self.vbMethod, 'DMax', expression, tablename, criteria)
+            return self.ExecMethod(self.vbMethod, 'DMax', expression, tablename, criteria)
 
         def DMin(self, expression, tablename, criteria = ''):
-            return self.Execute(self.vbMethod, 'DMin', expression, tablename, criteria)
+            return self.ExecMethod(self.vbMethod, 'DMin', expression, tablename, criteria)
 
         def DSum(self, expression, tablename, criteria = ''):
-            return self.Execute(self.vbMethod, 'DSum', expression, tablename, criteria)
+            return self.ExecMethod(self.vbMethod, 'DSum', expression, tablename, criteria)
 
         def GetRows(self, sqlcommand, directsql = False, header = False, maxrows = 0):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'GetRows', sqlcommand, directsql, header, maxrows)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetRows', sqlcommand, directsql, header, maxrows)
 
         def RunSql(self, sqlcommand, directsql = False):
-            return self.Execute(self.vbMethod, 'RunSql', sqlcommand, directsql)
+            return self.ExecMethod(self.vbMethod, 'RunSql', sqlcommand, directsql)
+
+
+# #####################################################################################################################
+#                       SFDialogs CLASS    (alias of SFDialogs Basic library)                                       ###
+# #####################################################################################################################
+class SFDialogs:
+    """
+        The SFDialogs class manages dialogs defined with the Basic IDE
+        """
+    pass
+
+    # #########################################################################
+    # SF_Dialog CLASS
+    # #########################################################################
+    class SF_Dialog(SFServices):
+        """
+            Each instance of the current class represents a single dialog box displayed to the user.
+            From a Python script, a dialog box can be displayed in modal mode only.
+            In modal mode, the box is displayed and the execution of the macro process is suspended
+            until one of the OK or Cancel buttons is pressed. In the meantime, other user actions
+            executed on the box can trigger specific actions.
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFDialogs.Dialog'
+        servicesynonyms = ('dialog', 'sfdialogs.dialog')
+        serviceproperties = dict(Caption = True, Height = True, Modal = False, Name = False,
+                                 OnFocusGained = False, OnFocusLost = False, OnKeyPressed = False,
+                                 OnKeyReleased = False, OnMouseDragged = False, OnMouseEntered = False,
+                                 OnMouseExited = False, OnMouseMoved = False, OnMousePressed = False,
+                                 OnMouseReleased = False,
+                                 Page = True, Visible = True, Width = True, XDialogModel = False, XDialogView = False)
+
+        @classmethod
+        def PreProcessArgs(cls, args):
+            """
+                Review the arguments of the creation of the Basic service (must be a class method)
+                Add the XComponentContext as last argument
+                """
+            newargs = (*args, ScriptForge.componentcontext)
+            return newargs
+
+        def Activate(self):
+            return self.ExecMethod(self.vbMethod, 'Activate')
+
+        def Controls(self, controlname = ''):
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
+
+        def EndExecute(self, returnvalue):
+            return self.ExecMethod(self.vbMethod, 'EndExecute', returnvalue)
+
+        def Execute(self, modal = True):
+            return self.ExecMethod(self.vbMethod, 'Execute', modal)
+
+        def Terminate(self):
+            return self.ExecMethod(self.vbMethod, 'Terminate')
+
+    # #########################################################################
+    # SF_DialogControl CLASS
+    # #########################################################################
+    class SF_DialogControl(SFServices):
+        """
+            Each instance of the current class represents a single control within a dialog box.
+            The focus is clearly set on getting and setting the values displayed by the controls of the dialog box,
+            not on their formatting.
+            A special attention is given to controls with type TreeControl.
+            """
+        # Mandatory class properties for service registration
+        serviceimplementation = 'basic'
+        servicename = 'SFDialogs.DialogControl'
+        servicesynonyms = ('dialogcontrol', 'sfdialogs.dialog')
+        serviceproperties = dict(Cancel = True, Caption = True, ControlType = False, CurrentNode = True,
+                                 Default = True, Enabled = True, Format = True, ListCount = False,
+                                 ListIndex = True, Locked = True, MultiSelect = True, Name = False,
+                                 OnActionPerformed = False, OnAdjustmentValueChanged = False, OnFocusGained = False,
+                                 OnFocusLost = False, OnItemStateChanged = False, OnKeyPressed = False,
+                                 OnKeyReleased = False, OnMouseDragged = False, OnMouseEntered = False,
+                                 OnMouseExited = False, OnMouseMoved = False, OnMousePressed = False,
+                                 OnMouseReleased = False, OnNodeExpanded = True, OnNodeSelected = True,
+                                 OnTextChanged = False, Page = True, Parent = False, Picture = True,
+                                 RootNode = False, RowSource = True, Text = False, TipText = True,
+                                 TripleState = True, Value = True, Visible = True,
+                                 XControlModel = False, XControlView = False, XTreeDataModel = False)
+
+        # Root related properties do not start with X and, nevertheless, return a UNO object
+        @property
+        def CurrentNode(self):
+            return self.EXEC(self.objectreference, self.vbGet + self.flgUno, 'CurrentNode')
+
+        @property
+        def RootNode(self):
+            return self.EXEC(self.objectreference, self.vbGet + self.flgUno, 'RootNode')
+
+        def AddSubNode(self, parentnode, displayvalue, datavalue = ScriptForge.cstSymEmpty):
+            return self.ExecMethod(self.vbMethod + self.flgUno, 'AddSubNode', parentnode, displayvalue, datavalue)
+
+        def AddSubTree(self, parentnode, flattree, withdatavalue = False):
+            return self.ExecMethod(self.vbMethod, 'AddSubTree', parentnode, flattree, withdatavalue)
+
+        def CreateRoot(self, displayvalue, datavalue = ScriptForge.cstSymEmpty):
+            return self.ExecMethod(self.vbMethod + self.flgUno, 'CreateRoot', displayvalue, datavalue)
+
+        def FindNode(self, displayvalue, datavalue = ScriptForge.cstSymEmpty, casesensitive = False):
+            return self.ExecMethod(self.vbMethod + self.flgUno, 'FindNode', displayvalue, datavalue, casesensitive)
+
+        def SetFocus(self):
+            return self.ExecMethod(self.vbMethod, 'SetFocus')
+
+        def WriteLine(self, line = ''):
+            return self.ExecMethod(self.vbMethod, 'WriteLine', line)
 
 
 # #####################################################################################################################
@@ -1430,25 +1556,26 @@ class SFDocuments:
         forceGetProperty = True
 
         def Activate(self):
-            return self.Execute(self.vbMethod, 'Activate')
+            return self.ExecMethod(self.vbMethod, 'Activate')
 
         def CloseDocument(self, saveask = True):
-            return self.Execute(self.vbMethod, 'CloseDocument', saveask)
+            return self.ExecMethod(self.vbMethod, 'CloseDocument', saveask)
 
         def Forms(self, form = ''):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'Forms', form)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', form)
 
         def RunCommand(self, command):
-            return self.Execute(self.vbMethod, 'RunCommand', command)
+            return self.ExecMethod(self.vbMethod, 'RunCommand', command)
 
         def Save(self):
-            return self.Execute(self.vbMethod, 'Save')
+            return self.ExecMethod(self.vbMethod, 'Save')
 
         def SaveAs(self, filename, overwrite = False, password = '', filtername = '', filteroptions = ''):
-            return self.Execute(self.vbMethod, 'SaveAs', filename, overwrite, password, filtername, filteroptions)
+            return self.ExecMethod(self.vbMethod, 'SaveAs', filename, overwrite, password, filtername, filteroptions)
 
         def SaveCopyAs(self, filename, overwrite = False, password = '', filtername = '', filteroptions = ''):
-            return self.Execute(self.vbMethod, 'SaveCopyAs', filename, overwrite, password, filtername, filteroptions)
+            return self.ExecMethod(self.vbMethod, 'SaveCopyAs', filename, overwrite,
+                                   password, filtername, filteroptions)
 
     # #########################################################################
     # SF_Base CLASS
@@ -1468,22 +1595,22 @@ class SFDocuments:
                                  XComponent = False)
 
         def CloseDocument(self, saveask = True):
-            return self.Execute(self.vbMethod, 'CloseDocument', saveask)
+            return self.ExecMethod(self.vbMethod, 'CloseDocument', saveask)
 
         def FormDocuments(self):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'FormDocuments')
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'FormDocuments')
 
         def Forms(self, formdocument, form = ''):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'Forms', formdocument, form)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', formdocument, form)
 
         def GetDatabase(self, user = '', password = ''):
-            return self.Execute(self.vbMethod, 'GetDatabase', user, password)
+            return self.ExecMethod(self.vbMethod, 'GetDatabase', user, password)
 
         def IsLoaded(self, formdocument):
-            return self.Execute(self.vbMethod, 'IsLoaded', formdocument)
+            return self.ExecMethod(self.vbMethod, 'IsLoaded', formdocument)
 
         def OpenFormDocument(self, formdocument, designmode = False):
-            return self.Execute(self.vbMethod, 'OpenFormDocument', formdocument, designmode)
+            return self.ExecMethod(self.vbMethod, 'OpenFormDocument', formdocument, designmode)
 
     # #########################################################################
     # SF_Calc CLASS
@@ -1529,113 +1656,113 @@ class SFDocuments:
             return self.GetProperty('Width', rangename)
 
         def XCellRange(self, rangename):
-            return self.Execute(self.vbGet + self.flgUno, 'XCellRange', rangename)
+            return self.ExecMethod(self.vbGet + self.flgUno, 'XCellRange', rangename)
 
         def XSpreadsheet(self, sheetname):
-            return self.Execute(self.vbGet + self.flgUno, 'XSpreadsheet', sheetname)
+            return self.ExecMethod(self.vbGet + self.flgUno, 'XSpreadsheet', sheetname)
 
         # Usual methods
         def Activate(self, sheetname = ''):
-            return self.Execute(self.vbMethod, 'Activate', sheetname)
+            return self.ExecMethod(self.vbMethod, 'Activate', sheetname)
 
         def ClearAll(self, range):
-            return self.Execute(self.vbMethod, 'ClearAll', range)
+            return self.ExecMethod(self.vbMethod, 'ClearAll', range)
 
         def ClearFormats(self, range):
-            return self.Execute(self.vbMethod, 'ClearFormats', range)
+            return self.ExecMethod(self.vbMethod, 'ClearFormats', range)
 
         def ClearValues(self, range):
-            return self.Execute(self.vbMethod, 'ClearValues', range)
+            return self.ExecMethod(self.vbMethod, 'ClearValues', range)
 
         def CopySheet(self, sheetname, newname, beforesheet = 32768):
             sheet = (sheetname.objectreference if isinstance(sheetname, SFDocuments.SF_CalcReference) else sheetname)
-            return self.Execute(self.vbMethod + self.flgObject, 'CopySheet', sheet, newname, beforesheet)
+            return self.ExecMethod(self.vbMethod + self.flgObject, 'CopySheet', sheet, newname, beforesheet)
 
         def CopySheetFromFile(self, filename, sheetname, newname, beforesheet = 32768):
             sheet = (sheetname.objectreference if isinstance(sheetname, SFDocuments.SF_CalcReference) else sheetname)
-            return self.Execute(self.vbMethod + self.flgObject, 'CopySheetFromFile',
-                                filename, sheet, newname, beforesheet)
+            return self.ExecMethod(self.vbMethod + self.flgObject, 'CopySheetFromFile',
+                                   filename, sheet, newname, beforesheet)
 
         def CopyToCell(self, sourcerange, destinationcell):
             range = (sourcerange.objectreference if isinstance(sourcerange, SFDocuments.SF_CalcReference)
                      else sourcerange)
-            return self.Execute(self.vbMethod + self.flgObject, 'CopyToCell', range, destinationcell)
+            return self.ExecMethod(self.vbMethod + self.flgObject, 'CopyToCell', range, destinationcell)
 
         def CopyToRange(self, sourcerange, destinationrange):
             range = (sourcerange.objectreference if isinstance(sourcerange, SFDocuments.SF_CalcReference)
                      else sourcerange)
-            return self.Execute(self.vbMethod + self.flgObject, 'CopyToRange', range, destinationrange)
+            return self.ExecMethod(self.vbMethod + self.flgObject, 'CopyToRange', range, destinationrange)
 
         def DAvg(self, range):
-            return self.Execute(self.vbMethod, 'DAvg', range)
+            return self.ExecMethod(self.vbMethod, 'DAvg', range)
 
         def DCount(self, range):
-            return self.Execute(self.vbMethod, 'DCount', range)
+            return self.ExecMethod(self.vbMethod, 'DCount', range)
 
         def DMax(self, range):
-            return self.Execute(self.vbMethod, 'DMax', range)
+            return self.ExecMethod(self.vbMethod, 'DMax', range)
 
         def DMin(self, range):
-            return self.Execute(self.vbMethod, 'DMin', range)
+            return self.ExecMethod(self.vbMethod, 'DMin', range)
 
         def DSum(self, range):
-            return self.Execute(self.vbMethod, 'DSum', range)
+            return self.ExecMethod(self.vbMethod, 'DSum', range)
 
         def Forms(self, sheetname, form = ''):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'Forms', sheetname, form)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Forms', sheetname, form)
 
         def GetColumnName(self, columnnumber):
-            return self.Execute(self.vbMethod, 'GetColumnName', columnnumber)
+            return self.ExecMethod(self.vbMethod, 'GetColumnName', columnnumber)
 
         def GetFormula(self, range):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'GetFormula', range)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetFormula', range)
 
         def GetValue(self, range):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'GetValue', range)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'GetValue', range)
 
         def ImportFromCSVFile(self, filename, destinationcell, filteroptions = ScriptForge.cstSymEmpty):
-            return self.Execute(self.vbMethod, 'ImportFromCSVFile', filename, destinationcell, filteroptions)
+            return self.ExecMethod(self.vbMethod, 'ImportFromCSVFile', filename, destinationcell, filteroptions)
 
         def ImportFromDatabase(self, filename = '', registrationname = '', destinationcell = '', sqlcommand = '',
                                directsql = False):
-            return self.Execute(self.vbMethod, 'ImportFromDatabase', filename, registrationname,
-                                destinationcell, sqlcommand, directsql)
+            return self.ExecMethod(self.vbMethod, 'ImportFromDatabase', filename, registrationname,
+                                   destinationcell, sqlcommand, directsql)
 
         def InsertSheet(self, sheetname, beforesheet = 32768):
-            return self.Execute(self.vbMethod, 'InsertSheet', sheetname, beforesheet)
+            return self.ExecMethod(self.vbMethod, 'InsertSheet', sheetname, beforesheet)
 
         def MoveRange(self, source, destination):
-            return self.Execute(self.vbMethod, 'MoveRange', source, destination)
+            return self.ExecMethod(self.vbMethod, 'MoveRange', source, destination)
 
         def MoveSheet(self, sheetname, beforesheet = 32768):
-            return self.Execute(self.vbMethod, 'MoveSheet', sheetname, beforesheet)
+            return self.ExecMethod(self.vbMethod, 'MoveSheet', sheetname, beforesheet)
 
         def Offset(self, range, rows = 0, columns = 0, height = ScriptForge.cstSymEmpty,
                    width = ScriptForge.cstSymEmpty):
-            return self.Execute(self.vbMethod, 'Offset', range, rows, columns, height, width)
+            return self.ExecMethod(self.vbMethod, 'Offset', range, rows, columns, height, width)
 
         def RemoveSheet(self, sheetname):
-            return self.Execute(self.vbMethod, 'RemoveSheet', sheetname)
+            return self.ExecMethod(self.vbMethod, 'RemoveSheet', sheetname)
 
         def RenameSheet(self, sheetname, newname):
-            return self.Execute(self.vbMethod, 'RenameSheet', sheetname, newname)
+            return self.ExecMethod(self.vbMethod, 'RenameSheet', sheetname, newname)
 
         def SetArray(self, targetcell, value):
-            return self.Execute(self.vbMethod + self.flgArrayArg, 'SetArray', targetcell, value)
+            return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetArray', targetcell, value)
 
         def SetCellStyle(self, targetrange, style):
-            return self.Execute(self.vbMethod, 'SetCellStyle', targetrange, style)
+            return self.ExecMethod(self.vbMethod, 'SetCellStyle', targetrange, style)
 
         def SetFormula(self, targetrange, formula):
-            return self.Execute(self.vbMethod + self.flgArrayArg, 'SetFormula', targetrange, formula)
+            return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetFormula', targetrange, formula)
 
         def SetValue(self, targetrange, value):
-            return self.Execute(self.vbMethod + self.flgArrayArg, 'SetValue', targetrange, value)
+            return self.ExecMethod(self.vbMethod + self.flgArrayArg, 'SetValue', targetrange, value)
 
         def SortRange(self, range, sortkeys, sortorder = 'ASC', destinationcell = ScriptForge.cstSymEmpty,
                       containsheader = False, casesensitive = False, sortcolumns = False):
-            return self.Execute(self.vbMethod, 'SortRange', range, sortkeys, sortorder, destinationcell,
-                                containsheader, casesensitive, sortcolumns)
+            return self.ExecMethod(self.vbMethod, 'SortRange', range, sortkeys, sortorder, destinationcell,
+                                   containsheader, casesensitive, sortcolumns)
 
     # #########################################################################
     # SF_CalcReference CLASS
@@ -1677,37 +1804,37 @@ class SFDocuments:
                                  OrderBy = True, Parent = False, RecordSource = True, XForm = False)
 
         def Activate(self):
-            return self.Execute(self.vbMethod, 'Activate')
+            return self.ExecMethod(self.vbMethod, 'Activate')
 
         def CloseFormDocument(self):
-            return self.Execute(self.vbMethod, 'CloseFormDocument')
+            return self.ExecMethod(self.vbMethod, 'CloseFormDocument')
 
         def Controls(self, controlname = ''):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
 
         def GetDatabase(self, user = '', password = ''):
-            return self.Execute(self.vbMethod, 'GetDatabase', user, password)
+            return self.ExecMethod(self.vbMethod, 'GetDatabase', user, password)
 
         def MoveFirst(self):
-            return self.Execute(self.vbMethod, 'MoveFirst')
+            return self.ExecMethod(self.vbMethod, 'MoveFirst')
 
         def MoveLast(self):
-            return self.Execute(self.vbMethod, 'MoveLast')
+            return self.ExecMethod(self.vbMethod, 'MoveLast')
 
         def MoveNew(self):
-            return self.Execute(self.vbMethod, 'MoveNew')
+            return self.ExecMethod(self.vbMethod, 'MoveNew')
 
         def MoveNext(self, offset = 1):
-            return self.Execute(self.vbMethod, 'MoveNext', offset)
+            return self.ExecMethod(self.vbMethod, 'MoveNext', offset)
 
         def MovePrevious(self, offset = 1):
-            return self.Execute(self.vbMethod, 'MovePrevious', offset)
+            return self.ExecMethod(self.vbMethod, 'MovePrevious', offset)
 
         def Requery(self):
-            return self.Execute(self.vbMethod, 'Requery')
+            return self.ExecMethod(self.vbMethod, 'Requery')
 
         def Subforms(self, subform = ''):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'Subforms', subform)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Subforms', subform)
 
     # #########################################################################
     # SF_FormControl CLASS
@@ -1738,10 +1865,10 @@ class SFDocuments:
                                  Visible = True, XControlModel = False, XControlView = False)
 
         def Controls(self, controlname = ''):
-            return self.Execute(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
+            return self.ExecMethod(self.vbMethod + self.flgArrayRet, 'Controls', controlname)
 
         def SetFocus(self):
-            return self.Execute(self.vbMethod, 'SetFocus')
+            return self.ExecMethod(self.vbMethod, 'SetFocus')
 
 
 # ##############################################False##################################################################
@@ -1791,7 +1918,15 @@ def CreateScriptService(service, *args):
         # Check if the service is a predefined standard Basic service
         elif scriptservice in ScriptForge.servicesmodules:
             return serv(ScriptForge.servicesmodules[scriptservice], classmodule = SFServices.moduleStandard)
+    else:
+        serv = None
     # The requested service is to be found in the Basic world
+    # Check if the service must review the arguments
+    if serv is not None:
+        if hasattr(serv, 'PreProcessArgs'):
+            # PreProcessArgs() must be a class method
+            args = serv.PreProcessArgs(args)
+    # Get the service object back from Basic
     if len(args) == 0:
         serv = ScriptForge.InvokeBasicService('SF_Services', SFServices.vbMethod, 'CreateScriptService', service)
     else:
diff --git a/wizards/source/sfdialogs/SF_Dialog.xba b/wizards/source/sfdialogs/SF_Dialog.xba
index 3bee408bdc7b..e0b7beb11d0a 100644
--- a/wizards/source/sfdialogs/SF_Dialog.xba
+++ b/wizards/source/sfdialogs/SF_Dialog.xba
@@ -531,6 +531,8 @@ Public Function Properties() As Variant
 					, "Page" _
 					, "Visible" _
 					, "Width" _
+					, "XDialogModel" _
+					, "XDialogView" _
 					)
 
 End Function	'	SFDialogs.SF_Dialog.Properties
@@ -658,8 +660,7 @@ Public Sub _Initialize()
 '''		- Initialisation of persistent storage for controls
 
 Try:
-	'	Create the graphical interface
-	Set _DialogControl = CreateUnoDialog(_DialogProvider)
+	'	Keep reference to model
 	Set _DialogModel = _DialogControl.Model
 
 	'	Add dialog reference to cache
diff --git a/wizards/source/sfdialogs/SF_DialogControl.xba b/wizards/source/sfdialogs/SF_DialogControl.xba
index 161ff1d2b571..ab32abbd484f 100644
--- a/wizards/source/sfdialogs/SF_DialogControl.xba
+++ b/wizards/source/sfdialogs/SF_DialogControl.xba
@@ -576,6 +576,7 @@ Public Function AddSubTree(Optional ByRef ParentNode As Variant _
 '''			Typically, such an array can be issued by the GetRows method applied on the SFDatabases.Database service
 '''			when an array item containing the text to be displayed is = "" or is empty/null,
 '''				no new subnode is created and the remainder of the row is skipped
+'''			When AddSubTree() is called from a Python script, FlatTree may be an array of arrays
 '''		WithDataValue:
 '''			When False (default), every column of FlatTree contains the text to be displayed in the tree control
 '''			When True, the texts to be displayed (DisplayValue) are in columns 0, 2, 4, ...
@@ -597,6 +598,13 @@ Dim oNode As Object					'	com.sun.star.awt.tree.XMutableTreeNode
 Dim oNewNode As Object				'	com.sun.star.awt.tree.XMutableTreeNode
 Dim lChildCount As Long				'	Number of children nodes of a parent node
 Dim iStep As Integer				'	1 when WithDataValue = False, 2 otherwise
+Dim iDims As Integer				'	Number of dimensions of FlatTree
+Dim lMin1 As Long					'	Lower bound (rows)
+Dim lMin2 As Long					'	Lower bounds (cols)
+Dim lMax1 As Long					'	Upper bound (rows)
+Dim lMax2 As Long					'	Upper bounds (cols)
+Dim vFlatItem As Variant			'	A single FlatTree item: FlatTree(i, j)
+Dim vFlatItem2 As Variant			'	A single FlatTree item
 Dim bChange As Boolean				'	When True, the item in FlatTree is different from the item above
 Dim sValue As String				'	Alias for display values
 Dim i As Long, j As Long
@@ -612,7 +620,7 @@ Check:
 		If _ControlType <> CTLTREECONTROL Then GoTo CatchType
 		If Not ScriptForge.SF_Utils._Validate(ParentNode, "ParentNode", V_OBJECT) Then GoTo Catch
 		If ScriptForge.SF_Session.UnoObjectType(ParentNode) <> "toolkit.MutableTreeNode" Then GoTo Catch
-		If Not ScriptForge.SF_Utils._ValidateArray(FlatTree, "FlatTree", 2) Then GoTo Catch
+		If Not ScriptForge.SF_Utils._ValidateArray(FlatTree, "FlatTree") Then GoTo Catch	'	Dimensions checked below
 		If Not ScriptForge.SF_Utils._Validate(WithDataValue, "WithDataValue", V_BOOLEAN) Then GoTo Catch
 	End If
 
@@ -623,34 +631,55 @@ Try:
 		For i = 1 To lChildCount
 			ParentNode.removeChildByIndex(0)		'	This cleans all subtrees too
 		Next i
+
+		'	Determine bounds
+		iDims = ScriptForge.SF_Array.CountDims(FlatTree)
+		Select Case iDims
+			Case -1, 0		:	GoTo Catch
+			Case 1					'	Called probably from Python
+				lMin1 = LBound(FlatTree, 1)			:	lMax1 = UBound(FlatTree, 1)
+				If Not IsArray(FlatTree(0)) Then GoTo Catch
+				If UBound(FlatTree(0)) < LBound(FlatTree(0)) Then GoTo Catch	'	No columns
+				lMin2 = LBound(FlatTree(0))			:	lMax2 = UBound(FlatTree(0))
+			Case 2
+				lMin1 = LBound(FlatTree, 1)			:	lMax1 = UBound(FlatTree, 1)
+				lMin2 = LBound(FlatTree, 2)			:	lMax2 = UBound(FlatTree, 2)
+			Case Else		:	GoTo Catch
+		End Select
+
 		'	Build a new subtree
-		If UBound(FlatTree, 1) < LBound(FlatTree, 1) Then		'Array is empty
-		Else
-			iStep = Iif(WithDataValue, 2, 1)
-			For i = LBound(FlatTree, 1) To UBound(FlatTree, 1)					'	Array rows
-				bChange = ( i = 0 )
-				'	Restart from the parent node at each i-iteration
-				Set oNode = ParentNode
-				For j = LBound(FlatTree, 2) To UBound(FlatTree, 2) Step iStep	'	Array columns
-					If FlatTree(i, j) = "" Or IsNull(FlatTree(i, j)) Or IsEmpty(FlatTree(i, j)) Then
-						Set oNode = Nothing
-						Exit For		'	Exit j-loop
+		iStep = Iif(WithDataValue, 2, 1)
+		For i = lMin1 To lMax1
+			bChange = ( i = 0 )
+			'	Restart from the parent node at each i-iteration
+			Set oNode = ParentNode
+			For j = lMin2 To lMax2 Step iStep	'	Array columns
+				If iDims = 1 Then vFlatItem = FlatTree(i)(j) Else vFlatItem = FlatTree(i, j)
+				If vFlatItem = "" Or IsNull(vFlatItem) Or IsEmpty(vFlatItem) Then
+					Set oNode = Nothing
+					Exit For		'	Exit j-loop
+				End If
+				If Not bChange Then
+					If iDims = 1 Then vFlatItem2 = FlatTree(i - 1)(j) Else vFlatItem2 = FlatTree(i - 1, j)
+					bChange = ( vFlatItem <> vFlatItem2 )
+				End If
+				If bChange Then		'	Create new subnode at tree depth = j
+					If VarType(vFlatItem) = V_STRING Then sValue = vFlatItem Else sValue = ScriptForge.SF_String.Represent(vFlatItem)
+					Set oNewNode = .createNode(sValue, True)
+					If WithDataValue Then
+						If iDims = 1 Then vFlatItem2 = FlatTree(i)(j + 1) Else vFlatItem2 = FlatTree(i, j + 1)
+						oNewNode.DataValue = vFlatItem2
 					End If
-					If Not bChange Then bChange = ( FlatTree(i, j) <> FlatTree(i - 1, j) )
-					If bChange Then		'	Create new subnode at tree depth = j
-						If VarType(FlatTree(i, j)) = V_STRING Then sValue = FlatTree(i, j) Else sValue = ScriptForge.SF_String.Represent(FlatTree(i, j))
-						Set oNewNode = .createNode(sValue, True)
-						If WithDataValue Then oNewNode.DataValue = FlatTree(i, j + 1)
-						oNode.appendChild(oNewNode)
-						Set oNode = oNewNode
-					Else
-						'	Position next current node on last child of actual current node
-						lChildCount = oNode.getChildCount()
-						If lChildCount > 0 Then Set oNode = oNode.getChildAt(lChildCount - 1) Else Set oNode = Nothing
-					End If
-				Next j
-			Next i
-		End If			
+					oNode.appendChild(oNewNode)
+					Set oNode = oNewNode
+				Else
+					'	Position next current node on last child of actual current node
+					lChildCount = oNode.getChildCount()
+					If lChildCount > 0 Then Set oNode = oNode.getChildAt(lChildCount - 1) Else Set oNode = Nothing
+				End If
+			Next j
+		Next i
+		bSubTree = True
 	End With
 
 Finally:
@@ -854,6 +883,7 @@ Public Function Properties() As Variant
 					, "Page" _
 					, "Parent" _
 					, "Picture" _
+					, "RootNode" _
 					, "RowSource" _
 					, "Text" _
 					, "TipText" _
diff --git a/wizards/source/sfdialogs/SF_Register.xba b/wizards/source/sfdialogs/SF_Register.xba
index 0bda31d48ebe..fc3dbf54008c 100644
--- a/wizards/source/sfdialogs/SF_Register.xba
+++ b/wizards/source/sfdialogs/SF_Register.xba
@@ -226,6 +226,7 @@ Public Function _NewDialog(Optional ByVal pvArgs As Variant) As Object
 '''		Library: the name of the library hosting the dialog. Default = "Standard"
 '''		DialogName: The name of the dialog
 '''			Library and dialog names are case-sensitive
+'''		Context: When called from Python, the context must be provided : XSCRIPTCONTEXT
 '''	Returns: the instance or Nothing
 
 Dim oDialog As Object				'	Return value
@@ -233,11 +234,14 @@ Dim vContainer As Variant			'	Alias of pvArgs(0)
 Dim vLibrary As Variant				'	Alias of pvArgs(1)
 Dim vDialogName As Variant			'	Alias of pvArgs(2)
 Dim oLibraries As Object			'	com.sun.star.comp.sfx2.DialogLibraryContainer
-Dim oLibrary As Object				'	com.sun.star.container.XNameAccess
+Dim vContext As Variant				'	com.sun.star.uno.XComponentContext
 Dim oDialogProvider As Object		'	com.sun.star.io.XInputStreamProvider
 Dim oEnum As Object					'	com.sun.star.container.XEnumeration
 Dim oComp As Object					'	com.sun.star.lang.XComponent
+Dim oDialogControl As Object		'	com.sun.star.awt.XControl - stardiv.Toolkit.UnoDialogControl
 Dim vWindow As Window				'	A single component
+Dim sScope As String				'	"application" or "document"
+Dim sURI As String					'	URI of the targeted dialog
 Dim oUi As Object					'	"UI" service
 Dim bFound As Boolean				'	True if WindowName is found on the desktop
 Const cstService = "SFDialogs.Dialog"
@@ -255,16 +259,18 @@ Check:
 	If Not ScriptForge.SF_Utils._Validate(vContainer, "Container", Array(V_STRING, ScriptForge.V_OBJECT)) Then GoTo Finally
 	If Not ScriptForge.SF_Utils._Validate(vLibrary, "Library", V_STRING) Then GoTo Finally
 	If Not ScriptForge.SF_Utils._Validate(vDialogName, "DialogName", V_STRING) Then GoTo Finally
+	If UBound(pvArgs) >= 3 Then vContext = pvArgs(3) Else vContext = Nothing
+	If Not ScriptForge.SF_Utils._Validate(vContext, "DialogName", V_OBJECT) Then GoTo Finally
 	Set oDialog = Nothing
 
 Try:
-	'	Determine the container and the library hosting the dialog
-	Set oLibraries = Nothing
+	'	Determine the library container hosting the dialog
+	Set oUi = ScriptForge.SF_Register.CreateScriptService("UI")
+	Set oComp = Nothing
 	If VarType(vContainer) = V_STRING Then
-		If UCase(vContainer) = UCase(cstGlobal) Then Set oLibraries = GlobalScope.DialogLibraries
+		bFound = ( UCase(vContainer) = UCase(cstGlobal) )
 	End If
-	If IsNull(oLibraries) Then
-		Set oUi = ScriptForge.SF_Register.CreateScriptService("UI")
+	If Not bFound Then
 		Select Case VarType(vContainer)
 			Case V_STRING
 				If Len(vContainer) > 0 Then
@@ -294,19 +300,27 @@ Try:
 		End Select
 		If Not bFound Then GoTo CatchNotFound
 		If Len(vWindow.DocumentType) = 0 Then GoTo CatchNotFound
-		'	The library is now fully determined
-		Set oLibraries = oComp.DialogLibraries
 	End If
 
-	'	Load the library and get the dialog
-	With oLibraries
-		If Not .hasByName(vLibrary) Then GoTo CatchNotFound
-		If Not .isLibraryLoaded(vLibrary) Then .loadLibrary(vLibrary)
-		Set oLibrary = .getByName(vLibrary)
-		If Not oLibrary.hasByName(vDialogName) Then GoTo CatchNotFound
-		Set oDialogProvider = oLibrary.getByName(vDialogName)
-	End With
+	'	Determine the dialog provider
+	Select Case True
+		Case IsNull(vContext) And IsNull(oComp)			'	Basic and GlobalScope
+			Set oDialogProvider = GetProcessServiceManager.createInstance("com.sun.star.awt.DialogProvider")
+		Case IsNull(vContext) And Not IsNull(oComp)		'	Basic and Document
+			Set oDialogProvider = GetProcessServiceManager.createInstanceWithArguments("com.sun.star.awt.DialogProvider", Array(oComp))
+		Case Not IsNull(vContext) And IsNull(oComp)		'	Python and GlobalScope
+			Set oDialogProvider = vContext.getServiceManager().createInstanceWithContext("com.sun.star.awt.DialogProvider", vContext)
+		Case Not IsNull(vContext) And Not IsNull(oComp)	'	Python and Document
+			Set oDialogProvider = vContext.getServiceManager().createInstanceWithContext("com.sun.star.awt.DialogProvider", Array(oComp))
+	End Select
+
+	'	Create the graphcal interface
+	sScope = Iif(IsNull(oComp), "application", "document")
+	sURI = "vnd.sun.star.script:" & vLibrary & "." & vDialogName & "?location=" & sScope
+	On Local Error GoTo CatchNotFound
+	Set oDialogControl = oDialogProvider.createDialog(sURI)
 
+	'	Initialize the basic SF_Dialog instance to return to the user script
 	Set oDialog = New SF_Dialog
 	With oDialog
 		Set .[Me] = oDialog
@@ -314,6 +328,7 @@ Try:
 		._Library = vLibrary
 		._Name = vDialogName
 		Set ._DialogProvider = oDialogProvider
+		Set ._DialogControl = oDialogControl
 		._Initialize()
 	End With
 


More information about the Libreoffice-commits mailing list