Clipboard gadget
In the second tutorial we are introducing new elements in our gadget: Notifications, the use of variables and shared functions and implementing a GTK object.
The function of our gadget is to read the clipboard content with the Text-To-Speech service.
1. Gadget creation
Like in the previous tutorial we are going to create the new gadget and define the gadget information:
- Create a new TGF file by selecting "Create new TGF file" from the menu
- When prompted for a name enter "Clipboard" and save it.
- In the "About" tab:
- Name: "Clipboard"
- Author: "Your name"
- Version: "0.0.1"
- Description: "Clipboard tutorial gadget for Tux Droid."
- In the "Strings" tab:
- name_to_read: in English "Clipboard" and for French "Presse papier". Don't forget to use the "Modify" button every time to store the changes.
2. Declaring the variables and shared functions
- Select the "Codes" tab and open the init.pyp file, by selecting it in the list and clicking the "Edit" button.
- To create shared variables (called parameters in the gadgets) we use the _me.set_param() object in the gadget:
_me.set_param('last_text',")
_me.set_param('current_text',")
- We will need both parameters to compare the clipboard text which already has been read and the text that hasn't been read. Both parameters are initialized with a string of empty characters. The next variable is a Clipboard object from the GTK library.
clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
_me.set_param('clipboard', clipboard)
- Now we are going to create two functions. One to check the contents of the clipboard and the other one to check if the content is text.
def clipboard_accepted_text(clipboard, text, data):
if not text or text == ":
return
_me.set_param('current_text', text)
return
def clipboard_find_info():
gtk.gdk.threads_enter()
_me.get_param('clipboard').request_text(_me.get_funct('clipboard_accepted_text'))
gtk.gdk.threads_leave()
return True
Notice we are using threads_enter() and threads_leave() in the second function. Those functions are required to use GTK in a thread. Later on the clipboard_find_info() function will be used by the gadget notification system working in a concurrent thread. Do the test by removing the protections and you will see the result.
- Now the functions are declared, we need to register them in the gadget to make them available in every gadget code part. To do this, we are using the _me.insert_funct() method.
_me.insert_funct('clipboard_accepted_text', clipboard_accepted_text)
_me.insert_funct('clipboard_find_info', clipboard_find_info)
Below you see the completed init.pyp code with added remarks:# ----------------------------------------------------------------------------
# Definition and initialization of the shared parameters
# ----------------------------------------------------------------------------
# Set a shared parameter for saving the last spoken text
_me.set_param('last_text', "")
# Set a shared parameter for saving the current clipboard text
_me.set_param('current_text', "")
# Create a gtk clipboard object
gtk.gdk.threads_enter()
clipboard = gtk.clipboard_get(gtk.gdk.SELECTION_CLIPBOARD)
gtk.gdk.threads_leave()
# Set a shared parameter with the clipboard object
_me.set_param('clipboard', clipboard)
# ----------------------------------------------------------------------------
# Definition of the shared functions
# ----------------------------------------------------------------------------
def clipboard_accepted_text(clipboard, text, data):
if not text or text == '':
return
_me.set_param('current_text', text)
return
def clipboard_find_info():
gtk.gdk.threads_enter()
_me.get_param('clipboard').request_text(_me.get_funct('clipboard_accepted_text'))
gtk.gdk.threads_leave()
return True
# ----------------------------------------------------------------------------
# Initialization and finalization functions
# ----------------------------------------------------------------------------
def initialization():
"""
Function to initialize the gadget. This function is executed when all gadgets
has been loaded.
"""
pass
def finalization():
"""
Function to finalize the gadget. This function is executed when the gadget is
destroyed.
"""
pass
# ----------------------------------------------------------------------------
# Registeration of the shared functions
# ----------------------------------------------------------------------------
_me.insert_funct('initialization', initialization)
_me.insert_funct('finalization', finalization)
_me.insert_funct('clipboard_accepted_text', clipboard_accepted_text)
_me.insert_funct('clipboard_find_info', clipboard_find_info)
3. Notification
The notification is a crucial part of this gadget. It will verify regularly a condition, and execute an action in case the condition is met.
In our gadget the verification will be "Is there new text in the clipboard?" and the action will be "Read the new text."
- Now select the "Codes" tab and edit the notify.pyp file. Two function are already present in the source code: notify_checker and notify_actuator.
- Enter the following lines of code under notify_checker:
_me.get_funct('clipboard_find_info')()
if _me.get_param('last_text') != _me.get_param('current_text'):
_me.set_param('last_text', _me.get_param('current_text'))
return True
else:
return False
_me.get_funct('clipboard_find_info')() executes the declared function in init.pyp and will search for the last selected text in the clipboard. Next, we verify if the text in the clipboard is the same as the one already read.- In the notify_actuator function: Remove the line with pass and add the following lines of code:
tux.event.on_head_bt_pushed = tux.tts.stoptux.event.on_head_bt_pushed = tux.tts.stop is the command to make the Text-To-Speech stop when pushing the head button of Tux. Next, the text to be read is retrieved and we select the Text-To-Speech voice according to the language of the clipboard text. And finally, the text is read with the Text-To-Speech.
text = _me.get_param('last_text')
tux.tts.select_voice(get_language_voice(text), 100)
tux.tts.speak(text)
The completed code for notify.pyp should look like this:
def notify_checker():
"""
Checker function to start in the notification system.
This function is executed in a loop. The duration between 2 loops is defined in the
'notify_delay' setting.
"""
_me.get_funct('clipboard_find_info')()
if _me.get_param('last_text') != _me.get_param('current_text'):
_me.set_param('last_text', _me.get_param('current_text'))
return True
else:
return False
def notify_actuator():
"""
If the 'notify_checker' function returns True, this function is executed with a high
priority.
"""
tux.event.on_head_bt_pushed = tux.tts.stop
text = _me.get_param('last_text')
tux.tts.select_voice(get_language_voice(text), 100)
tux.tts.speak(text)
- Now save the code and close gedit.
- To configure the frequency to verify the clipboard content:
- Select the "Settings" tab and select the "notify_delay" entry in the "General" list.
- Change the value to 1 instead of 60 seconds.
- Click the "Modify" button to update the change.
This completes our second gadget. Save the gadget, close the Gadget Maker and try it out in the Gadget Manager.
For reference; get the completed clipboard gadget here.