Home

lucid dreaming python widget on n900

Updated:
Created:

a slightly more readable (and slightly modified) script that I found when looking for desktop widgets in python on the n900

All credit for this goes to:

http://www.linux.com/community/blogs/n900-desktop-widget-lucid-dreaming-reality-check.html

So, do a

apt-get install hildon-desktop-python-loader python-hildondesktop

Add a file /usr/share/applications/hildon-home/realitycheck.desktop  (download)

[Desktop Entry]
Name=Reality Check
Comment=Reality Check, used to help induce a lucid dreaming and simply vibrates to remind you to do a reality check
Type=python
X-Path=realitycheck.py
X-Multiple=true

 

Add a file /usr/lib/hildon-desktop/realitycheck.py (download)

#!/usr/bin/env python
import os
import gtk
import glib
import osso #high end interface to dbus
import cairo#vector graphic drawing library
import hildon
import hildondesktop
from gtk import Window, Button, Widget, Image

#apt-get install hildon-desktop-python-loader
#apt-get install pythonhildon-desktop
#apt-get install hildon-desktop-python-loader
class realityCheckWidget(hildondesktop.HomePluginItem):
    #applications settings
    config_path='/home/user/.realitycheck'
    vibrate=True
    vibrateRepeat=15

    def __init__(self):
        hildondesktop.HomePluginItem.__init__(self)
        self.load()

        #enable the settings button, and function to call on click
        self.set_settings(True)
        self.connect("show-settings", self.show_options)

        #the vibrate timeout callback
        if self.vibrate==True:
            self.timeout_handler = glib.timeout_add_seconds(60*self.vibrateRepeat, self.vibratePhone)

        #request size of area to render text into.
        self.set_size_request(660,200)

    #draw scene
    def draw_cairo(self, cr): # This currently doesn't work
        #set cairo surface for drawing we require an alpha layer
        cr.set_source_rgba(1.0, 1.0, 1.0, 0.0)
        cr.set_operator(cairo.OPERATOR_SOURCE)
        cr.paint()

        #choose font and style ie bold italic
        cr.select_font_face("tahoma", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD);
        #set the font size
        cr.set_font_size(60);

        #font colour, position and text
        cr.set_source_rgb(65535,65535,65535)
        cr.move_to(20, 50);
        cr.show_text("Are you dreaming ?");

        #second line of text use text path so we can have a fill and stroke
        cr.set_source_rgb(0,0,0)
        cr.move_to(20, 120);
        cr.text_path("Reality Check")
        cr.fill_preserve()
        cr.set_source_rgb(65535,65535,65535)
        cr.stroke()

    #default option selection
    def show_options(self, widget):
        APP_TITLE="Reality Check"
        dialog = gtk.Dialog("Reality Check Options", None, gtk.DIALOG_DESTROY_WITH_PARENT)

                        #add settings button to dialog
        settings_button = hildon.Button(gtk.HILDON_SIZE_HALFSCREEN_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
        settings_button.set_text("Settings", "Change the frequency")
        settings_button.set_alignment(0,0,0,0)
        settings_button.connect('clicked', self.show_settings)
         
                        #add license button to dialog
        about_button = hildon.Button(gtk.HILDON_SIZE_HALFSCREEN_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
        about_button.set_text("About", "More about Author, Copyright and License")
        about_button.set_alignment(0,0,0,0)
        about_button.connect("clicked", self.show_about)

                        #pad the buttons into a box for nice alignment
        hboxRow = gtk.HBox()
        hboxRow.pack_start(settings_button, True, True, 0)
        hboxRow.pack_start(about_button, True, True, 0)

                        #add button row to the dialog and display it
        dialog.vbox.pack_start(hboxRow, True, True, 0) 
        dialog.show_all()
        dialog.run()
        dialog.destroy()

    #Setup the settings UI , store changed parameters 
    def show_settings(self, widget):
        #create a dialog and attach our buttons to the dialog
        dialog = gtk.Dialog("Settings", None, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR)
        btnSave = dialog.add_button(gtk.STOCK_SAVE, gtk.RESPONSE_OK)

        main_vbox = gtk.VBox()
        ts = hildon.TouchSelector()
        ts.add(main_vbox)

        #create the options and labels
        btn0mins = hildon.GtkRadioButton(gtk.HILDON_SIZE_HALFSCREEN_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, None)
        btn0mins.set_label("1 Min")
        btn0mins.set_mode(False)

        btn1mins = hildon.GtkRadioButton(gtk.HILDON_SIZE_HALFSCREEN_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, btn0mins)
        btn1mins.set_label("15 Mins")
        btn1mins.set_mode(False)

        btn2mins = hildon.GtkRadioButton(gtk.HILDON_SIZE_HALFSCREEN_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, btn1mins)
        btn2mins.set_label("30 Mins")
        btn2mins.set_mode(False)

        btn3mins = hildon.GtkRadioButton(gtk.HILDON_SIZE_HALFSCREEN_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, btn1mins)
        btn3mins.set_label("1 Hours")
        btn3mins.set_mode(False)

        btn4mins = hildon.GtkRadioButton(gtk.HILDON_SIZE_HALFSCREEN_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, btn1mins)
        btn4mins.set_label("2 Hours")
        btn4mins.set_mode(False)

                        #toggle vibrate on and off
        btnVibrate = hildon.GtkToggleButton(gtk.HILDON_SIZE_HALFSCREEN_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT)
        btnVibrate.set_label("Vibrate")
        btnVibrate.set_mode(False)

        #what options are currently set, highlight the currently active options
        if self.vibrateRepeat == 1:
            btn0mins.set_active(True)
        elif self.vibrateRepeat == 15:
            btn1mins.set_active(True)
        elif self.vibrateRepeat == 30:
            btn2mins.set_active(True)
        elif self.vibrateRepeat == 60:
            btn3mins.set_active(True)
        elif self.vibrateRepeat == 120:
            btn4mins.set_active(True)
        else:
            btn1mins.set_active(True)  #Fallback
        
        if self.vibrate==True:
            btnVibrate.set_active(True)

        #pack the buttons into a horizontal box
        hBoxLayout = gtk.HBox()
        hBoxLayout.pack_start(btn0mins, True, True, 0)
        hBoxLayout.pack_start(btn1mins, True, True, 0)
        hBoxLayout.pack_start(btn2mins, True, True, 0)
        hBoxLayout.pack_start(btn3mins, True, True, 0)
        hBoxLayout.pack_start(btn4mins, True, True, 0)
        hBoxLayout.pack_end(btnVibrate, True, True, 0)
        main_vbox.pack_start(hBoxLayout, True, True, 10)

        dialog.vbox.add(ts)
        dialog.show_all()
        response = dialog.run()
          
        #Parse the updated settings
        if response == gtk.RESPONSE_OK:
        
            camera_buttons = btn1mins.get_group()
            self.vibrate=btnVibrate.get_active()
        
            for button in camera_buttons:

                selected = button.get_active()
                if selected == True:
                    label=button.get_label()
                    if label=='1 Min':
                        self.vibrateRepeat=1
                    if label=='15 Mins':
                        self.vibrateRepeat=15
                    if label=='30 Mins':
                        self.vibrateRepeat=30
                    if label=='1 Hours':
                        self.vibrateRepeat=60
                    if label=='2 Hours':
                        self.vibrateRepeat=120

            #clear vibrate event and rest if we need to
            if hasattr(self,'timeout_handler'):
                glib.source_remove(self.timeout_handler)
            if self.vibrate==True:
                self.timeout_handler = glib.timeout_add_seconds(60*self.vibrateRepeat, self.vibratePhone)
            
            dialog.destroy()
            self.save()
     
    #Show the about dialog
    def show_about(self, widget):
        dialog = gtk.AboutDialog()
        dialog.set_title("About")
        dialog.set_name('Reality Check')
        dialog.set_version('1.0')
        dialog.set_copyright("Copyright 2010 Oliver Marks")
        dialog.set_authors(["Oliver Marks ",""])
        dialog.set_comments("All logos and trademarks are property of their respective owners and are used for informational purposes only.")
        dialog.set_license("""This program is free software: you can redistribute it and/or
        modify it under the terms of the GNU General Public License as
        published by the Free Software Foundation, either version 3 of
        the License, or (at your option) any later version.

        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied
        warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
        PURPOSE.  See the GNU General Public License for more details.

        You should have received a copy of the GNU General Public
        License along with this program.  If not, see
        .""")
        dialog.set_wrap_license(True)
                        #display the license information dialog
        dialog.show_all()
        dialog.run()
        dialog.destroy()

    #save settings file
    def save(self):
        fp = open(self.config_path,'w')
        if self.vibrate==True:
            fp.write('vibrate:on')
        else:
            fp.write('vibrate:off')
        fp.write('mins:'+str(self.vibrateRepeat)+"")
        fp.close()

    #load settings file
    def load(self):
        if not os.path.exists(self.config_path):
            fp=open(self.config_path,'w')
            fp.write('')
            fp.close()

        fp = open(self.config_path)
        for line in fp.readlines():
            sp=line.strip('').split(':')

            if sp[0]=='vibrate':
                if sp[1]=='on':
                    self.vibrate=True
                else:
                    self.vibrate=False

            if sp[0]=='mins':
                self.vibrateRepeat=int(sp[1])
        fp.close()

    #draw scene when re recieve an expose event ie the scene needs redrawing
    def do_expose_event(self, event):
        cr = self.window.cairo_create()
        cr.rectangle(event.area.x, event.area.y,event.area.width, event.area.height)
        cr.clip()
        self.draw_cairo(cr)

    #setup screen so we can draw on it with cairo
    def do_realize(self):
        screen = self.get_screen()
        self.set_colormap(screen.get_rgba_colormap())
        self.set_app_paintable(True)
        hildondesktop.HomePluginItem.do_realize(self)

    #this code will cause the led on the phone to flash
    def led_flash(self):
        _ENABLE_LED = 'req_led_pattern_activate'
        _DISABLE_LED = 'req_led_pattern_deactivate'
        _LED_PATTERN = 'PatternCommunicationIM'
        rpc.rpc_run(_MCE_SERVICE, _MCE_REQUEST_PATH,_MCE_REQUEST_IF,_ENABLE_LED,rpc_args=(_LED_PATTERN,"",""),use_system_bus=True)
        return True

    #cause the phone to vibrate
    def vibratePhone(self):
        osso_c = osso.Context("osso_test_app", "0.0.1", False)

        _MCE_SERVICE = 'com.nokia.mce'
        _MCE_REQUEST_PATH = '/com/nokia/mce/request'
        _MCE_REQUEST_IF = 'com.nokia.mce.request'

        _VIBRATE = 'req_vibrator_pattern_activate'
        _VIBRATE_PATTERN= 'PatternChatAndEmail'


        rpc = osso.Rpc(osso_c)

        rpc.rpc_run(_MCE_SERVICE, _MCE_REQUEST_PATH,_MCE_REQUEST_IF,_VIBRATE,rpc_args=(_VIBRATE_PATTERN,"",""),use_system_bus=True)
        return True

hd_plugin_type = realityCheckWidget


# Allow the widget to run on its own, without the hildon desktop loader
if __name__ == "__main__":
    import gobject
    gobject.type_register(realityCheckWidget)
    obj = gobject.new(realityCheckWidget, plugin_id="plugin_id")
    obj.show_all()
    gtk.main()

Thats it, install the widget.