4.2. Architecture

This section explains some components available and used everywhere in the application. These include services and common modules.

4.2.1. Encoding

Unlike the GTK client, KTiny doesn't convert all incoming server strings into UTF-8 using the encode('utf-8'). This makes it possible to use the automatic conversions between QString and python unicode strings.

You'll likely only need to care about string encodings when passing a string received from the server into a XML parser. There you should use the encode('utf-8') function.

Example extracted from bin/model/screen/screen.py:


dom = xml.dom.minidom.parseString(arch.encode('utf-8'))
   

4.2.2. XML-RPC

As you already learned KTiny uses the XML-RPC protocol to communicate with the server. The lower level API to access the server can be found at bin/rpc.py. This file contains a clear set of classes and functions that allow you to easily acces the most common server functionalities.

There are mainly three classes that help you with server interaction:

4.2.3. Local services

KTiny has inherited from the GTK client a simple mechanism for calling local or internal services. Though we call them services they're not any kind of server waiting for requests. They're simply objects for which we create an alias. There are four such services with the current version (though plugins could create their own). These are: gui.main, gui.window, action.main and spool.

TinyERP uses this mechanism to allow certain actions to be specified from server modules. For example, menu entries use action.main services to specify what should happen when it's triggered.

In order to request one of these services you should import the service module and call the LocalService function with the appropiate service name. The function will simply return the object that has itself associated with the service name. Example:


import service

obj = service.LocalService('action.main')
obj._exec_action(res['action'],self.datas)
   

If you want to create a new service then you need to create a new class that inherits from service.Service, and put the desired functions in it. See the example below:


import service

class Spool(service.Service):
	def __init__(self):
		service.Service.__init__(self, 'newservice')
		self.obj_sub = {}
		self.report = {}

	def sayHello(self):
		QMessageBox.information( None, 'Say Hello', 'Hello!' )

Spool()
object = service.LocalService('newservice')
object.sayHello()
   

The following subsections document the various local services available.

4.2.3.1. action.main

This service has functions for executing several actions.

  • execute(self, act_id, datas, type=None)

    Executes action with identifier act_id with datas as parameters. If given, type can be any of:

    • ir.actions.act_window which will open a new tab.

    • ir.actions.wizard which will execute a wizard.

    • ir.actions.report.custom which will open a new custom report.

    • ir.actions.report.xml which will open a new report.

  • exec_report(self, name, data)

    Opens the report name. name can be custom or the name of an existing report in ir_act_report_xml.

  • _exec_action(self, action, datas)

  • exec_keyword(self, keyword, data={}, adds={})

4.2.3.2. spool

This service provide a publisher/subscriber mechanism. The functions that can be used are:

  • subscribe(self, name, method, datas={})

    Which subscribes the function method to the name service. When the method function will be called datas (a dictionary) will be passed as parameters.

  • publish(self, name, obj, datas)

    Which publishes the service name. obj should be an object that will be passed as first argument to all subscribed functions and datas (a dictionary) will be passed as parameters among with the datas specified in the subscription.

4.2.3.3. gui.window

This service provides only a function which opens a new tab with the appropiate form or tree:


     create(self, view_id, model, res_id=False, domain=None, view_type='form', window=None, context={}, mode=None)
    

Where view_id is the view identifier or if None then the default view is used. model is a string with the model name of the model to show (e.g. ir.attachment). res_id identifier list of all items to show. domain is the domain for the data to show. view_type can be one of form which will show a new Screen or tree which will show a tab like the menu with the appropiate data. window is unused in KTiny context let's you specify a context for the data to show. mode is used only when view_type='form' and is a string with a list of coma separated view types (the default is 'form,tree').

4.2.4. common

The common module contains some functions and classes that are used and shared through all the application.

4.2.5. DBus

KTiny currently provides a very simple DBus inteface. A smarter interface will be provided in the future but some things are already possible.

Current interface provides only two methods:

Following a sample shell session using qdbus to query KTiny DBus interface:


$ qdbus org.ktiny.Interface /TinyERP services
spool
action.main
gui.main
gui.window
$ qdbus org.ktiny.Interface /TinyERP call "gui.window" "create" "None, 'ir.attachment', False, [], 'form', mode='form,tree'"
   

This example queries all available services in KTiny and then opens a new tab with the attachments form.