Active Topics

 


Reply
Thread Tools
Posts: 35 | Thanked: 5 times | Joined on Sep 2007
#11
Hi,

I have not tested if I get anything appearing on the screen but at least python is happy with it:
Code:
import gtk
import hildondesktop
e = gtk.eventbox()
screen = e.get_screen()
rgba = gtk.gdk.Screen.get_rgba_colormap(screen)
e.set_colormap(rgba)
So this is just a small piece of incomplete code but it's accepted by the interpreter. I got some example code from somewhere, I really don't remember where I got it, anyway in it the screen line was commented out.
Also in pyphantom the code does not work but in the IT itself it's just fine.
 
Posts: 99 | Thanked: 65 times | Joined on Jan 2008 @ Finland
#12
I know this thread started with code snippet in Python, but if you're interested, I wrote a simple example in C. It should show, among some other things, how to use real transparency in a Desktop plugin.
 
Posts: 25 | Thanked: 8 times | Joined on Feb 2008
#13
Originally Posted by wnd View Post
I know this thread started with code snippet in Python, but if you're interested, I wrote a simple example in C. It should show, among some other things, how to use real transparency in a Desktop plugin.
Thank you!

I'm not a C programmer, but I've tried to sift through your code and find the Python parallels. If I'm understanding it correctly, it looks like the initialization code (__init__ in Python) is example_init(). In there, the relevant bit for transparency seems to be:

Code:
rgba_colormap = gdk_screen_get_rgba_colormap(gdk_screen_get_default());
	
if (rgba_colormap != NULL) {
	gtk_widget_set_colormap(GTK_WIDGET(plugin), rgba_colormap);
}
Which I translate to Python as:

Code:
rgba_colormap = gtk.gdk.screen_get_default().get_rgba_colormap()

if rgba_colormap != None:
	self.set_colormap(rgba_colormap)
This seems to return the screen color map OK, but when it's applied to the plugin, the whole desktop crashes. So clearly I'm missing something.

Anyone have any thoughts?
 
Posts: 35 | Thanked: 5 times | Joined on Sep 2007
#14
Looks like I'm stuck with this. The code is kind of alright but does not work. I need a working example of a complete plugin...
I've been reading these:
GTK images: http://www.pygtk.org/pygtk2tutorial/sec-Images.html
window compositing: http://library.gnome.org/devel/pygtk...gdkwindow.html
Lucas's blog: http://blogs.gnome.org/lucasr/2007/0...ildon-desktop/

However Khertan used frame as the 'root' element or window and not gtk window as the base element and all these examples are based on using windows.

Only the gtk tutorials have complete code and don't have the hildon features obviously and I could not find complete program from Lucas either.

Well the frame looks a bit dull but I can live with it.

Anybody know how to stack two images? You know for example I have one image as background and the other image is drawn over the background image.
 
Posts: 35 | Thanked: 5 times | Joined on Sep 2007
#15
This pygtk faq looks promising: http://faq.pygtk.org/index.py?req=sh...=faq08.018.htp
I did some tests and I think it sort of works. Ran a test on the IDE. I need to retest on the IT and also do other tests...

I made a composite image of 2 png's but the other image was much smaller than the other so it appeared in the top left corner in the composite image.

Anyway I'm not sure how much this concerns the original question about the background of the home plugin.

And here is an example how to setup a window background:http://faq.pygtk.org/index.py?req=sh...=faq08.013.htp
Except that so far we have used frames.

Last edited by icer; 2008-02-28 at 15:20.
 
Posts: 87 | Thanked: 98 times | Joined on Oct 2007 @ Austria
#16
Originally Posted by SpiritGeek View Post
However, I'm not getting anywhere in actually making it work. Here's my best guess (in Python):

Code:
PixBuf = gtk.gdk.pixbuf_new_from_file("image.png")
Image = gtk.image_new_from_pixbuf(PixBuf)
Button = gtk.Button()
Button.set_image(Image)
MapMask = PixBuf.render_pixmap_and_mask()
Mask = MapMask[1]
self.add(Button)
Button.shape_combine_mask(Mask, 0, 0)
Button.show()
self.show()
This gets me a button with the correct image, but no masking. Can anybody spot what I'm doing wrong?
I found that shape_combine_mask() works, but you have to apply it to the container, not the button (which I think is transparent by default).

So replacing Button.shape_combine_mask(Mask, 0, 0) with self.shape_combine_mask(Mask, 0, 0) should do the trick, I think.
 
Posts: 87 | Thanked: 98 times | Joined on Oct 2007 @ Austria
#17
Googling on this topic, I came across this example of semi-transparent windows with cairo, and to my utter amazement it works perfectly on OS2008!

So I went ahead and remodeled this clock widget to a desktop maemo plugin.

Here's how it looks (it's resizable too!)

Name:  pyclock.jpg
Views: 6048
Size:  16.5 KB

And this is the code - following SpiritGeeks example I'll just paste it in

/usr/share/applications/hildon-home/pyclock.desktop:
Code:
[Desktop Entry]
Name=Python Cairo Clock
Type=python
X-Path=pyclock
/usr/lib/hildon-desktop/pyclock.py:
Code:
import sys
import gobject
import pango
import pygtk
pygtk.require('2.0')
import gtk
from gtk import gdk
import hildondesktop
import cairo
from datetime import datetime
import gobject
import math


# set this to False to disable display of seconds and update 
# only once per minute (saves CPU cycles on the tablet)
enable_seconds = True

supports_alpha = False


class PyClock(hildondesktop.HomeItem):
	def __init__(self):
		hildondesktop.HomeItem.__init__(self)
				
		self.set_resize_type(hildondesktop.HOME_ITEM_RESIZE_BOTH)
		self.set_size_request(140, 140)
		self.connect("expose-event", self.expose)
		self.connect("screen-changed", self.screen_changed)
		self.connect ("background", self.set_timer, False)
		self.connect ("foreground", self.set_timer, True)
		self.connect ("unrealize", self.unrealize)

		# set a timeout to update the clock, depending
		# on whether we are in the foreground or background
		self.timer = None
		self.set_timer(self, True)

		self.show_all()


	def expose(self, widget, event):

		global supports_alpha

		width, height = self.allocation[2], self.allocation[3]

		#Get a cairo context
		cr = widget.window.cairo_create()

		if supports_alpha == True:
			cr.set_source_rgba(1.0, 1.0, 1.0, 0.0) # Transparent
		else:
			cr.set_source_rgb(1.0, 1.0, 1.0) # Opaque white

		# Draw the background
		cr.set_operator(cairo.OPERATOR_SOURCE)
		cr.paint()

		#And draw everything we want
		#Some cos/sin magic is done, never mind
		if supports_alpha == True:
			cr.set_source_rgba(1.0, 1.0, 1.0, 0.5)
		else:
			cr.set_source_rgb(1.0, 1.0, 1.0)			
		if width < height:
			radius = float(width)/2 - 0.8
		else:
			radius = float(height)/2 - 0.8
			
		cr.arc(float(width)/2, float(height)/2, radius, 0, 2.0*3.14)
		cr.fill()
		cr.stroke()
	
		if supports_alpha == True:
			cr.set_source_rgba(0.0, 0.0, 0.0, 1.0)
		else:
			cr.set_source_rgb(0.0, 0.0, 0.0)

		cr.set_line_width(0.07 * radius)
		cr.move_to(-0.05 * radius + float(width/2 + radius), float(height)/2)
		cr.rel_line_to(-0.1 * radius, 0)
		cr.stroke()
		cr.move_to(float(width)/2, -0.05 * radius + float(height/2 + radius))
		cr.rel_line_to(0, -0.1 * radius)
		cr.stroke()
		cr.move_to(0.05 * radius + float(width/2 - radius), float(height)/2)
		cr.rel_line_to(0.1 * radius, 0)
		cr.stroke()
		cr.move_to(float(width)/2, 0.05 * radius + float(height/2 - radius))
		cr.rel_line_to(0, 0.1 * radius)
		cr.stroke()

		time = datetime.now()
		hour = time.hour
		minutes = time.minute
		seconds = time.second
		per_hour = (2 * 3.14) / 12
		dh = (hour * per_hour) + ((per_hour / 60) * minutes)
		dh += 2 * 3.14 / 4
		cr.set_line_width(0.07 * radius)
		cr.move_to(float(width)/2, float(height)/2)
		cr.rel_line_to(-0.6 * radius * math.cos(dh), -0.6 * radius * math.sin(dh))
		cr.stroke()
		per_minute = (2 * 3.14) / 60
		dm = minutes * per_minute
		dm += 2 * 3.14 / 4
		cr.set_line_width(0.05 * radius)
		cr.move_to(float(width)/2, float(height)/2)
		cr.rel_line_to(-0.9 * radius * math.cos(dm), -0.9 * radius * math.sin(dm))
		cr.stroke()
		# only draw seconds when in foreground
		if enable_seconds: # disable seconds, to much work for little tablets
			per_second = (2 * 3.14) / 60
			ds = seconds * per_second
			ds += 2 * 3.14 / 4
			cr.set_line_width(0.02 * radius)
			cr.move_to(float(width)/2, float(height)/2)
			cr.rel_line_to(-0.9 * radius * math.cos(ds), -0.9 * radius * math.sin(ds))
			cr.stroke()
		
		cr.arc(float(width)/2, float(height)/2, 0.1 * radius, 0, 2.0*3.14)
		cr.fill()
		cr.stroke()
		
		#Once everything has been drawn, create our XShape mask
		#Our window content is contained inside the big circle,
		#so let's use that one as our mask
		"""pm = gtk.gdk.Pixmap(None, width, height, 1)
		pmcr = pm.cairo_create()
		pmcr.arc(float(width)/2, float(height)/2, radius, 0, 2.0*3.14)
		pmcr.fill()
		pmcr.stroke()
		#Apply input mask
		self.input_shape_combine_mask(pm, 0, 0)"""
	
		return False


	def screen_changed(self, widget, old_screen=None):
		global supports_alpha
		# print "screen changed"
		
		# To check if the display supports alpha channels, get the colormap
		screen = self.get_screen()
		colormap = screen.get_rgba_colormap()
		if colormap == None:
			# print 'Your screen does not support alpha channels!'
			colormap = screen.get_rgb_colormap()
			supports_alpha = False
		else:
			# print 'Your screen supports alpha channels!'
			supports_alpha = True
    
		# Now we have a colormap appropriate for the screen, use it
		self.set_colormap(colormap)
    
		return False
	
	def unrealize(self, widget, date=None):
		# cancel timeout
		if self.timer:
			v = gobject.source_remove(self.timer)
			print "canceled pyclock timeout:", v
			self.timer = None


	def set_timer(self, widget, on):
		# when called first time from __init__ widget is None
		if self.timer != None:
			# print "removing old timer"
			gobject.source_remove(self.timer)
		if on:
			# print "creating new timer"
			delay = 1000 if enable_seconds else 60000
			self.timer = gobject.timeout_add(delay, self.update)
			# repaint immediately when coming to the foreground
			self.update()


	def update(self):
		# print "updating pyclock"
		self.queue_draw()
		return True


def hd_plugin_get_objects():
	plugin = PyClock()
	return [plugin]
Remember that you need the hildondesktop python bindings installed which aren't in the main repositories yet. Happy hacking!

Last edited by hns; 2008-03-07 at 09:22. Reason: Update code to cancel timeout call when plugin is removed.
 

The Following 6 Users Say Thank You to hns For This Useful Post:
Posts: 35 | Thanked: 5 times | Joined on Sep 2007
#18
Thanks a lot. I tried it out and it works! Though only in device not on pyphantom ide. Well I guess it doesn't matter as long as it works on IT.

Now just need to learn that cairo mumbo jumbo.

I got a python program ready for integration with GUI and a complete GUI concept ready too but looks like it's not that trivial task after all.

Anyway thanks for the example!
 
Posts: 87 | Thanked: 98 times | Joined on Oct 2007 @ Austria
#19
Originally Posted by icer View Post
Now just need to learn that cairo mumbo jumbo.
Well you can use Cairo just for transparency and widget shape, and than use ordinary GTK widgets on top of that. For example, here's a version of Khertan's HomeIP plugin that is rendered on a semitransparent black rectangle with rounded corners

Code:
import gtk
import hildondesktop
import cairo
import gobject
import pango
import commands
import traceback

supports_alpha = False

class IPPlugin(hildondesktop.HomeItem):
	def __init__(self):
		hildondesktop.HomeItem.__init__(self)
		
		self.label = gtk.Label()
		self.label.set_use_markup(True)
		self.label.modify_font(pango.FontDescription ("Sans 18"))
		self.label.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000"))
		self.label.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#fff"))
		self.label.set_text(self.get_ip())
		self.label.set_padding(15, 10)
		
		self.connect("expose-event", self.expose)
		self.connect("screen-changed", self.screen_changed)
		self.add(self.label)
		self.show_all()
		
		# set a timeout to change the images
		self.timer = gobject.timeout_add(2000, self.update)
		print "foreground timer", self.timer
		
		self.connect ("background", self.background)
		self.connect ("foreground", self.foreground)



	def expose(self, widget, event):
		cr = self.window.cairo_create()
		if supports_alpha == True:
			cr.set_source_rgba(1.0, 1.0, 1.0, 0.0) # Transparent
		else:
			cr.set_source_rgb(1.0, 1.0, 1.0) # Opaque white

		# Draw the background
		cr.set_operator(cairo.OPERATOR_SOURCE)
		cr.paint()

		# draw rounded rect
		width, height = self.allocation[2], self.allocation[3]

		#/* a custom shape, that could be wrapped in a function */
		x0 = 0   #/*< parameters like cairo_rectangle */
		y0 = 0

		radius = min(15, width/2, height/2)  #/*< and an approximate curvature radius */

		x1 = x0 + width
		y1 = y0 + height

		cr.move_to  (x0, y0 + radius)
		cr.arc (x0 + radius, y0 + radius, radius, 3.14, 1.5 * 3.14)
		cr.line_to (x1 - radius, y0)
		cr.arc (x1 - radius, y0 + radius, radius, 1.5 * 3.14, 0.0)
		cr.line_to (x1 , y1 - radius)
		cr.arc (x1 - radius, y1 - radius, radius, 0.0, 0.5 * 3.14)
		cr.line_to (x0 + radius, y1)
		cr.arc (x0 + radius, y1 - radius, radius, 0.5 * 3.14, 3.14)

		cr.close_path ()

		cr.set_source_rgba (0.0, 0.0, 0.0, 0.5)
		cr.fill_preserve ()
		# cr.set_source_rgba (0.5, 0.5, 1.0, 0.8)
		# cr.stroke ()


	def screen_changed(self, widget, old_screen=None):
		global supports_alpha
    
		# To check if the display supports alpha channels, get the colormap
		screen = widget.get_screen()
		colormap = screen.get_rgba_colormap()
		if colormap == None:
			print 'Your screen does not support alpha channels!'
			colormap = screen.get_rgb_colormap()
			supports_alpha = False
		else:
			print 'Your screen supports alpha channels!'
			supports_alpha = True
    
		# Now we have a colormap appropriate for the screen, use it
		widget.set_colormap(colormap)
    
		return False


	def background(self, widget, data=None):
		#Avoid refresh when applet is in background
		self.label.set_text("refreshing")
		if self.timer != None:
			gobject.source_remove(self.timer)
			self.timer = None

	def foreground(self, widget, data=None):
		self.label.set_text(self.get_ip())
		self.timer = gobject.timeout_add(2000, self.update)
		print "foreground timer", self.timer

	def unrealize(self, widget, date=None):
		# cancel timeout
		v = gobject.source_remove(self.timer)
		print "canceled homeip timeout:", v

	def update(self):
		self.label.set_text(self.get_ip())
		
	def get_ip(self):
		#CPU Speed
		text = "No IP"
		devs = commands.getoutput("/sbin/ifconfig wlan0")
		sdevs = devs.rsplit('\n')
		for stdev in sdevs:
			#sdev = re.findall("(\S*)\s*", stdev)
			if 'inet addr:' in stdev:
				sdev = stdev.rsplit(':')
				sdev2 = sdev[1].rsplit(' ')
				text= "IP: " + sdev2[0]
		return text
				
def hd_plugin_get_objects():
	plugin = IPPlugin()
	return [plugin]
 

The Following 2 Users Say Thank You to hns For This Useful Post:
Khertan's Avatar
Posts: 1,012 | Thanked: 817 times | Joined on Jul 2007 @ France
#20
Hey great !

Just a small thing ... my plugin is just an example, but if you use it ... sometimes label is too short for displaying the entire ip. (because it can be created with 'No IP') ... so just do a set_size_request(-1,-1) on it.

And THANKS ! I ll try this, maybe now will could have usefull and beautifful widget in python.
 
Reply


 
Forum Jump


All times are GMT. The time now is 13:45.