Kexi/Plugins/Macros: Difference between revisions
No edit summary |
|||
(2 intermediate revisions by the same user not shown) | |||
Line 131: | Line 131: | ||
===Diagram of components=== | ===Diagram of components=== | ||
An overview of where KoMacro. | An overview of where KoMacro. [https://kexi-project.org/archive/doc/keximacro.xmi XMI file] | ||
[[Image:KexiMacro.png|350px]] |
Latest revision as of 22:43, 17 May 2023
For a quick introduction to macros see this article for MS Access.
Below is a dump from the old wiki's Macros page.
Generic Macro framework for KEXI planning started: may 2005, js planning extended: since jule 2005, sebsauer development started: october 2005
Definition
Do not confuse Macros with scripts. Macros are simple tasks/actions/commands set up into sequences for later execution. So, they are kind of abstract containers for more specific functionality and useful for automating different tasks.
Macro is a program being dependent on "host" application; Macro has no assigned its own process identifier and private memory area. Script can have all of that. Please read the definition of macros as well.
See also:
- Discussions
- Automating Tasks in Microsoft Access
- Description of what is Macro in MSA
- Example Tutorial of using Macro in MSA
- Embedded MSA Macros
Introduction
Macros are abstract actions providing a flexible way to perform dynamic execution-chains. Think of a Macro as simple container to put extended KAction's together.
Those extended KAction's should implement functionality such as:
- call a Qt QObject's slot.
- connect Qt signals and slots together.
- optional use KDE DCOP-functionality for IPC/RPC. We can't depend on DCOP cause it would require to have the DCOP-Server running on each supported platform and may introduce some security related problems.
- optional use the Kross Scripting framework to call a scripting function.
- pass arguments/parameters like a QString around. So, as example if we have the execution-chain myaction1=>myaction2 the value myaction1 returns could be passed as argument to myaction2.
While a Macro does implement functionality such as:
- collect a tree of extended KAction's or even other Macros and execute them if the Macro itself got executed.
- provide an execution context to define local variables once a Macro got executed. That way we are able to share those variables in all extended KAction's the Macro defines.
- marshal/unmarshal the Macro to/from XML to be able to save and restore the serialized XML into Macro instances.
Use cases
Automating tasks
Automating tasks is one of the main goals that could be archived with Macros. As example it should be quit easy to execute a Macro each time a project got opened and let those Macro open a form named e.g. "startup" if there exists such a form (so, we are able to define startup-dialogs very easy :-). Another example would be that each time a modified project got saved a script-extensions, provided by the scripting bridge Kross, is executed. That way the user is able to start complex tasks with just one single Macro dynamically connected with some Qt signal.
Batch-processing
You may like to automate some work. Let's assume as example we have the actions:
- open a project
- add a new table
- save and close the project
and we may like to execute them with a single click. While it's not possible yet it will be with Macros. Just put all those actions into a Macro and execute the Macro.
Those kind of batch processing needs to implement functionality such as:
- abort execution and throw an exception if one action in the chain failed.
- pass additional arguments/parameters to an action like for the example above; 1) the name of the project that should be opened and 2) the name of the table to add.
- asynchron execution via signal and slots.
- provide an execution context like e.g. access to the KexiMainWindow or to local variables.
Actions in Kexi Forms
Kexi does include an own data-aware WYSIWYG Form Designer to let users build nice forms with just some clicks. At the moment it's possible to connect a button with "Assign Action" with most Kexi actions to execute the defined shared action if the button has been clicked. For example it's possible to call a Kross Scripting function or to just call a slot the KexiMainWindow provides or to connect the button's "click" signal with a Macro (if the user clicks the button the Macro is executed).
More info: Form Actions
Macro and scripting
Kexi provides the Kross scripting bridge to enable using of embedded interpreters like python. That way users are able to write complex python scripts to e.g. access the whole KexiDB functionality. At the moment scripting is used to provide scripting extensions like the "ExportHTML.py" to export a table or a query to a HTML-file or the "ProjectDocumentator.py" that generates some kind of project documentation including details about the tableschemas the project uses. Both scripts are local installed part of the Kexi-application. Scripting code embedded in a project is the other usage-scenario. There the scripts are bind to a single project and not stored local rather then in the project-database. In that case the Scripting editor is used to allow the user to edit those scripts. We arn't able to access e.g. forms from within scripting or activate actions Kexi provides or just call slots the Querydesigner provides. To archive that we would need Kross-wrappers for all those functionality Kexi provides. Also it would blow up the clean API we have right now between Kexi and Kross (the code in kexi/core/scripting.{h|cpp} does handle the whole connection between both code-bases and beside those code there is no dependency between Kexi and the Kross-framework).
Macros don't need to take care of dependencies cause they are designed to depend on the application that uses the Macro-framework. They are much more abstract and limited to fit only a hand full of tasks like automating or batch-processing. They provide a GUI for comfortable editing rather then an own whole interpreter-language you have to learn to deal with.
The Macro-framework provides a bridge between Kexi-functionality and the Kross scripting bridge. Kross would only need to wrap the Macro-framework and earns access to the Kexi-application that way without depending on the application itself and without knowing something about those host-application. So, the Macro-framework would be a bridge between Kexi and Kross and each application that uses the Macro-framework would be transparently accessible by the Kross too (Kross <=> Macro <=> Application). In the end it's all about beeing flexible and having clean and maintable interfaces between those components.
Design
Action
- extends KAction.
- asynchron cause of Qt signals and slots.
- enables manipulation of local variables provided with the execution-context
- each Action has an optional returnvalue.
- each Action has an execution-state like successfully, failed or exception.
- each Action has optional arguments/parameters.
Macro
- Macro is an Action too.
- has children like other Macros, Actions or Functions.
- On execution the childrens are executed in an execution-chain.
Function
- A function is a Qt slot that extends an Action too.
- Each slot defines a receiver that is a QObject instance.
- Each slot defines the receivers QCString-slot that should be invoked.
Context
- If a Macro or an Action got executed a local execution-context is created.
- Each context provides local variables for there scope.
- Each context has runtime-informations like who started the execution and provides access to e.g. the KMainWindow instance.
- Handles exceptions and errors.
Variable
- Could be a QVariant or a QObject.
- Hold predefined or dynamic values.
- e.g. define the result of a Qt slot as value or pass a variable as Qt slot argument/parameter.
- Needs to be dynamic.
Security
It is very difficult to provide a strong security around a scripting interpreter like python. For Macros it's damn easy to limit access cause we are able to define the functionality a Macro is able to access. We don't need to take care of different levels of trust cause Macros are always untrusted. They may come from untrusted sources like a remote database if stored within a KexiProject. They are just not able to access the filesystem and wipe off your home-directory!
While Macros are only little helper to get stuff automated, we may like to add someday a way to access dcop or to call scripting code like an extension. As you may imagine those topics are security-related and we need to take care of any kind of connection we put between Macros and such code.
One way would be to just ask the user if a Macro e.g. tries to call a scriptfunction and warn him. The better cause more flexible solution would be to implement a Security Manager and use it for Macros that try to access possible insecure areas.
- MS Access Security Model
- Macro Security Levels in MS Office 2003
- An introduction to OpenOffice.org Basic
Example solutions
- A GUI for defining function calls. See how it was done with Kommander
- A mockup of macro editing window; note the possibility of adding conditions (i.e. simple control flow). We can imagine it could be possible to add "for each" loop in a similar way.
- How Quanta did it.
- OpenOffice Calc functions. They use on the one hand a categorized flat lists what limits the hierachy to exactly 2 levels and enables fast seeking for a function. On the other hand the structur-page provides a treeview to display additional levels of detail.
- MSA Macro window. Note multiple properties for the "OpenForm" action at the bottom. We can use KProperty for this.
Ideas
- We need to develop 'generic' action data structure (well suited for scripting/kactions/macros) and look what's dependent on what
- looks like there will be a central repository for these, as a KexiProject singleton's member
- recursive: each macro instance is added to that repository, and can be called just as a script's function
- There arn't really differences between sender/signals, receiver/slots and KAction's. E.g. it is possible to execute a signal (emit it) too and therefore from technical perspective a signal could be a slot too. Also a slot could emit signals like executed() or even better executedSuccessfully() and executedFailed().
- If we would handle signals and slots the same way, it would be possible to build complex chains of actions and conditions like SIGNAL(form1.button1.onclick) => AND( SLOT(script1.function1) && SIGNAL(form1.button2.clicked) ).
Development
Diagram of components
An overview of where KoMacro. XMI file