CSSU's portrait mode support - WIP
[drlaunch] / drlaunch / src / widget.py
1 #!/usr/bin/env python
2 # coding=UTF-8
3
4 # Copyright (C) 2010 Stefanos Harhalakis
5 #
6 # This file is part of wifieye.
7 #
8 # wifieye is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # wifieye is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with wifieye.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 # $Id: 0.py 2265 2010-02-21 19:16:26Z v13 $
22
23 __version__ = "$Id: 0.py 2265 2010-02-21 19:16:26Z v13 $"
24
25 # HACK
26 # Add the current module's directory to sys.path to bypass
27 # problems when running as widget.
28 # Restore the path at the end of the imports
29 import sys
30 import os
31
32 import gobject
33 orig_path=sys.path[:]
34 tmp_path=os.path.dirname( os.path.realpath( __file__ ) )
35 sys.path.append(tmp_path)
36
37 # End of hack
38
39 import gtk
40 from hildondesktop import *
41 from gtk import gdk
42 from math import pi
43 import cairo
44 import gconf
45 import time
46
47 from subprocess import Popen,PIPE
48
49 from portrait import FremantleRotation
50 import launcher
51 from xdg.IconTheme import getIconPath
52 from win_config import WinConfig
53
54 import config
55 import apps
56 from icon import Icon
57 from icongrid import IconGrid
58 from sig import Disconnector
59
60 import icons
61
62 # Restore path
63 sys.path=orig_path
64
65 # IconGrid must be before HomePluginItem for its connect()
66 # and do_button_*() to override those of HomePluginItem
67 class DrlaunchPlugin(IconGrid, HomePluginItem, FremantleRotation, Disconnector):
68     __gtype_name__ = "DrlaunchPlugin"
69
70     def __init__(self):
71         IconGrid.__init__(self)
72         HomePluginItem.__init__(self)
73         FremantleRotation.__init__(self, 'DrlaunchPlugin',
74             mode=FremantleRotation.AUTOMATIC, dontrotate=True)
75         Disconnector.__init__(self)
76
77         self.winConfig=None
78
79         self.gconf=gconf.client_get_default()
80
81         self.set_settings(True)
82
83         self.id=None
84         self.config=None
85
86         self.reset_mode()
87
88     def get_id0(self):
89         """If this is called from the constructor then the program
90         core dumps """
91         aid=self.get_applet_id()
92
93         # Get desktop activity if D.A.M. is present
94         
95         act="/usr/bin/activity"
96
97         if os.path.exists(act):
98             r=Popen([act, "current"], stdout=PIPE).communicate()
99             activity=r[0].strip()
100         else:
101             activity=""
102
103         ret="%s-%s" % (aid, activity)
104
105         return(ret)
106
107     def get_id(self):
108         if self.id==None:
109             self.id=self.get_id0()
110
111         return(self.id)
112
113     def get_config(self):
114         if self.config==None:
115             id=self.get_id()
116             self.config=config.Config(id)
117
118         return(self.config)
119
120     def get_desktop_orientation(self):
121         """
122         Return desktop orientation
123
124         NOTE: This is the desktop orientation as it was introduced in CSSU.
125         Not the device orientation.
126
127         @return "portrait" or "landscape"
128         """
129
130         sw=gdk.screen_width()
131         sh=gdk.screen_height()
132
133         if sw>=sh:
134             ret='landscape'
135         else:
136             ret='portrait'
137
138         return(ret)
139
140     def is_rotating_desktop(self):
141         """
142         Check whether the desktop will change to portrait mode, as
143         added in CSSU.
144
145         @return True/False
146         """
147
148         c=self.gconf
149
150         # This returns False if the key doesn't exist
151         ret=c.get_bool('/apps/osso/hildon-desktop/ui_can_rotate')
152
153         return(ret)
154
155     def do_realize(self):
156         launcher.init()
157         config=self.get_config()
158         config.load()
159
160         IconGrid.do_realize(self, config)
161
162         self.setSize(config.getSize())
163         self.reloadIcons()
164
165         screen=self.get_screen()
166         self.set_colormap(screen.get_rgba_colormap())
167         self.set_app_paintable(True)
168
169         self.c(self, 'show-settings', self.slot_show_settings)
170         self.c(self, 'long-press', self.signalLongpress)
171         self.c(self, 'click', self.signalClick)
172         self.c(self, 'notify', self.signalNotify)
173
174         HomePluginItem.do_realize(self)
175
176     def on_orientation_changed(self, orientation):
177         # Avoid bugs
178         if orientation==None or len(orientation)==0:
179             return
180
181         # Get the first character of the string (l/p)
182         o=orientation[0]
183
184         # Get desktop orientation
185         #do=self.get_desktop_orientation()
186
187         # Is desktop rotation (per CSSU) enabled?
188         rd=self.is_rotating_desktop()
189
190         #print "desktop: %s / %s, device: %s" % (do, rd, o)
191
192         # In case of a rotating desktop, force orientation to be
193         # 'landscape'
194         if rd:
195             # CSSU Portrait mode?
196             if o=='p':
197                 csp=True
198             else:
199                 csp=False
200
201             o='l'
202
203         self.setCSSUPortrait(csp)
204
205         if rd:
206             self.resize2()
207
208         self.setMode(o)
209
210 #       self.queue_draw()
211
212     def do_expose_event(self, event):
213         IconGrid.do_expose_event(self, event)
214         HomePluginItem.do_expose_event(self, event)
215         self.reset_mode()
216
217     def slot_show_settings(self, dt):
218         if self.winConfig!=None:
219             # Doesn't work
220             # self.winConfig.show_all()
221             return
222
223         s=WinConfig(self.get_config())
224         s.show_all()
225         #s.c(s, 'delete-event', self.slotConfigDestroy)
226         self.c(s, 'delete-event', self.slotConfigDestroy)
227         #s.connect('destroy', self.slotConfigDestroy)
228         self.winConfig=s
229
230     def slotConfigDestroy(self, sender, event):
231 #       print "Sender:", sender
232         dt=sender.getData()
233
234         # Disconnect signals for that object in order to be deleted
235         self.dis_finish(self.winConfig)
236         #self.winConfig.finish()
237         #self.winConfig.destroy()
238
239         self.winConfig=None
240
241         cfg=self.get_config()
242
243         cfg.setSize(dt['size'])
244         cfg.setApps(dt['apps'])
245         cfg.setIndiv(dt['indiv'])
246         cfg.setLongpress(dt['longpress'])
247         cfg.setAnimate(dt['animate'])
248         cfg.setNoBg(dt['nobg'])
249         cfg.setThemeBg(dt['themebg'])
250         cfg.setIconSize(dt['iconsize'])
251         cfg.setIconPadding(dt['iconpadding'])
252         cfg.setIconMargin(dt['iconmargin'])
253         cfg.save()
254         
255         # Resize widget
256         self.icons.resizeMax()
257         self.setSize(dt['size'])
258         self.reloadIcons()
259
260         # Free memory that is used for animations if animations are disabled
261         if not dt['animate']:
262             self.clearAnimationCache()
263
264         # Free memory of backgrounds in case they changed
265         self.clearBgCache()
266
267         self.queue_draw()
268
269 #       print "slot-config-destroy-end"
270
271         return(False)
272
273     def handle_click(self, sender, icon):
274         """ common handler for longpress and click """
275         if icon.appname!=None and icon.appname!='':
276             launcher.launch(icon.appname)
277
278     def signalLongpress(self, sender, icon):
279         self.handle_click(sender, icon)
280
281     def signalClick(self, sender, icon):
282         config=self.get_config()
283
284         if not config.getLongpress():
285             self.handle_click(sender, icon)
286
287     def signalNotify(self, sender, property):
288         if property.name=='is-on-current-desktop':
289             v=self.get_property(property.name)
290             if v and self.draw_pending:
291                 self.queue_draw()
292
293     def resize2(self):
294         config=self.get_config()
295
296         w=(self.size[0] * config.iconsize) + \
297             (self.size[0] * config.getIconSpace())
298         h=(self.size[1] * config.iconsize) + \
299             (self.size[1] * config.getIconSpace())
300
301         if self.cssuportrait:
302             (w,h)=(h,w)
303
304         #print "w,h:", w, h
305         self.set_size_request(w, h)
306         self.resize(w, h)
307         self.queue_draw()
308
309     def setSize(self, size):
310         IconGrid.setSize(self, size)
311         self.resize2()
312
313 hd_plugin_type = DrlaunchPlugin
314
315 if __name__=="__main__":
316
317     icons.init_icons()
318
319     #gobject.type_register(hd_plugin_type)
320     obj=gobject.new(hd_plugin_type, plugin_id="plugin_id")
321     obj.show_all()
322     gtk.main()
323
324
325
326 # vim: set ts=8 sts=4 sw=4 noet formatoptions=r ai nocindent:
327