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.

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 like

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.

Usage

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 dynamicly connected with some Qt signal.

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).

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). At the end it's all about beeing flexible and having clean and maintable interfaces between those components.

Variable

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 the Security-Manager and use it for Macros that try to access possible insecure areas.

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 KoProperty 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) ).