Multiple instance support.
authorStefanos Harhalakis <v13@v13.gr>
Fri, 16 Jul 2010 19:26:14 +0000 (19:26 +0000)
committerStefanos Harhalakis <v13@v13.gr>
Fri, 16 Jul 2010 19:26:14 +0000 (19:26 +0000)
Rewrote config (now a class) to allow for multiple instances.
Made long-press an option.
Allow for individual icon rotation.
Bug fixes.
v0.3

setup.py
src/config.py
src/icon.py
src/icongrid.py
src/icons.py
src/widget.py
src/win_config.py

index e8b40e2..d440b73 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -24,7 +24,7 @@ from distutils.core import setup
 
 setup(
     name='drlaunch',
-    version="0.1",
+    version="0.3",
     description="DrLaunch",
     author="Stefanos Harhalakis",
     author_email="v13@v13.gr",
index f58b2ec..fad6826 100755 (executable)
@@ -25,7 +25,7 @@ __version__ = "$Id: 0.py 2265 2010-02-21 19:16:26Z v13 $"
 import os
 import pickle
 
-version = "0.2"
+version = "0.3"
 
 try:
     from glib import get_user_config_dir
@@ -38,71 +38,6 @@ except:
 
        return(cfg)
 
-size = (2,2)
-iconsize = 64
-iconspace = 42
-apps=None
-indiv=False
-id=None                # Applet ID
-longpress=True
-
-maxsz=(4,4)
-
-def setSize(sz):
-    global size
-
-    size=sz
-
-def getSize():
-    global size
-
-    return(size)
-
-def getMaxSize():
-    global maxsz
-
-    return(maxsz)
-
-def setIndiv(_indiv):
-    global indiv
-
-    indiv=_indiv
-
-def getIndiv():
-    global indiv
-
-    return(indiv)
-
-def setLongpress(_lp):
-    global longpress
-
-    longpress=_lp
-
-def getLongpress():
-    global longpress
-
-    return(longpress)
-
-def setApps(aps):
-    """ apps is a dictionary of (x,y)=>appname """
-    global apps
-
-    apps=aps
-
-def getApps():
-    global apps
-
-    if apps==None:
-       tmp={
-           (0,0):  'rtcom-call-ui',
-           (0,1):  'rtcom-messaging-ui',
-           (1,0):  'browser',
-           (1,1):  'osso-addressbook',
-           }
-       setApps(tmp)
-
-    return(apps)
-
 def ensure_dir():
     dir0=get_user_config_dir()
     dir=dir0+'/drlaunch'
@@ -119,117 +54,155 @@ def get_config_fn():
 
     return(ret)
 
-def save():
-    global id
+class Config:
+    def __init__(self, id):
+       self.id=id
 
-    check_init()
+       self.size = (2,2)
+       self.iconsize = 64
+       self.iconspace = 42
+       self.apps=None
+       self.indiv=False
+       self.longpress=True
 
-    dt=load_all()
+       self.maxsz=(4,4)
 
-    if dt==None:
-       dt={
-           'version':  3,
-           'data':     {},
-           }
+    def setSize(self, sz):
+       self.size=sz
 
-    dt['data'][id]={
-       'size':         getSize(),
-       'apps':         getApps(),
-       'indiv':        getIndiv(),
-       'longpress':    getLongpress(),
-       }
+    def getSize(self):
+       return(self.size)
 
-    fn=get_config_fn()
+    def getMaxSize(self):
+       return(self.maxsz)
 
-    st=pickle.dumps(dt)
-    f=file(fn, 'w')
-    f.write(st)
-    f.close()
+    def getIconSize(self):
+       return(self.iconsize)
 
-def parse_v1(dt0):
-    """ Convert a v1 config to v2 """
-    global id
+    def setIndiv(self, indiv):
+       self.indiv=indiv
 
-    ret={
-       'version':  2,
-       'data':     {},
-       }
+    def getIndiv(self):
+       return(self.indiv)
 
-    ret['data'][id]={
-       'size':     dt0['size'],
-       'apps':     dt0['apps'],
-       }
+    def setLongpress(self, lp):
+       self.longpress=lp
 
-    return(ret)
+    def getLongpress(self):
+       return(self.longpress)
 
-def parse_v2(dt):
-    global id
+    def setApps(self, aps):
+       """ apps is a dictionary of (x,y)=>appname """
+       self.apps=aps
 
-    # Perhaps copy dt?
+    def getApps(self):
+       if self.apps==None:
+           tmp={
+               (0,0):  'rtcom-call-ui',
+               (0,1):  'rtcom-messaging-ui',
+               (1,0):  'browser',
+               (1,1):  'osso-addressbook',
+               }
+           self.setApps(tmp)
 
-    dt['version']=3
+       return(self.apps)
 
-    for i in dt['data']:
-       dt['data'][i]['indiv']=False
-       dt['data'][i]['size']=(dt['data'][i]['size'], dt['data'][i]['size'])
-       dt['data'][i]['longpress']=True
+    def save(self):
+       self.check_init()
 
-    return(dt)
+       dt=self.load_all()
 
-def load_all():
-    fn=get_config_fn()
+       if dt==None:
+           dt={
+               'version':  3,
+               'data': {},
+               }
 
-    try:
-       f=file(fn, 'r')
-       st=f.read()
+       dt['data'][self.id]={
+           'size':         self.getSize(),
+           'apps':         self.getApps(),
+           'indiv':        self.getIndiv(),
+           'longpress':    self.getLongpress(),
+           }
+
+       fn=get_config_fn()
+
+       st=pickle.dumps(dt)
+       f=file(fn, 'w')
+       f.write(st)
        f.close()
-       ret=pickle.loads(st)
 
-       if ret==None:
-           ret=None
-       else:
-           if ret['version']==1:
-               ret=parse_v1(ret)
+    def parse_v1(self, dt0):
+       """ Convert a v1 config to v2 """
+       ret={
+           'version':      2,
+           'data':         {},
+           }
 
-           if ret['version']==2:
-               ret=parse_v2(ret)
-    except:
-       ret=None
+       ret['data'][self.id]={
+           'size':         dt0['size'],
+           'apps':         dt0['apps'],
+           }
 
-    return(ret)
+       return(ret)
+
+    def parse_v2(self, dt):
+       # Perhaps copy dt?
+
+       dt['version']=3
 
-def load():
-    global id
+       for i in dt['data']:
+           dt['data'][i]['indiv']=False
+           dt['data'][i]['size']=(dt['data'][i]['size'], dt['data'][i]['size'])
+           dt['data'][i]['longpress']=True
 
-    check_init()
+       return(dt)
 
-    fn=get_config_fn()
+    def load_all(self):
+       fn=get_config_fn()
+
+       try:
+           f=file(fn, 'r')
+           st=f.read()
+           f.close()
+           ret=pickle.loads(st)
+
+           if ret==None:
+               ret=None
+           else:
+               if ret['version']==1:
+                   ret=parse_v1(ret)
+
+               if ret['version']==2:
+                   ret=parse_v2(ret)
+       except:
+           ret=None
 
-    dt0=load_all()
+       return(ret)
 
-    if not dt0['data'].has_key(id):
-       return
+    def load(self):
+       self.check_init()
 
-    dt=dt0['data'][id]
+       fn=get_config_fn()
 
-    setSize(dt['size'])
-    setApps(dt['apps'])
-    setIndiv(dt['indiv'])
-    setLongpress(dt['longpress'])
+       dt0=self.load_all()
 
-def init(_id):
-    global id
+       if not dt0['data'].has_key(self.id):
+           return
 
-    id=_id
+       dt=dt0['data'][self.id]
 
-def check_init():
-    global id
+       self.setSize(dt['size'])
+       self.setApps(dt['apps'])
+       self.setIndiv(dt['indiv'])
+       self.setLongpress(dt['longpress'])
 
-    if id==None:
-       import sys
+    def check_init(self):
+       if self.id==None:
+           import sys
 
-       print "config.init() not done"
-       sys.exit(1)
+           print "config.init() not done"
+           sys.exit(1)
 
 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent:
 
index 335f6e4..c1a8096 100755 (executable)
@@ -36,21 +36,21 @@ import launcher
 from xdg.IconTheme import getIconPath
 
 
-import config
+#import config
 import apps
 
-def getIcon(name):
-    ico=getIconPath(name, config.iconsize)
-    ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, config.iconsize,
-       config.iconsize)
+def getIcon(name, iconsize):
+    ico=getIconPath(name, iconsize)
+    ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
 
     return(ret)
 
 class Icon(gobject.GObject):
-    def __init__(self, isconfig):
+    def __init__(self, isconfig, config):
        self.__gobject_init__()
 
        self.isconfig=isconfig
+       self.config=config
 
        self.name=None
        self.icon=None
@@ -82,7 +82,7 @@ class Icon(gobject.GObject):
        self.invalidate()
 
     def getSize(self):
-       return(config.iconsize+config.iconspace)
+       return(self.config.iconsize+self.config.iconspace)
 
     def draw(self, cr, x, y, mode):
        self.x=x
@@ -95,19 +95,22 @@ class Icon(gobject.GObject):
        cr.set_source_rgba(0.1, 0.1, 0.1, 1)
        cr.set_line_width(5)
 
-       if self.ispressed:
+       #if self.ispressed:
+       if self.timePressed() <= self.presstime or self.ispressed:
            t=1.0 * min(self.timePressed(), self.presstime) / self.presstime
            g=0.3+0.5*t
            b=0.3+0.7*t
            cr.set_source_rgba(0, g, b, 0.7)
+           print "t:", t
+
        else:
            cr.set_source_rgba(0.3, 0.3, 0.3, 0.7)
 
-       x3=x + (config.iconspace/6)
-       y3=y + (config.iconspace/6)
+       x3=x + (self.config.iconspace/6)
+       y3=y + (self.config.iconspace/6)
 
        r=10    # Radius
-       w=config.iconsize+(config.iconspace*2/3)
+       w=self.config.iconsize+(self.config.iconspace*2/3)
 
        cr.move_to(x3+r, y3)
        cr.arc(x3+w-r,  y3+r,   r,          pi*1.5, pi*2)
@@ -132,8 +135,8 @@ class Icon(gobject.GObject):
            icon2=icon.rotate_simple(gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
 
        cr.save()
-       x3=x + (config.iconspace/2)
-       y3=y + (config.iconspace/2)
+       x3=x + (self.config.iconspace/2)
+       y3=y + (self.config.iconspace/2)
        cr.set_source_pixbuf(icon2, x3, y3)
        cr.paint()
        cr.restore()
@@ -141,8 +144,10 @@ class Icon(gobject.GObject):
        return(False)
 
     def timerPressed(self):
-       if not self.ispressed:
-           return(False)
+#      if not self.ispressed:
+#          return(False)
+
+       print "timerPressed"
 
        self.invalidate()
 
@@ -190,7 +195,7 @@ class Icon(gobject.GObject):
        if window==None:
            return
 
-       w=config.iconsize + config.iconspace
+       w=self.config.iconsize + self.config.iconspace
        rect=gdk.Rectangle(self.x, self.y, w, w)
        gdk.Window.invalidate_rect(window, rect, True)
 
index 5184d09..670c80f 100755 (executable)
@@ -32,20 +32,19 @@ import cairo
 import time
 
 from portrait import FremantleRotation
-from xdg.IconTheme import getIconPath
+#from xdg.IconTheme import getIconPath
 
-import config
+#import config
 import apps
 import icon
 from icon import Icon
 from icons import Icons
 
-def getIcon(name):
-    ico=getIconPath(name, config.iconsize)
-    ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, config.iconsize,
-       config.iconsize)
-
-    return(ret)
+#def getIcon(name, iconsize):
+#    ico=getIconPath(name, iconsize)
+#    ret=gtk.gdk.pixbuf_new_from_file_at_size(ico, iconsize, iconsize)
+#
+#    return(ret)
 
 #class IconGrid(gtk.Widget, FremantleRotation):
 class IconGrid(object):        #(gobject.GObject):
@@ -56,20 +55,15 @@ class IconGrid(object):     #(gobject.GObject):
 
        self.isconfig=isconfig
 
-       self.icons=Icons(isconfig)
-
-       self.setMode('l')
+       self.icons=None
+       self.lasticon=None  # The last icon that got selected
 
-       # Maybe fix those:
-#      w=(config.getSize() * config.iconsize) + \
-#          (config.getSize()) * config.iconspace
-       #self.set_size_request(w, w)
+    def do_realize(self, config):
+       self.config=config
 
-#      self.setSize(config.getSize())
+       self.icons=Icons(self.isconfig, self.config)
+       self.setMode('l')
        self.setSize((4,4))
-
-       self.lasticon=None  # The last icon that got selected
-
        self.reloadIcons()
 
     def connect(self, what, *args):
@@ -94,9 +88,9 @@ class IconGrid(object):       #(gobject.GObject):
     def iconAt(self, x, y):
        """ Get icon at coordinates x,y. X and Y are in pixels """
 
-       w=config.iconsize + config.iconspace
+       w=self.config.iconsize + self.config.iconspace
 
-       if self.mode=='l' or config.getIndiv():
+       if self.mode=='l' or self.config.getIndiv():
            x2=int(x / w)
            y2=int(y / w)
        else:
@@ -113,14 +107,15 @@ class IconGrid(object):   #(gobject.GObject):
        return(ret)
 
     def _draw(self, cr, event):
-       w=config.iconsize + config.iconspace
+       w=self.config.iconsize + self.config.iconspace
        for x,y in self.icons:
-           if self.mode=='l' or config.getIndiv():
-               x2=x * (config.iconsize + config.iconspace)
-               y2=y * (config.iconsize + config.iconspace)
+           if self.mode=='l' or self.config.getIndiv():
+               x2=x * (self.config.iconsize + self.config.iconspace)
+               y2=y * (self.config.iconsize + self.config.iconspace)
            else:
-               x2=y * (config.iconsize + config.iconspace)
-               y2=(self.size[1]-x-1) * (config.iconsize + config.iconspace)
+               x2=y * (self.config.iconsize + self.config.iconspace)
+               y2=(self.size[1]-x-1) * \
+                       (self.config.iconsize + self.config.iconspace)
 
            # Only repaint the needed icons
            rect=gdk.Rectangle(x2, y2, w, w)
@@ -217,17 +212,21 @@ class IconGrid(object):   #(gobject.GObject):
 #      self.setMode(o)
 
 class IconGridWidget(IconGrid, gtk.Widget):
-    def __init__(self, isconfig):
+    def __init__(self, isconfig, config):
        IconGrid.__init__(self, isconfig)
        gtk.Widget.__init__(self)
 
+       self.config=config
+
+       IconGrid.do_realize(self, self.config)
+
        if isconfig:
-           maxsz=config.getMaxSize()
-           w=maxsz[0] * (config.iconsize + config.iconspace)
-           h=maxsz[1] * (config.iconsize + config.iconspace)
+           maxsz=self.config.getMaxSize()
+           w=maxsz[0] * (self.config.iconsize + self.config.iconspace)
+           h=maxsz[1] * (self.config.iconsize + self.config.iconspace)
        else:
-           w=self.size[0] * (config.iconsize + config.iconspace)
-           h=self.size[1] * (config.iconsize + config.iconspace)
+           w=self.size[0] * (self.config.iconsize + self.config.iconspace)
+           h=self.size[1] * (self.config.iconsize + self.config.iconspace)
 
        self.set_size_request(w, h)
 
index 9c344ee..015273b 100755 (executable)
@@ -22,7 +22,7 @@
 
 __version__ = "$Id: 0.py 2265 2010-02-21 19:16:26Z v13 $"
 
-import config
+#import config
 import apps
 import icon
 from icon import getIcon, Icon
@@ -42,22 +42,23 @@ class IconIter:
        return(ret)
 
 class Icons(gobject.GObject):
-    def __init__(self, isconfig):
+    def __init__(self, isconfig, config):
        self.__gobject_init__()
        self.icons={}
        self.allicons={}
        self.size=0
        self.isconfig=isconfig
+       self.config=config
 
        # signal handlers
        self.h={}
 
        # setup allicons
-       maxsz=config.getMaxSize()
+       maxsz=self.config.getMaxSize()
        for x in xrange(maxsz[0]):
            for y in xrange(maxsz[1]):
                k=(x,y)
-               ico=Icon(self.isconfig)
+               ico=Icon(self.isconfig, self.config)
                self.allicons[k]=ico
                self.connect_one(ico)
 
@@ -143,8 +144,8 @@ class Icons(gobject.GObject):
 #          'tecnoballz', 'ncalc', 'rtcom-call-ui', 'rtcom-messaging-ui',
 #          'extcalllog', 'browser', 'modest', 'osso-addressbook']
 
-       wapps=config.getApps()
-       sz=config.getSize()
+       wapps=self.config.getApps()
+       sz=self.config.getSize()
 
        for k in wapps:
            x,y=k
@@ -155,7 +156,7 @@ class Icons(gobject.GObject):
            if appname!=None:
                app=apps.readOne(appname)
                if app!=None:
-                   app['icon2']=getIcon(app['icon'])
+                   app['icon2']=getIcon(app['icon'], self.config.getIconSize())
                    self.get(x,y).setApp(app)
            else:
                self.get(x,y).setApp(None)
index bf490f2..409cb3c 100755 (executable)
@@ -44,6 +44,8 @@ from math import pi
 import cairo
 import time
 
+from subprocess import Popen,PIPE
+
 from portrait import FremantleRotation
 import launcher
 from xdg.IconTheme import getIconPath
@@ -68,25 +70,49 @@ class DrlaunchPlugin(IconGrid, HomePluginItem, FremantleRotation):
        self.winConfig=None
 
        self.set_settings(True)
-       self.connect('show-settings', self.slot_show_settings)
-       self.connect('long-press', self.signalLongpress)
-       self.connect('click', self.signalClick)
 
-    def get_id(self):
+       self.id=None
+       self.config=None
+
+    def get_id0(self):
        """If this is called from the constructor then the program
        core dumps """
        aid=self.get_applet_id()
 
-       ret="%s" % aid
+       # Get desktop activity if D.A.M. is present
+       
+       act="/usr/bin/activity"
+
+       if os.path.exists(act):
+           r=Popen([act, "current"], stdout=PIPE).communicate()
+           activity=r[0].strip()
+       else:
+           activity=""
+
+       ret="%s-%s" % (aid, activity)
 
        return(ret)
 
-    def do_realize(self):
-       #print "realize"
+    def get_id(self):
+       if self.id==None:
+           self.id=self.get_id0()
+
+       return(self.id)
+
+    def get_config(self):
+       if self.config==None:
+           id=self.get_id()
+           self.config=config.Config(id)
 
+       return(self.config)
+
+    def do_realize(self):
        launcher.init()
-       config.init(self.get_id())
+       config=self.get_config()
        config.load()
+
+       IconGrid.do_realize(self, config)
+
        self.setSize(config.getSize())
        self.reloadIcons()
 
@@ -94,6 +120,10 @@ class DrlaunchPlugin(IconGrid, HomePluginItem, FremantleRotation):
        self.set_colormap(screen.get_rgba_colormap())
        self.set_app_paintable(True)
 
+       self.connect('show-settings', self.slot_show_settings)
+       self.connect('long-press', self.signalLongpress)
+       self.connect('click', self.signalClick)
+
        HomePluginItem.do_realize(self)
 
     def on_orientation_changed(self, orientation):
@@ -111,7 +141,7 @@ class DrlaunchPlugin(IconGrid, HomePluginItem, FremantleRotation):
            # self.winConfig.show_all()
            return
 
-       s=WinConfig()
+       s=WinConfig(self.get_config())
        s.show_all()
        s.connect('destroy', self.slotConfigDestroy)
        self.winConfig=s
@@ -120,6 +150,9 @@ class DrlaunchPlugin(IconGrid, HomePluginItem, FremantleRotation):
        self.winConfig=None
 
        dt=sender.getData()
+
+       config=self.get_config()
+
        config.setSize(dt['size'])
        config.setApps(dt['apps'])
        config.setIndiv(dt['indiv'])
@@ -141,10 +174,14 @@ class DrlaunchPlugin(IconGrid, HomePluginItem, FremantleRotation):
        self.handle_click(sender, icon)
 
     def signalClick(self, sender, icon):
+       config=self.get_config()
+
        if not config.getLongpress():
            self.handle_click(sender, icon)
 
     def resize(self):
+       config=self.get_config()
+
        w=(self.size[0] * config.iconsize) + \
            (self.size[0] * config.iconspace)
        h=(self.size[1] * config.iconsize) + \
index 016de49..5e638c3 100755 (executable)
@@ -31,19 +31,22 @@ from hildon import StackableWindow
 #from portrait import FremantleRotation
 #from xdg.IconTheme import getIconPath
 
-import config
+#import config
 import apps
 from icon import Icon, getIcon
 from icongrid import IconGridWidget
 
 class WinConfig(StackableWindow):
-    def __init__(self, *args):
+    def __init__(self, config, *args):
        StackableWindow.__init__(self)
 
+       self.config=config
+
        self.setupUi()
 
     def setupUi(self):
-       self.igw=IconGridWidget(True)
+       self.igw=IconGridWidget(True, self.config)
+#      self.igw.do_realize()
 #      self.igw.setSize(config.getSize())
 
        hbox=gtk.HBox()
@@ -60,7 +63,7 @@ class WinConfig(StackableWindow):
 #      hbox.add(vbox)
        al.add(vbox)
 
-       maxsz=config.getMaxSize()
+       maxsz=self.config.getMaxSize()
 
        # ----------------------------------------------
        vbox.add(gtk.Label('Width:'))
@@ -114,9 +117,9 @@ class WinConfig(StackableWindow):
 
        self.ignore_toggle=False
 
-       self.setSize(config.getSize())
-       self.setIndiv(config.getIndiv())
-       self.setLongpress(config.getLongpress())
+       self.setSize(self.config.getSize())
+       self.setIndiv(self.config.getIndiv())
+       self.setLongpress(self.config.getLongpress())
 
     def slotLongpress(self, sender, icon):
        self.doConfig(icon)
@@ -149,7 +152,7 @@ class WinConfig(StackableWindow):
 
        self.ignore_toggle=True
 
-       maxsz=config.getMaxSize()
+       maxsz=self.config.getMaxSize()
 
        id=sz[0]-1