wizards/source/scriptforge/SF_Exception.xba | 2 wizards/source/scriptforge/SF_PythonHelper.xba | 4 wizards/source/scriptforge/SF_String.xba | 2 wizards/source/scriptforge/python/scriptforge.py | 103 ++++++++++++----------- wizards/source/sfdocuments/SF_FormControl.xba | 75 ++++++++++++---- 5 files changed, 118 insertions(+), 68 deletions(-)
New commits: commit de3b720f4066c9fcf1258bf6592263a7e476cc46 Author: Jean-Pierre Ledure <j...@ledure.be> AuthorDate: Sat Apr 10 15:10:02 2021 +0200 Commit: Jean-Pierre Ledure <j...@ledure.be> CommitDate: Sat Apr 10 16:44:27 2021 +0200 ScriptForge - (scriptforge.py) FormControl class New class to manage controls in forms and subforms from Python, essentially thru the use of Properties Required a review of SF_FormControl.Getproperty() Indeed, the IDE debugger computes all the properties of a Basic object when expanded in the watch window. This can cause errors. This class makes use of default values for properties when irrelevant for the actual control type Error were detected on date/time conversions of date/timefield controls and corrected. SF_String etc shortcuts have been removed (see previous commit) because not applicable in every scenario. The only entry point to the API from a user Python script is via CreateScriptService(). Change-Id: Ia87c7281c3fcf39ab0c3528f00114c9b1e067bcf Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113920 Tested-by: Jean-Pierre Ledure <j...@ledure.be> Tested-by: Jenkins Reviewed-by: Jean-Pierre Ledure <j...@ledure.be> diff --git a/wizards/source/scriptforge/SF_Exception.xba b/wizards/source/scriptforge/SF_Exception.xba index d2ee476c6430..650f14164a02 100644 --- a/wizards/source/scriptforge/SF_Exception.xba +++ b/wizards/source/scriptforge/SF_Exception.xba @@ -1173,4 +1173,4 @@ Private Function _Repr() As String End Function ' ScriptForge.SF_Exception._Repr REM ============================================ END OF SCRIPTFORGE.SF_EXCEPTION -</script:module> +</script:module> \ No newline at end of file diff --git a/wizards/source/scriptforge/SF_PythonHelper.xba b/wizards/source/scriptforge/SF_PythonHelper.xba index e3d988c38aa9..328978033290 100644 --- a/wizards/source/scriptforge/SF_PythonHelper.xba +++ b/wizards/source/scriptforge/SF_PythonHelper.xba @@ -729,6 +729,10 @@ Try: Case "Controls" : vReturn = vBasicObject.Controls(vArgs(0)) Case "Subforms" : vReturn = vBasicObject.Subforms(vArgs(0)) End Select + Case "SFDocuments.FormControl" + Select Case Script + Case "Controls" : vReturn = vBasicObject.Controls(vArgs(0)) + End Select End Select ' Methods in class modules are invoked with CallByName diff --git a/wizards/source/scriptforge/SF_String.xba b/wizards/source/scriptforge/SF_String.xba index 6519ac2383d3..f7c645981c8b 100644 --- a/wizards/source/scriptforge/SF_String.xba +++ b/wizards/source/scriptforge/SF_String.xba @@ -2309,7 +2309,7 @@ Dim bSplit As Boolean ' New chunk found or not Dim i As Long Const cstDouble = """" : Const cstSingle = "'" Const cstThisSub = "String.SplitNotQuoted" -Const cstSubArgs = "InputStr, [Delimiter="" ""], [Occurrences=0], [QuoteChar=""" & cstDouble & """" +Const cstSubArgs = "InputStr, [Delimiter="" ""], [Occurrences=0], [QuoteChar=""" & cstDouble & """]" If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch vSplit = Array() diff --git a/wizards/source/scriptforge/python/scriptforge.py b/wizards/source/scriptforge/python/scriptforge.py index c143d196e3b7..e3d4bdfa63e6 100644 --- a/wizards/source/scriptforge/python/scriptforge.py +++ b/wizards/source/scriptforge/python/scriptforge.py @@ -183,7 +183,7 @@ class ScriptForge(object, metaclass = _Singleton): """ servicemanager = context.ServiceManager # com.sun.star.lang.XMultiComponentFactory masterscript = servicemanager.createInstanceWithContext( - "com.sun.star.script.provider.MasterScriptProviderFactory", context) + 'com.sun.star.script.provider.MasterScriptProviderFactory', context) return masterscript.createScriptProvider("") @classmethod @@ -201,7 +201,7 @@ class ScriptForge(object, metaclass = _Singleton): :return: the value returned by the invoked script, or an error if the script was not found """ - # The frequently called PythonDispatcher in the ScriptForge Basic library is buffered to privilege performance + # The frequently called PythonDispatcher in the ScriptForge Basic library is cached to privilege performance if cls.servicesdispatcher is not None and script == ScriptForge.basicdispatcher: xscript = cls.servicesdispatcher fullscript = script @@ -313,7 +313,11 @@ class ScriptForge(object, metaclass = _Singleton): elif returntuple[cstVarType] >= ScriptForge.V_ARRAY: pass elif returntuple[cstVarType] == ScriptForge.V_DATE: - return datetime.datetime.fromisoformat(returntuple[cstValue]) + try: # Anticipate fromisoformat('00:00:00') and alike + dat = None + dat = datetime.datetime.fromisoformat(returntuple[cstValue]) + finally: + return dat else: # All other scalar values pass return returntuple[cstValue] @@ -351,12 +355,11 @@ class ScriptForge(object, metaclass = _Singleton): func = getattr(cls, method) if callable(func): # Assign to each synonym a reference to the original method - m = method.lower() - if hasattr(cls, m) is False: - setattr(cls, m, func) - m = camelCase(method) - if hasattr(cls, m) is False: - setattr(cls, m, func) + lc = method.lower() + setattr(cls, lc, func) + cc = camelCase(method) + if cc != lc: + setattr(cls, cc, func) return @@ -553,7 +556,7 @@ class SFServices(object): Set the given property to a new value in the Basic world """ if self.serviceimplementation == 'basic': - return self.EXEC(self.objectreference, self.vbLet, propertyname, value) + return self.EXEC(self.objectreference, self.vbLet + self.flgDateArg, propertyname, value) # ##################################################################################################################### @@ -648,10 +651,9 @@ class SFScriptForge: expression = expression.isoformat() return self.SIMPLEEXEC(self.module + '.PyFormat', expression, format) - @staticmethod - def GetDefaultContext(): + @classmethod + def GetDefaultContext(cls): return ScriptForge.componentcontext - getDefaultContext, getdefaultcontext = GetDefaultContext, GetDefaultContext def GetGuiType(self): return self.SIMPLEEXEC(self.module + '.PyGetGuiType') @@ -659,10 +661,9 @@ class SFScriptForge: def GetSystemTicks(self): return self.SIMPLEEXEC(self.module + '.PyGetSystemTicks') - @staticmethod - def GetPathSeparator(): + @classmethod + def GetPathSeparator(cls): return os.sep - getPathSeparator, getpathseparator = GetPathSeparator, GetPathSeparator class GlobalScope(object, metaclass = _Singleton): @classmethod # Mandatory because the GlobalScope class is normally not instantiated @@ -681,18 +682,16 @@ class SFScriptForge: def MsgBox(self, prompt, buttons = 0, title = ''): return self.SIMPLEEXEC(self.module + '.PyMsgBox', prompt, buttons, title) - @staticmethod - def Now(): + @classmethod + def Now(cls): return datetime.datetime.now() - now = Now - @staticmethod - def RGB(red, green, blue): + @classmethod + def RGB(cls, red, green, blue): return int('%02x%02x%02x' % (red, green, blue), 16) - rgb = RGB - @staticmethod - def StarDesktop(): + @classmethod + def StarDesktop(cls): ctx = ScriptForge.componentcontext if ctx is None: return None @@ -700,7 +699,6 @@ class SFScriptForge: DESK = 'com.sun.star.frame.Desktop' desktop = smgr.createInstanceWithContext(DESK, ctx) return desktop - starDesktop, stardesktop = StarDesktop, StarDesktop def Xray(self, unoobject = None): return self.SIMPLEEXEC('XrayTool._main.xray', unoobject) @@ -1653,6 +1651,40 @@ class SFDocuments: def Subforms(self, subform = ''): return self.Execute(self.vbMethod + self.flgArrayRet, 'Subforms', subform) + # ######################################################################### + # SF_FormControl CLASS + # ######################################################################### + class SF_FormControl(SFServices): + """ + Manage the controls belonging to a form or subform stored in a document. + Each instance of the current class represents a single control within a form, a subform or a tablecontrol. + A prerequisite is that all controls within the same form, subform or tablecontrol must have + a unique name. + """ + # Mandatory class properties for service registration + serviceimplementation = 'basic' + servicename = 'SFDocuments.FormControl' + servicesynonyms = () + serviceproperties = dict(Action = True, Caption = True, ControlSource = False, ControlType = False, + Default = True, DefaultValue = True, Enabled = True, Format = True, + ListCount = False, ListIndex = True, ListSource = True, ListSourceType = True, + Locked = True, MultiSelect = True, Name = False, + OnActionPerformed = True, OnAdjustmentValueChanged = True, + OnApproveAction = True, OnApproveReset = True, OnApproveUpdate = True, + OnChanged = True, OnErrorOccurred = True, OnFocusGained = True, OnFocusLost = True, + OnItemStateChanged = True, OnKeyPressed = True, OnKeyReleased = True, + OnMouseDragged = True, OnMouseEntered = True, OnMouseExited = True, + OnMouseMoved = True, OnMousePressed = True, OnMouseReleased = True, OnResetted = True, + OnTextChanged = True, OnUpdated = True, Parent = False, Picture = True, + Required = True, Text = False, TipText = True, TripleState = True, Value = True, + Visible = True, XControlModel = False, XControlView = False) + + def Controls(self, controlname = ''): + return self.Execute(self.vbMethod + self.flgArrayRet, 'Controls', controlname) + + def SetFocus(self): + return self.Execute(self.vbMethod, 'SetFocus') + # ##############################################False################################################################## # CreateScriptService() ### @@ -1712,27 +1744,6 @@ def CreateScriptService(service, *args): createScriptService, createscriptservice = CreateScriptService, CreateScriptService -# ##################################################################################################################### -# Services shortcuts ### -# ##################################################################################################################### -def _CreateScriptService(service): - """ - Mini CreateScriptService() function to create singleton predefined Basic services - The ScriptForge() initialization is SKIPPED. - """ - if service in ScriptForge.servicesmodules: - serv = ScriptForge.serviceslist[service] - return serv(ScriptForge.servicesmodules[service], classmodule = SFServices.moduleStandard) - return None - - -# Shortcuts below are for compatibility with the Basic ScriptForge API -SF_Basic = SFScriptForge.SF_Basic() -SF_Array = _CreateScriptService('ScriptForge.SF_Array') -SF_Exception = _CreateScriptService('ScriptForge.SF_Exception') -SF_String = _CreateScriptService('ScriptForge.SF_String') - - # ###################################################################### # Lists the scripts, that shall be visible inside the Basic/Python IDE # ###################################################################### diff --git a/wizards/source/sfdocuments/SF_FormControl.xba b/wizards/source/sfdocuments/SF_FormControl.xba index a40b902e3425..92055c5e25a4 100644 --- a/wizards/source/sfdocuments/SF_FormControl.xba +++ b/wizards/source/sfdocuments/SF_FormControl.xba @@ -758,9 +758,10 @@ Public Function GetProperty(Optional ByVal PropertyName As Variant) As Variant ''' Exceptions: ''' see the exceptions of the individual properties ''' Examples: -''' myModel.GetProperty("MyProperty") +''' myControl.GetProperty("MyProperty") -Const cstThisSub = "SFDocuments.DialogControl.GetProperty" +Dim vDefault As Variant ' Default value when property not applicable on control type +Const cstThisSub = "SFDocuments.FormControl.GetProperty" Const cstSubArgs = "" If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch @@ -772,7 +773,28 @@ Check: End If Try: - GetProperty = _PropertyGet(PropertyName) + ' FormControl properties are far from applicable to all control types + ' Getting a property must never abort to not interfere with the Basic IDE watch function + ' Hence a default value must be provided + Select Case UCase(PropertyName) + Case UCase("Default") : vDefault = False + Case UCase("DefaultValue") : vDefault = Null + Case UCase("Enabled") : vDefault = False + Case UCase("ListCount") : vDefault = 0 + Case UCase("ListIndex") : vDefault = -1 + Case UCase("Locked") : vDefault = False + Case UCase("MultiSelect") : vDefault = False + Case UCase("Parent") : vDefault = Nothing + Case UCase("Required") : vDefault = False + Case UCase("TripleState") : vDefault = False + Case UCase("Value") : vDefault = Empty + Case UCase("Visible") : vDefault = True + Case UCase("XControlModel") : vDefault = Nothing + Case UCase("XControlView") : vDefault = Nothing + Case Else : vDefault = "" + End Select + + GetProperty = _PropertyGet(PropertyName, vDefault) Finally: ScriptForge.SF_Utils._ExitFunction(cstThisSub) @@ -783,7 +805,7 @@ End Function ' SFDocuments.SF_FormControl.GetProperty REM ----------------------------------------------------------------------------- Public Function Methods() As Variant -''' Return the list of public methods of the Model service as an array +''' Return the list of public methods of the FormControl service as an array Methods = Array( _ "AddSubNode" _ @@ -798,10 +820,11 @@ End Function ' SFDocuments.SF_FormControl.Methods REM ----------------------------------------------------------------------------- Public Function Properties() As Variant -''' Return the list or properties of the Timer class as an array +''' Return the list or properties of the FormControl class as an array Properties = Array( _ - "Cancel" _ + "Action" _ + , "Cancel" _ , "Caption" _ , "ControlSource" _ , "ControlType" _ @@ -926,7 +949,7 @@ Public Function SetProperty(Optional ByVal PropertyName As Variant _ ''' Exceptions ''' ARGUMENTERROR The property does not exist -Const cstThisSub = "SFDocuments.DialogControl.SetProperty" +Const cstThisSub = "SFDocuments.FormControl.SetProperty" Const cstSubArgs = "PropertyName, Value" If SF_Utils._ErrorHandling() Then On Local Error GoTo Catch @@ -1173,7 +1196,7 @@ Dim vSelection As Variant ' Alias of Model.SelectedItems or Model.Selec Dim vList As Variant ' Alias of Model.StringItemList Dim lIndex As Long ' Index in StringItemList Dim sItem As String ' A single item -Dim vDate As Variant ' com.sun.star.util.Date or com.sun.star.util.Time +Dim vDate As Variant ' Date after conversion from com.sun.star.util.Date or com.sun.star.util.Time Dim vValues As Variant ' Array of listbox values Dim oControlEvents As Object ' com.sun.star.container.XNameContainer Dim sEventName As String ' Internal event name @@ -1246,8 +1269,10 @@ Const cstSubArgs = "" Case CTLDATEFIELD If oSession.HasUNOProperty(_ControlModel, "DefaultDate") Then If Not IsEmpty(_ControlModel.DefaultDate) Then - vDate = _ControlModel.DefaultDate - _PropertyGet = DateSerial(vDate.Year, vDate.Month, vDate.Day) + With _ControlModel.DefaultDate + vDate = DateSerial(.Year, .Month, .Day) + End With + _PropertyGet = vDate End If End If Case CTLFORMATTEDFIELD @@ -1268,8 +1293,10 @@ Const cstSubArgs = "" Case CTLTIMEFIELD If oSession.HasUNOProperty(_ControlModel, "DefaultTime") Then If Not IsEmpty(_ControlModel.DefaultTime) Then - vDate = _ControlModel.DefaultTime - _PropertyGet = TimeSerial(vDate.Hours, vDate.Minutes, vDate.Seconds) + With _ControlModel.DefaultTime + vDate = TimeSerial(.Hours, .Minutes, .Seconds) + End With + _PropertyGet = vDate End If End If Case Else : GoTo CatchType @@ -1387,15 +1414,19 @@ Const cstSubArgs = "" And oSession.HasUNOProperty(_ControlModel, "FormatKey") _ And oSession.HasUNOProperty(_ControlModel, "FormatsSupplier") Then If Not IsEmpty(_ControlModel.Date) Then - vDate = DateSerial(_ControlModel.Date.Year, _ControlModel.Date.Month, _ControlModel.Date.Day) + With _ControlModel.Date + vDate = DateSerial(.Year, .Month, .Day) + End With _PropertyGet = Format(vDate, _ControlModel.FormatsSupplier.getNumberFormats.getByKey(_ControlModel.FormatKey).FormatString) End If End If Case CTLTIMEFIELD If oSession.HasUNOProperty(_ControlModel, "Text") Then If Not IsEmpty(_ControlModel.Time) Then - Set vDate = _ControlModel.Time - _PropertyGet = Format(TimeSerial(vDate.Hours, vDate.Minutes, vDate.Seconds), "HH:MM:SS") + With _ControlModel.Time + vDate = TimeSerial(.Hours, .Minutes, .Seconds) + End With + _PropertyGet = Format(vDate, "HH:MM:SS") End If End If Case CTLCOMBOBOX, CTLFILECONTROL, CTLFORMATTEDFIELD, CTLPATTERNFIELD, CTLTEXTFIELD @@ -1432,8 +1463,10 @@ Const cstSubArgs = "" vGet = CDate(1) If oSession.HasUnoProperty(_ControlModel, "Date") Then If VarType(_ControlModel.Date) = ScriptForge.V_OBJECT Then ' com.sun.star.util.Date - Set vDate = _ControlModel.Date - vGet = DateSerial(vDate.Year, vDate.Month, vDate.Day) + With _ControlModel.Date + vDate = DateSerial(.Year, .Month, .Day) + End With + vGet = vDate Else ' .Date = Empty End If End If @@ -1480,8 +1513,10 @@ Const cstSubArgs = "" vGet = CDate(0) If oSession.HasUnoProperty(_ControlModel, "Time") Then If VarType(_ControlModel.Time) = ScriptForge.V_OBJECT Then ' com.sun.star.Util.Time - Set vDate = _ControlModel.Time - vGet = TimeSerial(vDate.Hours, vDate.Minutes, vDate.Seconds) + With _ControlModel.Time + vDate = TimeSerial(.Hours, .Minutes, .Seconds) + End With + vGet = vDate Else ' .Time = Empty End If End If @@ -1625,7 +1660,7 @@ Const cstSubArgs = "Value" If _ControlType = CTLCOMBOBOX Then _ControlModel.ListSource = pvValue Else _ControlModel.ListSource = Array(pvValue) _ControlModel.refresh() Case .SQL - et oDatabase = _ParentForm.GetDatabase() + Set oDatabase = _ParentForm.GetDatabase() If _ControlType = CTLCOMBOBOX Then _ControlModel.ListSource = oDatabase._ReplaceSquareBrackets(pvValue) Else _ControlModel.ListSource = Array(oDatabase._ReplaceSquareBrackets(pvValue)) _ControlModel.refresh() Case .VALUELIST ' ListBox only ! _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits