[Sugar-devel] [PATCH Record (Gtk3)] Use new syntax for Gst.Caps
Using the new syntax for Gst.Caps we avoid Gst's WARNING message in the log. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- glive.py | 18 +++--- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/glive.py b/glive.py index 5d78bbe..d39e292 100644 --- a/glive.py +++ b/glive.py @@ -102,8 +102,7 @@ class Glive: pipeline = Gst.Pipeline() -# WARNING **: 0.10-style raw video caps are being created. Should be video/x-raw,format=(string) -caps = Gst.Caps.from_string('video/x-raw-yuv,framerate=10/1') +caps = Gst.Caps.from_string('video/x-raw, format=(string)yuv, framerate=(fraction)10/1') camerafilter = Gst.ElementFactory.make(capsfilter, capsfilter) camerafilter.set_property(caps, caps) @@ -165,8 +164,7 @@ class Glive: if not hwdev_available: src.set_property(device, default) -# WARNING **: 0.10-style raw audio caps are being created. Should be audio/x-raw,format=(string) -srccaps = Gst.Caps.from_string(audio/x-raw-int,rate=16000,channels=1,depth=16) +srccaps = Gst.Caps.from_string(audio/x-raw, rate=(int)16000, channels=(int)1, depth=(int)16) # guarantee perfect stream, important for A/V sync rate = Gst.ElementFactory.make(audiorate, 'audiorate') @@ -210,8 +208,7 @@ class Glive: scale = Gst.ElementFactory.make(videoscale, vbscale) -# WARNING **: 0.10-style raw video caps are being created. Should be video/x-raw,format=(string) -scalecaps = Gst.Caps.from_string('video/x-raw-yuv,width=160,height=120') +scalecaps = Gst.Caps.from_string('video/x-raw, format=(string)yuv, width=(int)160, height=(int)120') scalecapsfilter = Gst.ElementFactory.make(capsfilter, scalecaps) scalecapsfilter.set_property(caps, scalecaps) @@ -273,7 +270,7 @@ class Glive: vbenc = self._videobin.get_by_name(vbenc) vbenc.set_property(quality, 16) #scaps = self._videobin.get_by_name(scalecaps) # FIXME: If these elements connect the pipeline does not run. -#scaps.set_property(caps, Gst.Caps.from_string(video/x-raw-yuv,width=%d,height=%d % (width, height))) +#scaps.set_property(caps, Gst.Caps.from_string(video/x-raw, format=(string)yuv, width=(int)%d, height=(int)%d % (width, height))) def _create_pipeline(self): @@ -287,10 +284,10 @@ class Glive: # camera level if self._can_limit_framerate: -srccaps = Gst.Caps.from_string('video/x-raw-yuv,framerate=10/1') +srccaps = Gst.Caps.from_string('video/x-raw, format=(string)yuv, framerate=(fraction)10/1') else: -srccaps = Gst.Caps.from_string('video/x-raw-yuv') +srccaps = Gst.Caps.from_string('video/x-raw, format=(string)yuv') # we attempt to limit the framerate on the v4l2src directly, but we # can't trust this: perhaps we are falling behind in our capture, @@ -299,7 +296,7 @@ class Glive: # for A/V sync because OGG does not store timestamps, it just stores # the FPS value. rate = Gst.ElementFactory.make(videorate, 'videorate') -ratecaps = Gst.Caps.from_string('video/x-raw-yuv,framerate=10/1') +ratecaps = Gst.Caps.from_string('video/x-raw, format=(string)yuv, framerate=(fraction)10/1') tee = Gst.ElementFactory.make(tee, tee) queue = Gst.ElementFactory.make(queue, dispqueue) @@ -860,4 +857,3 @@ class Glive: if os.path.exists(mux_path): os.remove(mux_path) - \ No newline at end of file -- 1.7.11.7 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [RELEASE] sugar-toolkit-gtk3-0.98.2
On Mon, Dec 17, 2012 at 6:49 PM, Simon Schampijer si...@schampijer.de wrote: The 2 points for KaufmannQuiñones 1 for Garnacho release. Yeah! We are closer of getting the ticket to Germany :) Congratulation to all the team involved on this! -- Kaufmann Manuel -- http://mkaufmann.com.ar ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [Release] Clock-12
Hi Daniel, On Sun, Dec 16, 2012 at 3:41 PM, Gary Martin garycmar...@googlemail.com wrote: This is a release of Clock-12 to fix #4079 (broken speech) for landing in the 13.1.0 release (thanks go to Humitos for the patch). Can we include this version of Clock?. It solves a really good feature that it will be a pity if it's not included on the image. -- Kaufmann Manuel -- http://mkaufmann.com.ar ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [sugar-toolkit-gtk3 PATCH] sl#4276: Writing the icon-files for .xo files on a permanent mount-point, and not /tmp. mount-point.
On Mon, Dec 10, 2012 at 4:09 PM, Ajay Garg a...@activitycentral.com wrote: Thus, now as the solution, we write the icon-files (maximum of one file per activity) at ~/.sugar/default/icon_files. Now, the icons are rendered correctly then. I didn't check the patch yet, but I don't see anything that collects the icon garbage at any point. I mean, if you download many activities from ASLO and go to the Journal, those icons will be copied into ~/.sugar/default/icon_files and displayed properly in the Journal. Then, you remove the downloaded files but those icons will still be there at ~/.sugar/default/icon_files. Am I right? -- Kaufmann Manuel -- http://mkaufmann.com.ar ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] Automated testing
On Fri, Dec 7, 2012 at 8:48 PM, Daniel Narvaez dwnarv...@gmail.com wrote: Link to the test case (tree.py is an helper that I'm trying to integrated in toolkit) Good! This is really useful. I was playing with it yesterday and I found it fun! Another utility that I found useful is this one: https://live.gnome.org/Accerciser It allows us to explore the full structure of our Gtk application that are running. So, we can explore our Activities to look for the specific widget. Then use find_child / find_children with the name and role_name to find them. I wrote a simple (and awful) test using these utilities to check that the frame is shown and it works. It uses ImageMagick to call the compare command. The idea: - preset a language - preset a XO color - look for the widget - run event on them (click, motion, etc) - wait some secs so those events take effect - take a screenshot - crop it (check only the proper section) - compare that screenshot with another already taken manually by us Known issues: - we need to hide the mouse cursor - sensible to different resolutions - others Maybe you can find something interesting here. Good luck with this :P Cheers, -- Kaufmann Manuel -- http://mkaufmann.com.ar test_frame.py Description: Binary data my_screenshot.png.bak Description: Binary data ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] sugar-build make build-sugar-artwork and quad-core compilation
On Mon, Nov 26, 2012 at 6:08 PM, Daniel Narvaez dwnarv...@gmail.com wrote: * make build only build the sources build just builds! * make pull only pulls the sources pull just pulls! * make check the system, pull the sources and builds them. (which is what make build was doing before) ... make ... just make? :P What's up if there are no changes on the source code? make (and make build) will build it anyway? I'm happy with this. I think it's clearer now. PS: make build-* works again! Wiii! -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [RELEASE] sugar-0.97.13
On Tue, Nov 27, 2012 at 4:55 PM, Simon Schampijer si...@schampijer.de wrote: Meh... The boring release with no funny summary ;-) -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] sugar-build make build-sugar-artwork and quad-core compilation
Hi, Sometime ago I used to run: make build-sugar-artwork to just re-compile sugar-artwork. Nowadays that is not more possible. Any clue here? Another issue is that I was able to set -j 8 to make and use more than one CPU to compile all sources. Is there any way to do that in the current sugar-build implementation? Cheers, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] sugar-build make build-sugar-artwork and quad-core compilation
On Mon, Nov 26, 2012 at 3:06 PM, Daniel Narvaez dwnarv...@gmail.com wrote: can you explain how you are using it exactly? I didn't readd it when I rewrote things because I was not very clear on the use case (I normally just make; make install stuff inside a shell). $ make build-sugar - just compile and install sugar $ make build-sugar-artwork - just compile and install sugar-artwork and so on... It seems to be a shortcut for do what you described here. 1. make shell 2. cd source/sugar 3. make 4. make install Another issue is that I was able to set -j 8 to make and use more than one CPU to compile all sources. Is there any way to do that in the current sugar-build implementation? That's supposed to just work Oh! It's automatic! Great! I can see the make -j8 in the logs ;) -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] sugar-build make build-sugar-artwork and quad-core compilation
On Mon, Nov 26, 2012 at 3:59 PM, Daniel Narvaez dwnarv...@gmail.com wrote: But did you use it to build your own changes or changes someone made to the repo? Or both? I'm not sure if I used it for both. I used it before knowing auto-install. I mean, I made a change on some .py file and I ran make build-sugar for example. That's all. PS: I can live without that option, maybe I'm the only one that want to use it. So, do not complicate your life. It's not so annoying to enter to the shell and run make ; make install -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] Shared activity game - Maze
On Sat, Nov 24, 2012 at 6:34 PM, RJV jv.ravichand...@gmail.com wrote: It will be great fun if both the mazes were the same and both players could play on the same maze, racing against each other, as in the single XO, multi-players scenario! It does really work in that way in Maze-22. I worked on that two weeks ago and I tested it a lot. I played with up to 3 player per XO ;) What version of Maze are you using? -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [sugar-build] Recent improvements
On Fri, Nov 16, 2012 at 2:10 PM, Daniel Narvaez dwnarv...@gmail.com wrote: in the last couple of weeks I worked a lot on sugar-build and made a bunch of improvements: Well! You are doing a really good work! Congratulations and thanks for that! -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] Activities without summaries
On Wed, Nov 14, 2012 at 9:22 AM, Gonzalo Odiard gonz...@laptop.org wrote: -InfoSlicer.activity/activity/activity.info Done. http://git.sugarlabs.org/infoslicer/mainline/commit/142d6f43c28e2eb5364c9c93fedd91b15ec0dbad Thank you for this email. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] Browse activity proxy settings
On Sun, Nov 11, 2012 at 11:41 AM, Ariel Calzada ar...@activitycentral.com wrote: I would like to know if there's a way to make Browse activity use PROXY SETTINGS. I tried configuring proxy settings in My settings/Network with no luck. I think we have to modify Browse to make this possible. I didn't find anything related with proxy on Browse's code. Do you know what My settings/Network does? I found there is a simple way (but I didn't try it yet) to make use of the http_proxy env variable from WebKitGtk: http://lists.macosforge.org/pipermail/webkit-help/2009-December/000475.html If My settings/Network set that environment variable we can use it, if no, we need to know what it does and read that value. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [RELEASE] sugar-0.97.11
On Sat, Nov 10, 2012 at 7:51 AM, Simon Schampijer si...@schampijer.de wrote: The one step closer to collaboration release. Well! That's really good! What is missing to say that collaboration is working properly? Yesterday, I worked on Maze Collaboration[1] on os9 and os10 with the sugar version compiled from the git repository and I was able to play with three XO without any problem. Can I help in some way? [1] http://bugs.sugarlabs.org/ticket/3747 -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH sugar-toolkit-gtk3] Sugar scroll bar clicks should invoke page up/page down SL #3859
On Mon, Nov 5, 2012 at 8:55 AM, Daniel Narvaez dwnarv...@gmail.com wrote: Also would be nice to update pygobject and others, and use them from packages now that there are for both Fedora and Ubuntu. Are these packaged for Fedora 17? We don't have support for Fedora 18 in sugar-build yet but I'm planning to add it next week, when the beta is released (assuming it does work in a vm). That's the problem. I didn't find the latest version of pygobject and gtk built for Fedora 17. I think we should update the commit hash on the sugar-build tool to get the latest version and compile it as we are doing now with an older version. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Read] Show 'No book' message when Read starts from scratch
When the user starts a new instance of Read the 'No book' message is shown with a button to 'Choose a book' that opens the Object Chooser. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- emptypanel.py | 45 + icons/activity-read.svg | 11 +++ readactivity.py | 8 ++-- 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 emptypanel.py create mode 100644 icons/activity-read.svg diff --git a/emptypanel.py b/emptypanel.py new file mode 100644 index 000..d8fa042 --- /dev/null +++ b/emptypanel.py @@ -0,0 +1,45 @@ +import logging + +from gi.repository import Gtk + +from sugar3.graphics import style +from sugar3.graphics.icon import Icon + + +def show(activity, icon_name, message, btn_label, btn_callback): +empty_widgets = Gtk.EventBox() +empty_widgets.modify_bg(Gtk.StateType.NORMAL, +style.COLOR_WHITE.get_gdk_color()) + +vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) +mvbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) +vbox.pack_start(mvbox, True, False, 0) + +image_icon = Icon(pixel_size=style.LARGE_ICON_SIZE, + icon_name=icon_name, + stroke_color=style.COLOR_BUTTON_GREY.get_svg(), + fill_color=style.COLOR_TRANSPARENT.get_svg()) +mvbox.pack_start(image_icon, False, False, style.DEFAULT_PADDING) + +label = Gtk.Label('span foreground=%sb%s/b/span' % + (style.COLOR_BUTTON_GREY.get_html(), + message)) +label.set_use_markup(True) +mvbox.pack_start(label, False, False, style.DEFAULT_PADDING) + +hbox = Gtk.Box() +open_image_btn = Gtk.Button() +open_image_btn.connect('clicked', btn_callback) +add_image = Gtk.Image.new_from_stock(Gtk.STOCK_ADD, + Gtk.IconSize.BUTTON) +buttonbox = Gtk.Box() +buttonbox.pack_start(add_image, False, True, 0) +buttonbox.pack_end(Gtk.Label(btn_label), True, True, 5) +open_image_btn.add(buttonbox) +hbox.pack_start(open_image_btn, True, False, 0) +mvbox.pack_start(hbox, False, False, style.DEFAULT_PADDING) + +empty_widgets.add(vbox) +empty_widgets.show_all() +logging.error('Showing empty Panel') +activity.set_canvas(empty_widgets) diff --git a/icons/activity-read.svg b/icons/activity-read.svg new file mode 100644 index 000..d0d1804 --- /dev/null +++ b/icons/activity-read.svg @@ -0,0 +1,11 @@ +?xml version=1.0 ?!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + !ENTITY stroke_color #010101 + !ENTITY fill_color #FF +]svg enable-background=new 0 0 55 55 height=55px version=1.1 viewBox=0 0 55 55 width=55px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg; xmlns:xlink=http://www.w3.org/1999/xlink; y=0pxg display=block id=activity-read + path d=M27.904,11.023h-0.002 c0-0.002-1.71-2.053-9.376-2.504C10.86,8.07,6.843,10.121,6.84,10.122c-1.898,0.619-3.495,1.735-3.495,3.494v27.702 c0,2.025,1.235,3.494,3.495,3.494c0.003,0,4.41-1.35,10.004-1.35c5.589-0.001,11.061,2.253,11.061,2.253 display=inline fill=fill_color; stroke=stroke_color; stroke-linejoin=round stroke-width=3.5/ + path d=M27.898,11.023 L27.898,11.023c0-0.002,1.715-2.053,9.377-2.504c7.668-0.449,11.686,1.602,11.688,1.603c1.897,0.619,3.494,1.735,3.494,3.494 v27.702c0,2.025-1.233,3.494-3.494,3.494c-0.003,0-4.409-1.35-10.004-1.35c-5.589-0.001-11.062,2.253-11.062,2.253 display=inline fill=fill_color; stroke=stroke_color; stroke-linejoin=round stroke-width=3.5/ + + line display=inline fill=none stroke=stroke_color; stroke-linecap=round stroke-linejoin=round stroke-width=3.5 x1=27.898 x2=27.9 y1=11.023 y2=45.717/ + path d= M32.566,44.275c0,0-0.031,2.906-4.666,2.906c-4.632,0-4.663-2.906-4.663-2.906 display=inline fill=none stroke=stroke_color; stroke-linecap=round stroke-linejoin=round stroke-width=3.5/ +/g/svg + diff --git a/readactivity.py b/readactivity.py index 17f8455..846fef9 100644 --- a/readactivity.py +++ b/readactivity.py @@ -25,6 +25,7 @@ import re import md5 import StringIO import cairo +import emptypanel import dbus from gi.repository import GObject @@ -335,7 +336,9 @@ class ReadActivity(activity.Activity): self.connect(joined, self._joined_cb) elif self._object_id is None: # Not joining, not resuming -self._show_journal_object_picker() +emptypanel.show(self, 'activity-read', +_('No book'), _('Choose a book'), +self._show_journal_object_picker_cb) def _create_back_button(self): back = ToolButton('go-previous-paired') @@ -612,7 +615,7 @@ class ReadActivity(activity.Activity): else: logging.debug('link %s not found in the toc model', current_link) -def
[Sugar-devel] [PATCH Jukebox] Show 'No media' message when Jukebox starts from scratch
When the user starts a new instance of Jukebox the 'No media' message is shown with a button to 'Choose media files' that opens the Object Chooser. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- emptypanel.py | 45 + icons/activity-jukebox.svg | 7 +++ jukeboxactivity.py | 35 +++ 3 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 emptypanel.py create mode 100644 icons/activity-jukebox.svg diff --git a/emptypanel.py b/emptypanel.py new file mode 100644 index 000..d8fa042 --- /dev/null +++ b/emptypanel.py @@ -0,0 +1,45 @@ +import logging + +from gi.repository import Gtk + +from sugar3.graphics import style +from sugar3.graphics.icon import Icon + + +def show(activity, icon_name, message, btn_label, btn_callback): +empty_widgets = Gtk.EventBox() +empty_widgets.modify_bg(Gtk.StateType.NORMAL, +style.COLOR_WHITE.get_gdk_color()) + +vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) +mvbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) +vbox.pack_start(mvbox, True, False, 0) + +image_icon = Icon(pixel_size=style.LARGE_ICON_SIZE, + icon_name=icon_name, + stroke_color=style.COLOR_BUTTON_GREY.get_svg(), + fill_color=style.COLOR_TRANSPARENT.get_svg()) +mvbox.pack_start(image_icon, False, False, style.DEFAULT_PADDING) + +label = Gtk.Label('span foreground=%sb%s/b/span' % + (style.COLOR_BUTTON_GREY.get_html(), + message)) +label.set_use_markup(True) +mvbox.pack_start(label, False, False, style.DEFAULT_PADDING) + +hbox = Gtk.Box() +open_image_btn = Gtk.Button() +open_image_btn.connect('clicked', btn_callback) +add_image = Gtk.Image.new_from_stock(Gtk.STOCK_ADD, + Gtk.IconSize.BUTTON) +buttonbox = Gtk.Box() +buttonbox.pack_start(add_image, False, True, 0) +buttonbox.pack_end(Gtk.Label(btn_label), True, True, 5) +open_image_btn.add(buttonbox) +hbox.pack_start(open_image_btn, True, False, 0) +mvbox.pack_start(hbox, False, False, style.DEFAULT_PADDING) + +empty_widgets.add(vbox) +empty_widgets.show_all() +logging.error('Showing empty Panel') +activity.set_canvas(empty_widgets) diff --git a/icons/activity-jukebox.svg b/icons/activity-jukebox.svg new file mode 100644 index 000..b921d4f --- /dev/null +++ b/icons/activity-jukebox.svg @@ -0,0 +1,7 @@ +?xml version=1.0 ?!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ + !ENTITY stroke_color #010101 + !ENTITY fill_color #FF +]svg enable-background=new 0 0 55 55 height=55px version=1.1 viewBox=0 0 55 55 width=55px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg; xmlns:xlink=http://www.w3.org/1999/xlink; y=0pxg display=block id=activity-jukebox + path d=M17.666,7.884v32.841 c-2.587-0.614-7.914-0.612-10.755,1.764c-5.688,4.76-0.695,10.109,5.815,7.456c3.705-1.512,4.94-3.937,4.94-7.597V25.997 l30.952-3.516v12.974c-4.212-0.615-7.915-0.614-10.758,1.764c-5.688,4.76-0.695,10.109,5.815,7.454 c3.705-1.51,4.942-3.936,4.942-7.596V4.293L17.666,7.884z M48.618,15.86l-30.952,4.029l0-5.225l30.953-4.102V15.86z display=inline fill=fill_color; stroke=stroke_color; stroke-width=3.5/ +/g/svg + diff --git a/jukeboxactivity.py b/jukeboxactivity.py index 1bc4d4a..bde15a3 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -24,6 +24,7 @@ import sys import logging import tempfile +import emptypanel from gettext import gettext as _ import os @@ -152,31 +153,34 @@ class JukeboxActivity(activity.Activity): # self.bin = Gtk.HBox() # self.bin.show() -self.canvas = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) +self._video_canvas = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL) self._alert = None self.playlist_widget = PlayListWidget(self.play) self.playlist_widget.update(self.playlist) self.playlist_widget.show() -self.canvas.pack_start(self.playlist_widget, False, True, 0) +self._video_canvas.pack_start(self.playlist_widget, False, True, 0) self._empty_widget = Gtk.Label(label=) self._empty_widget.show() self.videowidget = VideoWidget() -self.set_canvas(self.canvas) +self.set_canvas(self._video_canvas) self._init_view_area() self.show_all() -self.canvas.connect('size-allocate', self.__size_allocate_cb) +self._video_canvas.connect('size-allocate', self.__size_allocate_cb) -#From ImageViewer Activity self._want_document = True if self._object_id is None: -self._show_object_picker = GObject.timeout_add(1000, \ -self._show_picker_cb) +emptypanel.show(self, 'activity
Re: [Sugar-devel] Problem playing videos in jukebox
On Thu, Nov 1, 2012 at 4:43 PM, Ariel Calzada ariel.calz...@gmail.com wrote: Image: http://build.laptop.org/13.1.0/os8/xo-1.75/ Jukebox Activity Version: 28 I've just test using these versions and I had no problem. The audio is not so good, but that is a known issue on 1.75. I downloaded the file from wikipedia with wget and moved it to ~/Documents folder. What is the error that you are getting? -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH sugar-toolkit-gtk3] Sugar scroll bar clicks should invoke page up/page down SL #3859
The default value of 'gtk-primary-button-warps-slider' in Gtk3 is True[1] and in gtk2 is False[2]. So, this patch sets that property to False to keep the same behaviour we have before. [1] http://developer.gnome.org/gtk3/stable/GtkSettings.html#GtkSettings--gtk-primary-button-warps-slider [2] http://developer.gnome.org/gtk/2.24/GtkSettings.html#GtkSettings--gtk-primary-button-warps-slider Signed-off-by: Manuel Kaufmann humi...@gmail.com --- src/sugar3/activity/activity.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sugar3/activity/activity.py b/src/sugar3/activity/activity.py index 3325f47..d799aee 100644 --- a/src/sugar3/activity/activity.py +++ b/src/sugar3/activity/activity.py @@ -271,6 +271,7 @@ class Activity(Window, Gtk.Container): settings.set_property('gtk-icon-theme-name', 'sugar') settings.set_property('gtk-font-name', '%s %f' % (style.FONT_FACE, style.FONT_SIZE)) +settings.set_property('gtk-primary-button-warps-slider', False) Window.__init__(self) -- 1.7.11.7 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH sugar] Invoke page up/page down on scrollbars clicks
The default value of 'gtk-primary-button-warps-slider' in Gtk3 is True[1] and in gtk2 is False[2]. So, this patch sets that property to False to keep the same behaviour we had before. [1] http://developer.gnome.org/gtk3/stable/GtkSettings.html#GtkSettings--gtk-primary-button-warps-slider [2] http://developer.gnome.org/gtk/2.24/GtkSettings.html#GtkSettings--gtk-primary-button-warps-slider Signed-off-by: Manuel Kaufmann humi...@gmail.com --- bin/sugar-session | 4 1 file changed, 4 insertions(+) diff --git a/bin/sugar-session b/bin/sugar-session index 23f88a1..5911052 100755 --- a/bin/sugar-session +++ b/bin/sugar-session @@ -253,6 +253,9 @@ def set_theme(): settings.set_property('gtk-theme-name', sugar_theme) settings.set_property('gtk-icon-theme-name', 'sugar') +def set_warps_slider(): +settings = Gtk.Settings.get_default() +settings.set_property('gtk-primary-button-warps-slider', False) def main(): try: @@ -291,6 +294,7 @@ def main(): set_fonts() set_theme() +set_warps_slider() # this must be added early, so that it executes and unfreezes the screen # even when we initially get blocked on the intro screen -- 1.7.11.7 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH sugar] Invoke page up/page down on scrollbars clicks
On Fri, Nov 2, 2012 at 8:16 PM, Manuel Kaufmann humi...@gmail.com wrote: The default value of 'gtk-primary-button-warps-slider' in Gtk3 is True[1] and in gtk2 is False[2]. So, this patch sets that property to False to keep the same behaviour we had before. This patch works properly but, please, reconsider changing the way it's implemented. I didn't know where to put that settings, so I created a new function that is called immediately after set_theme(). Feel free to move that to the correct place considering the Sugar Philosophy :D -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Reload fixed
Hello, I'm sending the patch attached because after an update git send-mail is not more available (now, there is a subcommand called send-bugzilla :( ) Cheers, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ 0001-Reload-fixed.patch Description: Binary data ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Don't show error page when plugin will handle
Hello, I found this bug while I was testing SL #3934 [1]. The patch that fixes this is attached. Cheers, [1] http://bugs.sugarlabs.org/ticket/3934 -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ 0001-Don-t-show-error-page-when-plugin-will-handle.patch Description: Binary data ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Speak] Use radians instead of degrees
Cairo.Context.arc needs the angle in radians instead of degrees. Give it as 360 (radians) was taking up to 8 seconds to draw the eyes. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- eye.py | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/eye.py b/eye.py index 954e68a..e1bf5b8 100644 --- a/eye.py +++ b/eye.py @@ -125,18 +125,20 @@ class Eye(gtk.DrawingArea): self.context.fill() # eye ball -self.context.arc(bounds.width / 2, bounds.height / 2, eyeSize / 2 - outlineWidth / 2, 0, 360) +self.context.arc(bounds.width / 2, bounds.height / 2, + eyeSize / 2 - outlineWidth / 2, 0, 2 * math.pi) self.context.set_source_rgb(1, 1, 1) self.context.fill() # outline self.context.set_line_width(outlineWidth) -self.context.arc(bounds.width / 2, bounds.height / 2, eyeSize / 2 - outlineWidth / 2, 0, 360) +self.context.arc(bounds.width / 2, bounds.height / 2, + eyeSize / 2 - outlineWidth / 2, 0, 2 * math.pi) self.context.set_source_rgb(0, 0, 0) self.context.stroke() # pupil -self.context.arc(pupilX, pupilY, pupilSize, 0, 360) +self.context.arc(pupilX, pupilY, pupilSize, 0, 2 * math.pi) self.context.set_source_rgb(0, 0, 0) self.context.fill() -- 1.7.11.7 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] espeak in gst 0.10 on 13.1.0
Hello, I took a look at this issue[1] and I found that it's not possible to get the espeak gstreamer element on 13.1.0 os7 using gst 0.10 but it's available using Gst 1.0 (from gi.repository import Gst). However, there is no package called something like gstreamer1-plugins-espeak installed but there is one called gstreamer-plugins-espeak[2] So, I'm a little confused: * Is espeak available on 13.1.0 for gst 0.10? * Is gstreamer-plugins-espeak for gst 0.10 and the version for Gst 1.0 is inside on one of these? (already installed in the build os7): * gstreamer1-1.0.1-1.fc18.i686 * gstreamer1-plugins-base-1.0.1-1.fc18.i686 * gstreamer1-plugins-good-1.0.1-1.fc18.i686 Anyway, I think this activity should work without espeak gstreamer element because it has a workaround to use the /usr/bin/espeak command, save the text into a wav file and finally play it. But for some reason (that I couldn't find yet) the same version (Speak v42) works properly on 12.1.0 but it doesn't work on 13.1.0. [1] http://bugs.sugarlabs.org/ticket/3901 [2] http://build.laptop.org/13.1.0/os7/xo-1.5/31007o1.packages.txt -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] espeak in gst 0.10 on 13.1.0
On Wed, Oct 24, 2012 at 3:28 PM, Peter Robinson pbrobin...@gmail.com wrote: the version in 13.1.0 is for gst1 and built against it. so, there is no way to have both of them, right? I mean, espeak for 0.10 and for 1.0. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] espeak in gst 0.10 on 13.1.0
On Wed, Oct 24, 2012 at 3:46 PM, Peter Robinson pbrobin...@gmail.com wrote: Possibly, it was my understanding that we were moving to gst1 for the activities that use it. Yes, we are moving on that way. Actually, Speak is already ported to Gtk3 and Gst 1.0 but it doesn't work on 13.1.0 (same issue: CPU 100%). So, I'm starting to think that the problem has nothing to do with gstreamer. I asked that because I wanted to test Speak v42 in 13.1.0 with the correct gst 0.10 plugin. Thanks, I'll keep researching about this. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] espeak in gst 0.10 on 13.1.0
On Wed, Oct 24, 2012 at 4:01 PM, Peter Robinson pbrobin...@gmail.com wrote: use rpm to remove the currently installed one and then grab the old one from koji and install it manually. Great! Thanks I used (on XO-1.5 13.1.0 os7): sudo rpm -e --nodeps gstreamer-plugins-espeak wget http://kojipkgs.fedoraproject.org//packages/gstreamer-plugins-espeak/0.3.5/3.fc18/i686/gstreamer-plugins-espeak-0.3.5-3.fc18.i686.rpm sudo rpm -i gstreamer-plugins-espeak-0.3.5-3.fc18.i686.rpm After doing that I'm able to create espeak plugin for gst 0.10 import gst gst.element_factory_make('espeak', 'espeak') __main__.GstEspeak object ... I tested Speak-42 and I have the same problem with the CPU consumption. So, I will change my way of the researching because it seems that it has nothing to do with gstreamer versions. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH ImageViewer] Rotate, Zoom and center the image
Improves the rotation by centering the image on the screen when it is smaller than the screen size. Optimal zoom is calculated for images than are higher in hight when they are rotated as well. Fixed rotation (anti)clockwise. X, Y axis + angles in gradians are handled different by cairo. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- ImageView.py | 113 ++--- ImageViewerActivity.py | 4 +- 2 files changed, 82 insertions(+), 35 deletions(-) diff --git a/ImageView.py b/ImageView.py index 30b19ac..cbc5516 100644 --- a/ImageView.py +++ b/ImageView.py @@ -27,6 +27,7 @@ import logging import cairo import random import time +import math ZOOM_IN_OUT = 0.1 @@ -71,6 +72,7 @@ class ImageViewer(Gtk.DrawingArea): self._fast = True self._redraw_id = None self._is_touching = False +self._switched = False def do_get_property(self, pspec): if pspec.name == 'zoom': @@ -123,35 +125,64 @@ class ImageViewer(Gtk.DrawingArea): h = int(self.surface.get_height() * self.zoom) logging.error('W: %s, H: %s', w, h) -ctx.save() if self._fast: ctx.set_antialias(cairo.ANTIALIAS_NONE) -if self.angle != 0: -logging.error('Rotating: %s', self.angle) -ctx.translate(0.5 * w, 0.5 * h) -ctx.rotate(self.angle) -ctx.translate(-0.5 * w, -0.5 * h) scrolled_window = self.get_parent() rect = scrolled_window.get_allocation() x = y = 0 -if rect.width = w: -x = int((rect.width - w) / 2) -elif self._is_touching: -hadj = int((w - rect.width) / 2) -hadjustment = scrolled_window.get_hadjustment() -hadjustment.set_value(hadj) - -if rect.height = h: -y = int((rect.height - h) / 2) -elif self._is_touching: -vadj = int((h - rect.height) / 2) -vadjustment = scrolled_window.get_vadjustment() -vadjustment.set_value(vadj) +if self.angle != 0: +logging.error('Rotating: %s', self.angle) +ctx.rotate(self.angle) + +if self.angle == math.pi: +ctx.translate(-w, -h) + +if rect.width w: +x = -(rect.width - w) / 2 +if rect.height h: +y = -(rect.height - h) / 2 + +elif self.angle == math.pi / 2: +ctx.translate(0, -h) + +# center the image +if rect.height w: +x = (rect.height - w) / 2 +if rect.width h: +y = -(rect.width - h) / 2 + +elif self.angle == math.pi * 3 / 2: +ctx.translate(-w, 0) + +if rect.height w: +x = -(rect.height - w) / 2 +if rect.width h: +y = (rect.width - h) / 2 + +else: +if rect.width w: +x = int((rect.width - w) / 2) +if rect.height h: +y = int((rect.height - h) / 2) +ctx.translate(x, y) + +if self._is_touching: +if self._switched: +w, h = h, w + +if rect.height h: +vadj = int((h - rect.height) / 2) +vadjustment = scrolled_window.get_vadjustment() +vadjustment.set_value(vadj) + +if rect.width w: +hadj = int((w - rect.width) / 2) +hadjustment = scrolled_window.get_hadjustment() +hadjustment.set_value(hadj) if self.zoom != 1: logging.error('Scaling: %s', self.zoom) -ctx.translate(x, y) ctx.scale(self.zoom, self.zoom) ctx.set_source_surface(self.surface, 0, 0) @@ -171,9 +202,23 @@ class ImageViewer(Gtk.DrawingArea): def _redraw_high_quality(self): self._fast = False self._redraw_id = None -self.queue_draw() +self._redraw() return False +def _redraw(self): +# README: this is a hack to not raise the 'draw' event (again) +# when we request more space to show the scroll bars +w = int(self.surface.get_width() * self.zoom) +h = int(self.surface.get_height() * self.zoom) + +self._switched = False +if (self.angle / (math.pi / 2)) % 2 == 1: +# change image dimensions if it's rotated +w, h = h, w +self._switched = True + +self.set_size_request(w, h) + def set_zoom(self, zoom): self._optimal_zoom_flag = False self._set_zoom(zoom) @@ -191,8 +236,8 @@ class ImageViewer(Gtk.DrawingArea): def set_angle(self, angle): self._optimal_zoom_flag = True -self.angle = angle -self.queue_draw() +self.angle = angle % (2 * math.pi) +self._redraw
Re: [Sugar-devel] [VERY FRUSTRATING] sugar-build requires reboot of the laptop
On Thu, Oct 11, 2012 at 10:46 AM, Ajay Garg a...@activitycentral.com wrote: a) Is there a way to NOT run sugar-build in fullscreen? If yes, then we could simply kill the process by clicking on x icon in the process window of sugar-build. A quick reply. Take a look at this link. That is what I'm using to run Sugar in a VNC window: http://wiki.sugarlabs.org/go/User:Humitos/SugarBuild#Fedora_17_64_bits -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH v3 Browse] Remove temporary downloaded (cancelled) files SL #3973
When a download is cancelled for any reason WebKit leaves a temporary file called .goutputstream-* in the instance directory. This is because of a bug in GLib: * https://bugzilla.gnome.org/show_bug.cgi?id=629301 This patch is a workaround to that behaviour. Every time that Browse is started it looks for all the .goutputstream files in the instance directory and checks its mtime. If it greater than 1 day or it was created before we booted, Browse removes the old temporary file. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- webactivity.py | 38 ++ 1 file changed, 38 insertions(+) diff --git a/webactivity.py b/webactivity.py index dff3a4a..b784476 100644 --- a/webactivity.py +++ b/webactivity.py @@ -241,6 +241,44 @@ class WebActivity(activity.Activity): else: _logger.debug('Created activity') +# README: this is a workaround to remove old temp file +# http://bugs.sugarlabs.org/ticket/3973 +self._cleanup_temp_files() + +def _cleanup_temp_files(self): +Removes temporary files generated by Download Manager that +were cancelled by the user or failed for any reason. + +There is a bug in GLib that makes this to happen: +https://bugzilla.gnome.org/show_bug.cgi?id=629301 + + +try: +uptime_proc = open('/proc/uptime', 'r').read() +uptime = int(float(uptime_proc.split()[0])) +except EnvironmentError: +logging.warning('/proc/uptime could not be read') +uptime = None + +temp_path = os.path.join(self.get_activity_root(), 'instance') +now = int(time.time()) +cutoff = now - 24 * 60 * 60 # yesterday +if uptime is not None: +boot_time = now - uptime +cutoff = max(cutoff, boot_time) + +for f in os.listdir(temp_path): +if f.startswith('.goutputstream-'): +fpath = os.path.join(temp_path, f) +mtime = int(os.path.getmtime(fpath)) +if mtime cutoff: +logging.warning('Removing old temporary file: %s', fpath) +try: +os.remove(fpath) +except EnvironmentError: +logging.error('Temporary file could not be ' + 'removed: %s', fpath) + def _on_focus_url_entry(self, gobject): self._primary_toolbar.entry.grab_focus() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] Turtle Confusion en Español
On Mon, Oct 8, 2012 at 3:51 AM, Barry Newell barry.new...@anu.edu.au wrote: Congratulations to All! Thanks! I'm very happy that you liked our work. It's mutual, we like yours :) The effort that you and your colleagues have put into this project, and the high quality of the end result, have prompted me to go ahead and produce the guide to the riddles. That's an excellent news for me! I will not be able to do it quickly, but I will keep you updated on my progress. I will, unfortunately, have to write it in English. Well, maybe we can help on the translation of it as well if you give us permission. I think Melina would like to help on this translation. It will help us to make sure that the riddles still work after translation into Spanish. I'm not pretty sure of this because we don't solve all the riddles yet but it's something that we have in mind and we will do in the near future. But... Maybe we never get the answers, haha ;) Cheers, PD: we are about to start the translation of Turtles Speak Mathematics on the next week, I guess. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH] Sort the activities in the home in alphabetic order
On Fri, Oct 5, 2012 at 12:41 AM, Gonzalo Odiard godi...@sugarlabs.org wrote: The best we can do is provide a coherent order. Alphabetical using the localized numbers and the same order than in the list view, is the best in my opinion. I was about to suggest that maybe we can sort the activities using the launch-time proposed by Walter on another email -and already applied-. This will make easy to find the most used activities by the kid. I think it's practical but does not freeze the Home View between XOs at all. My 5¢ -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Jukebox 1/8] Use a notebook in the visualization area
Previously an empty widget and a videowidget were packed and removed from a container, but there are problems with the video widget not ready when the player want start at times. Signed-off-by: Gonzalo Odiard gonz...@laptop.org Signed-off-by: Manuel Kaufmann humi...@gmail.com --- jukeboxactivity.py | 25 - 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/jukeboxactivity.py b/jukeboxactivity.py index aebbc98..5132c68 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -150,8 +150,8 @@ class JukeboxActivity(activity.Activity): self._empty_widget = Gtk.Label(label=) self._empty_widget.show() self.videowidget = VideoWidget() -self._switch_canvas(show_video=False) self.set_canvas(self.canvas) +self._init_view_area() self.show_all() self.canvas.connect('size-allocate', self.__size_allocate_cb) @@ -165,6 +165,18 @@ class JukeboxActivity(activity.Activity): self.uri = handle.uri GObject.idle_add(self._start, self.uri, handle.title) +def _init_view_area(self): + +Use a notebook with two pages, one empty an another +with the videowidget + +self.view_area = Gtk.Notebook() +self.view_area.set_show_tabs(False) +self.view_area.append_page(self._empty_widget, None) +self.view_area.append_page(self.videowidget, None) +self.canvas.pack_end(self.view_area, expand=True, + fill=True, padding=0) + def _switch_canvas(self, show_video): Show or hide the video visualization in the canvas. @@ -173,11 +185,9 @@ class JukeboxActivity(activity.Activity): if show_video: -self.canvas.remove(self._empty_widget) -self.canvas.pack_end(self.videowidget, True, True, 0) +self.view_area.set_current_page(1) else: -self.canvas.pack_end(self._empty_widget, True, True, 0) -self.canvas.remove(self.videowidget) +self.view_area.set_current_page(0) self.canvas.queue_draw() def __get_tags_cb(self, tags_reader, order, tags): @@ -288,10 +298,7 @@ class JukeboxActivity(activity.Activity): self.player.stop() self.player.set_uri(None) self.control.set_disabled() -self.canvas.remove(self.videowidget) -text = Gtk.Label(Error: %s - %s % (message, detail)) -text.show_all() -self.canvas.add(text) +self._show_error_alert(Error: %s - %s % (message, detail)) def _player_new_tag_cb(self, widget, tag, value): if not tag in [gst.TAG_TITLE, gst.TAG_ARTIST, gst.TAG_ALBUM]: -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Jukebox 2/8] Remove capsfilter filter because of performance
Without this filter the performance to reproduce videos is great and in audio files the visualization performance is improved as well. The only consequense is the text (artist, track, etc) is rendered without antialiasing. Signed-off-by: Gonzalo Odiard gonz...@laptop.org Signed-off-by: Manuel Kaufmann humi...@gmail.com --- jukeboxactivity.py | 19 +-- 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/jukeboxactivity.py b/jukeboxactivity.py index 5132c68..45bb333 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -754,22 +754,6 @@ class GstPlayer(GObject.GObject): self.bin.add_pad(ghostpad) videoscale.set_property(method, 0) -caps_string = video/x-raw-yuv, -r = self.videowidget.get_allocation() -if r.width 500 and r.height 500: -# Sigh... xvimagesink on the XOs will scale the video to fit -# but ximagesink in Xephyr does not. So we live with unscaled -# video in Xephyr so that the XO can work right. -w = 480 -h = float(w) / float(float(r.width) / float(r.height)) -caps_string += width=%d, height=%d % (w, h) -else: -caps_string += width=480, height=360 -caps = gst.Caps(caps_string) -self.filter = gst.element_factory_make(capsfilter, filter) -self.bin.add(self.filter) -self.filter.set_property(caps, caps) - textoverlay = gst.element_factory_make('textoverlay') self.overlay = textoverlay self.bin.add(textoverlay) @@ -777,8 +761,7 @@ class GstPlayer(GObject.GObject): self.bin.add(conv) videosink = gst.element_factory_make('autovideosink') self.bin.add(videosink) -gst.element_link_many(videoscale, self.filter, textoverlay, conv, -videosink) +gst.element_link_many(videoscale, textoverlay, conv, videosink) self.player.set_property(video-sink, self.bin) def set_overlay(self, title, artist, album): -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Jukebox 5/8] Use 'playbin2' instead of 'playbin'
'playbin' is obsolete and not should be used. I was told in #gstreamer (irc.freenode.net) that 'playbin' is no longer supported, that has some bugs and shouldn't be used anymore. It should be changed by 'playbin2' I had to set some flags as well to keep showing the 'vis-plugin' with 'playbin2' player. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- jukeboxactivity.py | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/jukeboxactivity.py b/jukeboxactivity.py index 11e1331..5c02d23 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -698,7 +698,13 @@ class GstPlayer(GObject.GObject): self.playing = False self.error = False -self.player = gst.element_factory_make(playbin, player) +self.player = gst.element_factory_make(playbin2, player) + +# Set the proper flags to render the vis-plugin +GST_PLAY_FLAG_VIS = 1 3 +GST_PLAY_FLAG_TEXT = 1 2 +self.player.props.flags |= GST_PLAY_FLAG_VIS +self.player.props.flags |= GST_PLAY_FLAG_TEXT r = gst.registry_get_default() l = [x for x in r.get_feature_list(gst.ElementFactory) -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Jukebox 3/8] Stop the player when the user is reproducing a video and switch to another activity.
Signed-off-by: Manuel Kaufmann humi...@gmail.com --- jukeboxactivity.py | 20 +--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/jukeboxactivity.py b/jukeboxactivity.py index 45bb333..97c2de4 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -101,6 +101,11 @@ class JukeboxActivity(activity.Activity): self.connect(key_press_event, self._key_press_event_cb) +# We want to be notified when the activity gets the focus or +# loses it. When it is not active, we don't need to keep +# reproducing the video +self.connect(notify::active, self._notify_active_cb) + # FIXME: this is related with shared activity and it doesn't work # if handle.uri: # pass @@ -126,7 +131,6 @@ class JukeboxActivity(activity.Activity): self.playflag = False self.tags = {} self.only_audio = False -self.got_stream_info = False self.tag_reader = TagReader() self.tag_reader.connect('get-tags', self.__get_tags_cb) @@ -165,6 +169,17 @@ class JukeboxActivity(activity.Activity): self.uri = handle.uri GObject.idle_add(self._start, self.uri, handle.title) +def _notify_active_cb(self, widget, event): +Sugar notify us that the activity is becoming active or inactive. +When we are inactive, we stop the player if it is reproducing +a video. + +if self.player is not None and not self.only_audio: +if not self.player.is_playing() and self.props.active: +self.player.play() +if self.player.is_playing() and not self.props.active: +self.player.pause() + def _init_view_area(self): Use a notebook with two pages, one empty an another @@ -319,7 +334,7 @@ class JukeboxActivity(activity.Activity): self.tags[gst.TAG_ARTIST], album) def _player_stream_info_cb(self, widget, stream_info): -if not len(stream_info) or self.got_stream_info: +if not len(stream_info): return GST_STREAM_TYPE_UNKNOWN = 0 @@ -332,7 +347,6 @@ class JukeboxActivity(activity.Activity): if item.props.type == GST_STREAM_TYPE_VIDEO: only_audio = False self.only_audio = only_audio -self.got_stream_info = True self._update_overlay() def _joined_cb(self, activity): -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Jukebox 4/8] Create GstPlayer just once
Instanciating GstPlayer when Jukebox is launched and changing its uri when a new stream is played. This allow us to change between different streams in the playlist without having many memory issues regarding video playing in HD. To change the stream being played in the GstPlayer instance we firstly set the state of it to STATE_PAUSED, then to STATE_NULL and finally we change the uri. When this process finishes we change the state again to STATE_PLAYING. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- jukeboxactivity.py | 31 +-- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/jukeboxactivity.py b/jukeboxactivity.py index 97c2de4..11e1331 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -169,12 +169,20 @@ class JukeboxActivity(activity.Activity): self.uri = handle.uri GObject.idle_add(self._start, self.uri, handle.title) +# Create the player just once +logging.debug('Instantiating GstPlayer') +self.player = GstPlayer(self.videowidget) +self.player.connect(eos, self._player_eos_cb) +self.player.connect(error, self._player_error_cb) +self.player.connect(tag, self._player_new_tag_cb) +self.player.connect(stream-info, self._player_stream_info_cb) + def _notify_active_cb(self, widget, event): Sugar notify us that the activity is becoming active or inactive. When we are inactive, we stop the player if it is reproducing a video. -if self.player is not None and not self.only_audio: +if self.player.player.props.uri is not None and not self.only_audio: if not self.player.is_playing() and self.props.active: self.player.play() if self.player.is_playing() and not self.props.active: @@ -269,12 +277,6 @@ class JukeboxActivity(activity.Activity): def play(self, media_index): self._switch_canvas(show_video=True) self.currentplaying = media_index -self.player.stop() -self.player = GstPlayer(self.videowidget) -self.player.connect(eos, self._player_eos_cb) -self.player.connect(error, self._player_error_cb) -self.player.connect(tag, self._player_new_tag_cb) -self.player.connect(stream-info, self._player_stream_info_cb) url = self.playlist[self.currentplaying]['url'] error = None if url.startswith('journal://'): @@ -289,7 +291,7 @@ class JukeboxActivity(activity.Activity): if error is None: self.player.set_uri(url) -self.play_toggled() +self.player.play() else: self.control.set_disabled() self._show_error_alert(error) @@ -517,16 +519,6 @@ class JukeboxActivity(activity.Activity): if not error: self.tag_reader.set_file(url, len(self.playlist) - 1) -if not self.player: -# lazy init the player so that videowidget is realized -# and has a valid widget allocation -self._switch_canvas(show_video=True) -self.player = GstPlayer(self.videowidget) -self.player.connect(eos, self._player_eos_cb) -self.player.connect(error, self._player_error_cb) -self.player.connect(tag, self._player_new_tag_cb) -self.player.connect(stream-info, self._player_stream_info_cb) - self.playlist_widget.update(self.playlist) try: @@ -538,6 +530,7 @@ class JukeboxActivity(activity.Activity): url = 'file://' + jobject.file_path self.player.set_uri(url) +self.player.play() self.currentplaying = 0 self.play_toggled() self.show_all() @@ -728,6 +721,8 @@ class GstPlayer(GObject.GObject): bus.connect('message', self.on_message) def set_uri(self, uri): +self.player.set_state(gst.STATE_PAUSED) +self.player.set_state(gst.STATE_NULL) self.player.set_property('uri', uri) def on_sync_message(self, bus, message): -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Jukebox 7/8] Do not pause the stream after adding a new one
After the user adds the first stream to the playlist it is played immediately and when a new stream is added, the first one is kept playing. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- jukeboxactivity.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jukeboxactivity.py b/jukeboxactivity.py index ea66d34..1ad5ff1 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -459,7 +459,7 @@ class JukeboxActivity(activity.Activity): self.playlist_widget.update(self.playlist) try: -if not self.currentplaying: +if self.currentplaying is None: logging.info(Playing: + self.playlist[0]['url']) url = self.playlist[0]['url'] if url.startswith('journal://'): -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Jukebox 6/8] Tag reader feature removed
I removed it because of performance. Jukebox was working too slow when it was reproducing a video and it had to read the tag of the media added to the playlist. So, we decided to remove this feature by the moment. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- jukeboxactivity.py | 119 + 1 file changed, 1 insertion(+), 118 deletions(-) diff --git a/jukeboxactivity.py b/jukeboxactivity.py index 5c02d23..ea66d34 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -129,11 +129,6 @@ class JukeboxActivity(activity.Activity): self.playpath = None self.currentplaying = None self.playflag = False -self.tags = {} -self.only_audio = False - -self.tag_reader = TagReader() -self.tag_reader.connect('get-tags', self.__get_tags_cb) self.p_position = gst.CLOCK_TIME_NONE self.p_duration = gst.CLOCK_TIME_NONE @@ -174,15 +169,13 @@ class JukeboxActivity(activity.Activity): self.player = GstPlayer(self.videowidget) self.player.connect(eos, self._player_eos_cb) self.player.connect(error, self._player_error_cb) -self.player.connect(tag, self._player_new_tag_cb) -self.player.connect(stream-info, self._player_stream_info_cb) def _notify_active_cb(self, widget, event): Sugar notify us that the activity is becoming active or inactive. When we are inactive, we stop the player if it is reproducing a video. -if self.player.player.props.uri is not None and not self.only_audio: +if self.player.player.props.uri is not None: if not self.player.is_playing() and self.props.active: self.player.play() if self.player.is_playing() and not self.props.active: @@ -213,10 +206,6 @@ class JukeboxActivity(activity.Activity): self.view_area.set_current_page(0) self.canvas.queue_draw() -def __get_tags_cb(self, tags_reader, order, tags): -self.playlist[order]['title'] = tags['title'] -self.playlist_widget.update(self.playlist) - def __size_allocate_cb(self, widget, allocation): canvas_size = self.canvas.get_allocation() playlist_width = int(canvas_size.width * PLAYLIST_WIDTH_PROP) @@ -317,40 +306,6 @@ class JukeboxActivity(activity.Activity): self.control.set_disabled() self._show_error_alert(Error: %s - %s % (message, detail)) -def _player_new_tag_cb(self, widget, tag, value): -if not tag in [gst.TAG_TITLE, gst.TAG_ARTIST, gst.TAG_ALBUM]: -return -self.tags[tag] = value -self._update_overlay() - -def _update_overlay(self): -if self.only_audio == False: -return -if not gst.TAG_TITLE in self.tags or \ -not gst.TAG_ARTIST in self.tags: -return -album = None -if gst.TAG_ALBUM in self.tags: -album = self.tags[gst.TAG_ALBUM] -self.player.set_overlay(self.tags[gst.TAG_TITLE], -self.tags[gst.TAG_ARTIST], album) - -def _player_stream_info_cb(self, widget, stream_info): -if not len(stream_info): -return - -GST_STREAM_TYPE_UNKNOWN = 0 -GST_STREAM_TYPE_AUDIO = 1 -GST_STREAM_TYPE_VIDEO = 2 -GST_STREAM_TYPE_TEXT = 3 - -only_audio = True -for item in stream_info: -if item.props.type == GST_STREAM_TYPE_VIDEO: -only_audio = False -self.only_audio = only_audio -self._update_overlay() - def _joined_cb(self, activity): logging.debug(someone joined) pass @@ -500,24 +455,6 @@ class JukeboxActivity(activity.Activity): else: uri = file:// + urllib.quote(os.path.abspath(uri)) self.playlist.append({'url': uri, 'title': title}) -if uri.endswith(title) or title is None or title == '' or \ -object_id is not None: -error = False -logging.error('Try get a better title reading tags') -# TODO: unify this code -url = self.playlist[len(self.playlist) - 1]['url'] -if url.find('home') 0: -url = url[len(journal://):] -url = 'file://' + url -elif url.startswith('journal://'): -try: -jobject = datastore.get(url[len(journal://):]) -url = 'file://' + jobject.file_path -except: -error = True -# jobject.destroy() ?? -if not error: -self.tag_reader.set_file(url, len(self.playlist) - 1) self.playlist_widget.update(self.playlist) @@ -642,54 +579,11 @@ class JukeboxActivity(activity.Activity): self.canvas.queue_draw() -class TagReader(GObject.GObject): - -__gsignals__ = { -'get-tags
[Sugar-devel] [PATCH Jukebox 8/8] Port gst 0.10 to Gst 1.0
Useful guide: * https://wiki.ubuntu.com/Novacut/GStreamer1.0 Signed-off-by: Manuel Kaufmann humi...@gmail.com --- jukeboxactivity.py | 180 ++--- 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/jukeboxactivity.py b/jukeboxactivity.py index 1ad5ff1..48a5aa8 100644 --- a/jukeboxactivity.py +++ b/jukeboxactivity.py @@ -40,15 +40,23 @@ from sugar3.graphics.alert import ErrorAlert import gi gi.require_version('Gtk', '3.0') +gi.require_version('Gst', '1.0') from gi.repository import GObject from gi.repository import Gdk - -import pygst -pygst.require('0.10') -import gst -import gst.interfaces from gi.repository import Gtk +from gi.repository import Gst + +# Needed for window.get_xid(), xvimagesink.set_window_handle(), +# respectively: +from gi.repository import GdkX11, GstVideo + +# Avoid Fatal Python error: GC object already tracked +# http://stackoverflow.com/questions/7496629/gstreamer-appsrc-causes-random-crashes +GObject.threads_init() + +# Initialize GStreamer +Gst.init(None) import urllib from ControlToolbar import Control, ViewToolbar @@ -130,9 +138,6 @@ class JukeboxActivity(activity.Activity): self.currentplaying = None self.playflag = False -self.p_position = gst.CLOCK_TIME_NONE -self.p_duration = gst.CLOCK_TIME_NONE - # README: I changed this because I was getting an error when I # tried to modify self.bin with something different than # Gtk.Bin @@ -169,6 +174,8 @@ class JukeboxActivity(activity.Activity): self.player = GstPlayer(self.videowidget) self.player.connect(eos, self._player_eos_cb) self.player.connect(error, self._player_error_cb) +self.p_position = Gst.CLOCK_TIME_NONE +self.p_duration = Gst.CLOCK_TIME_NONE def _notify_active_cb(self, widget, event): Sugar notify us that the activity is becoming active or inactive. @@ -524,7 +531,7 @@ class JukeboxActivity(activity.Activity): real = long(scale.get_value() * self.p_duration / 100) # in ns self.player.seek(real) # allow for a preroll -self.player.get_state(timeout=50 * gst.MSECOND) # 50 ms +self.player.get_state(timeout=50 * Gst.MSECOND) # 50 ms def scale_button_release_cb(self, widget, event): # see seek.cstop_seek @@ -546,8 +553,13 @@ class JukeboxActivity(activity.Activity): self.update_scale_cb) def update_scale_cb(self): -self.p_position, self.p_duration = self.player.query_position() -if self.p_position != gst.CLOCK_TIME_NONE: +success, self.p_position, self.p_duration = \ +self.player.query_position() + +if not success: +return True + +if self.p_position != Gst.CLOCK_TIME_NONE: value = self.p_position * 100.0 / self.p_duration self.control.adjustment.set_value(value) @@ -558,7 +570,7 @@ class JukeboxActivity(activity.Activity): # FIXME: this should be updated just once when the file starts # the first time -if self.p_duration != gst.CLOCK_TIME_NONE: +if self.p_duration != Gst.CLOCK_TIME_NONE: seconds = self.p_duration * 10 ** -9 time = '%2d:%02d' % (int(seconds / 60), int(seconds % 60)) self.control.total_time_label.set_text(time) @@ -592,7 +604,22 @@ class GstPlayer(GObject.GObject): self.playing = False self.error = False -self.player = gst.element_factory_make(playbin2, player) +# Create GStreamer pipeline +self.pipeline = Gst.Pipeline() +# Create bus to get events from GStreamer pipeline +self.bus = self.pipeline.get_bus() +self.bus.add_signal_watch() + +self.bus.connect('message::eos', self.__on_eos_message) +self.bus.connect('message::error', self.__on_error_message) + +# This is needed to make the video output in our DrawingArea +self.bus.enable_sync_message_emission() +self.bus.connect('sync-message::element', self.__on_sync_message) + +# Create GStreamer elements +self.player = Gst.ElementFactory.make('playbin', None) +self.pipeline.add(self.player) # Set the proper flags to render the vis-plugin GST_PLAY_FLAG_VIS = 1 3 @@ -600,12 +627,12 @@ class GstPlayer(GObject.GObject): self.player.props.flags |= GST_PLAY_FLAG_VIS self.player.props.flags |= GST_PLAY_FLAG_TEXT -r = gst.registry_get_default() -l = [x for x in r.get_feature_list(gst.ElementFactory) -if (gst.ElementFactory.get_klass(x) == Visualization)] +r = Gst.Registry.get() +l = [x for x in r.get_feature_list(Gst.ElementFactory) + if (x.get_metadata('klass') == Visualization)] if len(l): e = l.pop() # take latest plugin in the list -vis_plug
Re: [Sugar-devel] ImageViewer (gtk3) traceback
On Thu, Oct 4, 2012 at 1:54 PM, Gary Martin garycmar...@googlemail.com wrote: /me wonders if he dare mention this to Gonzalo as a solution for the same issue in Read Maybe we can design a widget for this and include it in sugar-toolkit-gtk3 so we will have more consistency between activities. What do you think? -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] Jukebox patches
Hello people, I've just sent 8 patches to the sugar-devel mailing list for Jukebox. Seven of them are those ones that were applied to the sugar-0.98 (gtk2) branch that I ported to the master branch. The last one is the port of gstreamer from 0.10 to 1.0. Yesterday I was working a lot on Jukebox itself, removing some old code, rewriting some other functions and doing some bugfixing as well. I'm preparing some patches that I will be sending later. Thanks, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] GStreamer 1.0.0 has been released
On Wed, Oct 3, 2012 at 10:51 AM, Peter Robinson pbrobin...@gmail.com wrote: Ultimately I'm sure we'd like to drop 0.10 if at all possible just so we don't need to ship two copies and any of the deps that go with it. I'm working on the port of Jukebox to Gst 1.0 and I have it quite stable but I'm doing some of my tests on my F17 Desktop with sugar-build because I'm not sure how to install Gst1.0 with ugly plugins and video support(*) on XO 1.75 with 13.1.0. (*) Martin and Jon told me that video support is not available yet for 13.1.0 -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH v2 Browse] Remove temporary downloaded (cancelled) files SL #3973
On Wed, Oct 3, 2012 at 12:08 PM, Martin Langhoff martin.langh...@gmail.com wrote: Not at all. Ignoring the computer is not elegance. OK. I will send a new version of this patch with all the things that we were discussing. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] Gst1.0 plugins in sugar-build
Hello, I'd like to comment that there are many Gst 1.0 plugin decoders that are not built because of missing dependencies. I had to install libmad-devel.x86_64 (on my F17) to be able to play MP3 files from Jukebox. Daniel, can be this package added as a dependency for sugar-build? Cheers, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] Gst1.0 plugins in sugar-build
On Wed, Oct 3, 2012 at 6:08 PM, Peter Robinson pbrobin...@gmail.com wrote: The advantage of gstreamer is you can add extra codecs easily by just installing packages and without recompiling anything and the functionality should just work without any changes in the application so I'm not sure why it's a needed requirement. That's why I wasn't sure. This library is not a dependency but gstreamer 1.0 is not as well and it's inside sugar-build. That's why I was asking. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] touch_test.py resutls
On Mon, Oct 1, 2012 at 11:59 PM, Agustin Zubiaga Sanchez a...@sugarlabs.org wrote: Would be nice to have a touch example Activity. What do you think? Yes. I started a HelloTouchGestures some time ago when SugarGestures weren't developed yet and I used a known algorithm to match gestures. Do you want to migrate this activity to the new way (using from gi.repository import SugarGestures)? If you say yes, I can add you as commiter. This is the repo: * http://git.sugarlabs.org/hello-touch-gesture -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Remove temporary downloaded (cancelled) files SL #3973
On Tue, Oct 2, 2012 at 6:40 AM, Martin Langhoff martin.langh...@gmail.com wrote: Good, but not enough. Compare mtime also to our boot time (ie: now - uptime). If the file is from before we booted, needs to be nuked. You say that I should add this test as well, right? I mean, compare if the file is older than 1 day AND check the mtime with our boot time or remove my test and use only this one? I think that comparing just with the boot time is not enough as well. Think about this scenario: turn on the XO, use Browse for a while, download and cancel many files, close Brose and close the lid. It will suspend. So, if you repeat these steps every day and you never power off / restart the XO, these kind of files won't be removed. Am I right? -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH v2 Browse] Remove temporary downloaded (cancelled) files SL #3973
When a download is cancelled for any reason WebKit leaves a temporary file called .goutputstream-* in the instance directory. This is because of a bug in GLib: * https://bugzilla.gnome.org/show_bug.cgi?id=629301 This patch is a workaround to that behaviour. Every time that Browse is started it looks for all the .goutputstream files in the instance directory and checks its mtime. If it greater than 1 day or it was created before we booted, Browse removes the old temporary file. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- webactivity.py | 38 ++ 1 file changed, 38 insertions(+) diff --git a/webactivity.py b/webactivity.py index dff3a4a..8c66ac5 100644 --- a/webactivity.py +++ b/webactivity.py @@ -37,6 +37,7 @@ from gi.repository import GConf import locale import cairo import StringIO +import datetime from hashlib import sha1 from sugar3.activity import activity @@ -241,6 +242,43 @@ class WebActivity(activity.Activity): else: _logger.debug('Created activity') +# README: this is a workaround to remove old temp file +# http://bugs.sugarlabs.org/ticket/3973 +self._cleanup_temp_files() + +def _cleanup_temp_files(self): +Removes temporary files generated by Download Manager that +were cancelled by the user or failed for any reason. + +There is a bug in GLib that makes this to happen: +https://bugzilla.gnome.org/show_bug.cgi?id=629301 + + +try: +uptime_proc = open('/proc/uptime', 'r').read() +uptime_seconds = float(uptime_proc.split()[0]) +uptime = datetime.timedelta(seconds=uptime_seconds) +except: +logging.warning('/proc/uptime could not be read') +uptime = None + +temp_path = os.path.join(self.get_activity_root(), 'instance') +now = datetime.datetime.now() +for f in os.listdir(temp_path): +if f.startswith('.goutputstream-'): +fpath = os.path.join(temp_path, f) +mtime = os.path.getmtime(fpath) +mdate = datetime.datetime.fromtimestamp(mtime) +delta = now - mdate +if delta.days 0 or \ +(uptime is not None and (now - uptime) mdate): +logging.warning('Removing old temporary file: %s', fpath) +try: +os.remove(fpath) +except OSError: +logging.error('Temporary file could not be ' + 'removed: %s', fpath) + def _on_focus_url_entry(self, gobject): self._primary_toolbar.entry.grab_focus() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] touch_test.py resutls
On Tue, Oct 2, 2012 at 10:32 AM, Agustin Zubiaga Sanchez a...@sugarlabs.org wrote: Yes, I can help you but I don't have a touch XO, so I can't test it. However, I could program it hypothetically, if you want (and you can), to test my changes. I can test your changes if you want but I think it's really boring to develop in blind-mode :D -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH v2 Browse] Remove temporary downloaded (cancelled) files SL #3973
On Tue, Oct 2, 2012 at 1:43 PM, Martin Langhoff martin.langh...@gmail.com wrote: +except: +logging.warning('/proc/uptime could not be read') +uptime = None Should I use EnvironmentError[1] here too? Tiny optimization and elegance improvement: just calculate your cutoff here. The cutoff is the largest of - yesterday (now - 1 day) - boottime (now - uptime) -- if you managed to read uptime What do you think about this? cutoff = now - datetime.timedelta(days=1) if uptime is not None: boot_time = now - uptime cutoff = max(yesterday, boot_time) Should catch both OSError _and_ IOError. Or perhaps EnvironmentError which, strange as the name might sound, is the granddaddy of both. Yes, you are right [1] http://docs.python.org/library/exceptions.html#exceptions.EnvironmentError -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH 4/7] metadatareader: ignore .hidden files
On Fri, Sep 21, 2012 at 12:55 AM, Martin Langhoff mar...@laptop.org wrote: Ignore any file with a filename starting with a '.' -- metadatastore writes its tempfiles prefixed with a '.' . This patch is OK for me. Just a comment: this patch removes the possibility to have a property named ..property, right? is this OK? Is any activity setting a property that its name starts with .? We should check that and change its name. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Remove temporary downloaded (cancelled) files SL #3973
When a download is cancelled for any reason WebKit leaves a temporary file called .goutputstream-* in the instance directory. This is because of a bug in GLib: * https://bugzilla.gnome.org/show_bug.cgi?id=629301 This patch is a workaround to that behaviour. Every time that Browse is started it looks for all the .goutputstream files in the instance directory and checks its mtime. If it greater than 1 day it removes the old temporary file. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- webactivity.py | 29 + 1 file changed, 29 insertions(+) diff --git a/webactivity.py b/webactivity.py index dff3a4a..6ba1099 100644 --- a/webactivity.py +++ b/webactivity.py @@ -37,6 +37,7 @@ from gi.repository import GConf import locale import cairo import StringIO +import datetime from hashlib import sha1 from sugar3.activity import activity @@ -241,6 +242,34 @@ class WebActivity(activity.Activity): else: _logger.debug('Created activity') +# README: this is a workaround to remove old temp file +# http://bugs.sugarlabs.org/ticket/3973 +self._cleanup_temp_files() + +def _cleanup_temp_files(self): +Removes temporary files generated by Download Manager that +were cancelled by the user or failed for any reason. + +There is a bug in GLib that makes this to happen: +https://bugzilla.gnome.org/show_bug.cgi?id=629301 + + +temp_path = os.path.join(self.get_activity_root(), 'instance') +for f in os.listdir(temp_path): +if f.startswith('.goutputstream-'): +fpath = os.path.join(temp_path, f) +mdate = datetime.datetime.fromtimestamp( +os.path.getmtime(fpath)) +now = datetime.datetime.now() +delta = now - mdate +if delta.days 0: +logging.warning('Removing old temporary file: %s', fpath) +try: +os.remove(fpath) +except OSError: +logging.error('Temporary file could not be ' + 'removed: %s', fpath) + def _on_focus_url_entry(self, gobject): self._primary_toolbar.entry.grab_focus() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Handle LoadInterruptedByPolicyChange SL #3972
This error is raised when the mimetype policy suffers a change. When this happens __load_error_cb is called and we were showing the error page in any case. With this patch that case is properly handled in __load_error_cb and the error page is not shown on the current tab. In fact, we keep the same page where the user clicked the link in the tab. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- browser.py | 6 ++ 1 file changed, 6 insertions(+) diff --git a/browser.py b/browser.py index fb8a985..ccdf78c 100644 --- a/browser.py +++ b/browser.py @@ -653,6 +653,12 @@ class Browser(WebKit.WebView): 'url': uri, } +# Don't show error page if the load was interrupted by policy +# change. For example, if a file was requested for download +if web_error.code == WebKit.PolicyError.\ +FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE: +return True + html = open(DEFAULT_ERROR_PAGE, 'r').read() % data web_frame.load_alternate_string(html, '', uri) -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [DESIGN] List View of Activities (hovering stars)
On Sat, Sep 29, 2012 at 6:00 PM, Gary Martin garycmar...@googlemail.com wrote: So if the star is currently enabled (colorized) and you hover over it, you'll first see the grey rounded rectangle outline, then if you click/press it you will still see the grey rectangle outline and the star will change immediately to disabled (uncolorized star), as you release and move the mouse away the grey rounded rectangle outline will disappear. If the star is currently disabled (uncolorized) and you hover over it, you'll first see the grey rounded rectangle outline, then if you click/press it you will still see the grey rectangle outline and the star will change immediately to enabled (colorized star), as you release and move the mouse away the grey rounded rectangle outline will disappear. Cool! This is exactly what I tried to write. Thanks to clarify it. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH 1/7] Add ds_clean flag to trigger index rebuilds #2095, #2317
On Fri, Sep 21, 2012 at 12:55 AM, Martin Langhoff mar...@laptop.org wrote: This gives us more complete coverage of cases where ENOSPC or other errors are hit when creating/updating datastore entries. I reviewed this patch and I think it's OK. I didn't test it because I'm not sure how to simulate that scenario. Just a comment: why you didn't add a callback function (_delete_completion_cb) to the delete method and make create / update / delete consistent between them? In that method we can add self._mark_clean Thought: we are dealing near ENOSPC, right? So, maybe the clean_flag will not be created (this is already handled in the patch) and this patch will not take effect the next time the XO restarts and we will be in the same situation again. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH 2/7] Remove invalid/corrupt on-disk entries #2317
On Fri, Sep 21, 2012 at 12:55 AM, Martin Langhoff mar...@laptop.org wrote: When operating close to ENOSPC, we sometimes end up with incomplete or invalid on-disk entries. So we prune these during index rebuild. I took a look at this patch and it seems to be OK. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH 3/7] metadatastore: store/change files on disk defensively #2317
Hi, I reviewed this patch and it seems to be OK for me. The only thing that I do not understand well is this comment / section. Can you explain to me this a bit more? Thanks On Fri, Sep 21, 2012 at 12:55 AM, Martin Langhoff mar...@laptop.org wrote: +# FIXME: this codepath handles raw image data +# str() is 8-bit clean right now, but +# this won't last. We will need more explicit +# handling of strings, int/floats vs raw data +if isinstance(value, unicode): +value = value.encode('utf-8') +elif not isinstance(value, basestring): +value = str(value) -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [sugar-toolkit-gtk2] Add management of summary property to the activity.info file - v2
On Thu, Sep 20, 2012 at 12:34 PM, godi...@sugarlabs.org wrote: +self._summary = None +self._local_summary = None Sorry to bother you, I have two questions: * What each of these variable mean? * What are the difference between them? -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [DESIGN] List View of Activities (hovering stars)
Hello, I've just realize that there is no feedback on clicking on the star in the List View to make it Favorite. 1. Go to Home View 2. Click on List View 3. Hover one the star of one no-favorite Activity 4. The star gets colorized 5. Click on it 6. Did I click? Maybe we can use a 0.5 alpha star when the user is hovering the star of a no-favorite Activity to highlight it but showing that it's not activated and 1.0 after a click. Wikipedia on its rating feature uses a circle to show what star you are hovering. Here is an example at the bottom of the page: * http://es.wikipedia.org/wiki/New_X-Men What do you think? -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [DESIGN] List View of Activities (hovering stars)
On Sat, Sep 29, 2012 at 3:52 PM, Gary Martin garycmar...@googlemail.com wrote: I think my last suggestion was that we should be using the round grey rectangle outline to show hover, press visual feedback (as we do in the Home view for Activity icons, though this is currently broken after the GTK3 shell port and theming), this sounds like a similar fix as to the UI you linked to in wikipedia. So, we will have 4 states: 1. Pressed and un hovered: colorized star without grey rectangle 2. Pressed and hovered: colorized star with grey rectangle 3. Unpressed and un hovered: uncolorized star without grey rectangle 4. Unpressed and hovered: uncolorized star withtout grey rectangle So, if I click on the star in the 4) state I will get 2) immediately, right? I like this way. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] scale-changed and angle-changed events
Hello, I'm working on ImageViewer using SugarGestures.ZoomController and SugarGestures.RotateController with the signals: angle-changed and scale-changed. I realized that those signals are trigged without a change on those values. For example, if I simply touch the screen with two fingers and do not move them (just keep them frozen into the screen) I receive a lot of calls to the callback function associated to those events with the same scale, angle and diff values. I think it's a bug upstream but maybe I'm confused about how it should work. Thanks, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [RELEASE] Browse-141
On Fri, Sep 28, 2012 at 11:37 AM, Manuel Quiñones ma...@laptop.org wrote: The Palettes are back, nice page for errors, and many more fixes release. I'm very happy with this release. Thanks to manuq and gary for they help! -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] last-minute feature proposal for 0.98
On Fri, Sep 28, 2012 at 11:19 AM, Walter Bender walter.ben...@gmail.com wrote: +self._jobject.metadata['launch-times'] = '%s, %d' % ( +self._jobject.metadata['launch-times'], +int(time.time())) Another approach for this portion. Maybe more readable... or not :) self._jobject.metadata['launch-times'] += ', %d' % int(time.time()) -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Display only the URL in the URL entry SL #3553
On Thu, Sep 27, 2012 at 11:25 AM, Martin Langhoff martin.langh...@gmail.com wrote: - The tabs are often too small to show the title. This behaviour is going to change because we are going to use the same version of the tabs that is on the Gtk3 port of Terminal. They use all the available space to be expanded. - The title is more important for the user than the URL. No? I think it's a good idea to show both of them. Personally, I agreed with this feature. It's the way that many browsers work. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] Performace in os3
Hello, I'm working on my 1.75 XO with os3 and I feel it really slow. There are some examples: - Hover in Favourite and List view 1. Hover in Favourite view 2. Move the mouse directly to List view and hover it 3. It shows the palette after the timeout but the palette square appears first and then the text (test this many times because sometimes does not happen) - Show and Hide the frame 1. Go to the edge of the screen 2. The frame appears 3. Go again to the edge of the screen (to make the frame hides) -- comment: this works different than before, it was no needed to go again to the edge of the screen to make it disappears. 4. The frame disappears but it leaves the same frame (width and hight) in gray color for a while Besides, I noticed that when you hover on Home Icons they are no longer highlighted as it was gtk2 version of Sugar. Is this a desired behaviour? See you, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Error page SL #3500
On Fri, Sep 21, 2012 at 8:32 PM, Martin Langhoff martin.langh...@gmail.com wrote: So just put img src=file:///path/to/file . That saves a some of pointless CPU cycles, some RAM. This old man doesn't like inefficient code, even in small details. I agree with you in this point but I would like to mention that this feature (reading from file:// uri) has to be enabled because it is not enabled by default[1] and this is because it was marked as a security issue[2]. ** Message: console message: @0: Not allowed to load local resource: file:///home/humitos/src/browse/browse.png What do you think? Should I go for the file:// approach anyway? [1] http://webkitgtk.org/reference/webkitgtk/stable/WebKitWebSettings.html#WebKitWebSettings--enable-file-access-from-file-uris [2] http://en.wikipedia.org/wiki/File_URI_scheme -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Undo close tab SL #3534
Browse manages a list of 10 recently closed tab to be able to re-open them (the most recently closed is opened firstly) by pressing Ctrl+Shift+T. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- browser.py | 13 + webactivity.py | 11 +-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/browser.py b/browser.py index de546f2..8f960cc 100644 --- a/browser.py +++ b/browser.py @@ -19,6 +19,7 @@ import os import time import re +import collections from gettext import gettext as _ from gi.repository import GObject @@ -99,6 +100,16 @@ class TabbedView(BrowserNotebook): self._update_closing_buttons() self._update_tab_sizes() +# LIFO queue of closed tabs (10 tabs max) +self.closed_tabs = collections.deque(maxlen=10) + +def get_last_closed_tab(self): +try: +uri = self.closed_tabs.pop() +except IndexError: +uri = None +return uri + def normalize_or_autosearch_url(self, url): Normalize the url input or return a url for search. @@ -164,6 +175,8 @@ class TabbedView(BrowserNotebook): self._update_tab_sizes() def __page_removed_cb(self, notebook, child, pagenum): +self.closed_tabs.append(child._browser.props.uri) + if self.get_n_pages(): self._update_closing_buttons() self._update_tab_sizes() diff --git a/webactivity.py b/webactivity.py index 24f3b44..2559fa7 100644 --- a/webactivity.py +++ b/webactivity.py @@ -428,8 +428,15 @@ class WebActivity(activity.Activity): def _key_press_cb(self, widget, event): key_name = Gdk.keyval_name(event.keyval) browser = self._tabbed_view.props.current_browser - -if event.get_state() Gdk.ModifierType.CONTROL_MASK: +state = event.get_state() + +if state Gdk.ModifierType.CONTROL_MASK: +if state Gdk.ModifierType.SHIFT_MASK: +if key_name == 'T': +uri = self._tabbed_view.get_last_closed_tab() +if uri is not None: +self._tabbed_view.current_browser.emit('new-tab', uri) +return True if key_name == 'd': self._add_link() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Show Bookmark toolbar when a bookmark is added SL #3868
The Bookmark toolbar is shown when the first bookmark is added by the user. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- webactivity.py | 1 - 1 file changed, 1 deletion(-) diff --git a/webactivity.py b/webactivity.py index 24f3b44..f9497db 100644 --- a/webactivity.py +++ b/webactivity.py @@ -172,7 +172,6 @@ class WebActivity(activity.Activity): self._tray = HTray() self.set_tray(self._tray, Gtk.PositionType.BOTTOM) -self._tray.show() self._primary_toolbar = PrimaryToolbar(self._tabbed_view, self) self._edit_toolbar = EditToolbar(self) -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Display only the URL in the URL entry SL #3553
The Title of the current page is no longer shown in the URL entry. Now, it's only shown in the tab and the current URL is visible all the time in the URL entry. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- browser.py| 13 + webtoolbar.py | 53 + 2 files changed, 18 insertions(+), 48 deletions(-) diff --git a/browser.py b/browser.py index de546f2..1c67beb 100644 --- a/browser.py +++ b/browser.py @@ -453,6 +453,10 @@ class Browser(WebKit.WebView): # Scale text and graphics: self.set_full_content_zoom(True) +# This property is used to set the title immediatly the user +# presses Enter on the URL Entry +self._loading_uri = None + # Reference to the global history and callbacks to handle it: self._global_history = globalhistory.get_global_history() self.connect('notify::load-status', self.__load_status_changed_cb) @@ -542,6 +546,15 @@ class Browser(WebKit.WebView): def open_new_tab(self, url): self.emit('new-tab', url) +def _set_loading_uri(self, uri): +self._loading_uri = uri + +def _get_loading_uri(self): +return self._loading_uri + +loading_uri = GObject.property(type=str, setter=_set_loading_uri, + getter=_get_loading_uri) + def __run_file_chooser(self, browser, request): picker = FilePicker(self) chosen = picker.run() diff --git a/webtoolbar.py b/webtoolbar.py index 28bc015..1d531bc 100644 --- a/webtoolbar.py +++ b/webtoolbar.py @@ -47,7 +47,6 @@ class WebEntry(iconentry.IconEntry): GObject.GObject.__init__(self) self._address = None -self._title = None self._search_view = self._search_create_view() self._search_window = Gtk.Window(type=Gtk.WindowType.POPUP) @@ -57,8 +56,6 @@ class WebEntry(iconentry.IconEntry): self.connect('focus-in-event', self.__focus_in_event_cb) self.connect('populate-popup', self.__populate_popup_cb) self.connect('key-press-event', self.__key_press_event_cb) -self.connect('enter-notify-event', self.__enter_notify_event_cb) -self.connect('leave-notify-event', self.__leave_notify_event_cb) self._focus_out_hid = self.connect( 'focus-out-event', self.__focus_out_event_cb) self._change_hid = self.connect('changed', self.__changed_cb) @@ -79,18 +76,11 @@ class WebEntry(iconentry.IconEntry): def _set_address(self, address): self._address = address -if address is not None and self.props.has_focus: +if address is not None: self._set_text(address) address = GObject.property(type=str, setter=_set_address) -def _set_title(self, title): -self._title = title -if title is not None and not self.props.has_focus: -self._set_text(title) - -title = GObject.property(type=str, setter=_set_title) - def _search_create_view(self): view = Gtk.TreeView() view.props.headers_visible = False @@ -146,21 +136,11 @@ class WebEntry(iconentry.IconEntry): self._search_window.hide() def __focus_in_event_cb(self, entry, event): -self._set_text(self._address) self._search_popdown() def __focus_out_event_cb(self, entry, event): -self._set_text(self._title) self._search_popdown() -def __enter_notify_event_cb(self, entry, event): -if not entry.props.has_focus: -self._set_text(self._address) - -def __leave_notify_event_cb(self, entry, event): -if not entry.props.has_focus: -self._set_text(self._title) - def __view_button_press_event_cb(self, view, event): model = view.get_model() @@ -241,7 +221,6 @@ class PrimaryToolbar(ToolbarBase): self._tabbed_view = tabbed_view self._loading = False -self._title = _('Untitled') toolbar = self.toolbar activity_button = ActivityToolbarButton(self._activity) @@ -310,7 +289,6 @@ class PrimaryToolbar(ToolbarBase): self._loading_changed_hid = None self._progress_changed_hid = None self._session_history_changed_hid = None -self._title_changed_hid = None self._uri_changed_hid = None if tabbed_view.get_n_pages(): @@ -324,25 +302,19 @@ class PrimaryToolbar(ToolbarBase): def _connect_to_browser(self, browser): if self._browser is not None: -self._browser.disconnect(self._title_changed_hid) self._browser.disconnect(self._uri_changed_hid) self._browser.disconnect(self._progress_changed_hid) self._browser.disconnect(self._loading_changed_hid) self._browser = browser -if self._browser.props.title: -self._set_title(self._browser.props.title) -else: -self._set_title(_('Untitled
[Sugar-devel] [PATCH v2 Browse] Busy indication SL #851
Show WATCH Cursor when the page is loading and LEFT_PTR when the load finishes. This changes take in consideration the tab that the user is watching, so the cursor refers to the state of the current browser / tab. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- browser.py | 21 + webactivity.py | 16 2 files changed, 37 insertions(+) diff --git a/browser.py b/browser.py index de546f2..99b05d4 100644 --- a/browser.py +++ b/browser.py @@ -39,6 +39,8 @@ import globalhistory import downloadmanager from pdfviewer import PDFTabPage +from webactivity import NORMAL_CURSOR, WATCH_CURSOR + ZOOM_ORIGINAL = 1.0 _ZOOM_AMOUNT = 0.1 _LIBRARY_PATH = '/usr/share/library-common/index.html' @@ -188,10 +190,26 @@ class TabbedView(BrowserNotebook): self.set_current_page(next_index) tab_page.setup(url) +def __load_status_changed_cb(self, widget, param): +# Do not change the cursor if the load-status changed is not +# on the current browser +if self.props.current_browser != widget: +return + +status = widget.get_load_status() +if status in (WebKit.LoadStatus.PROVISIONAL, + WebKit.LoadStatus.COMMITTED, + WebKit.LoadStatus.FIRST_VISUALLY_NON_EMPTY_LAYOUT): +self.get_window().set_cursor(WATCH_CURSOR) +elif status in (WebKit.LoadStatus.FAILED, +WebKit.LoadStatus.FINISHED): +self.get_window().set_cursor(NORMAL_CURSOR) + def add_tab(self, next_to_current=False): browser = Browser() browser.connect('new-tab', self.__new_tab_cb) browser.connect('open-pdf', self.__open_pdf_in_new_tab_cb) +browser.connect('notify::load-status', self.__load_status_changed_cb) if next_to_current: self._insert_tab_next(browser) @@ -318,6 +336,8 @@ class TabbedView(BrowserNotebook): browser = Browser() browser.connect('new-tab', self.__new_tab_cb) browser.connect('open-pdf', self.__open_pdf_in_new_tab_cb) +browser.connect('notify::load-status', +self.__load_status_changed_cb) self._append_tab(browser) browser.set_history(tab_history) @@ -404,6 +424,7 @@ class TabLabel(Gtk.HBox): def __load_status_changed_cb(self, widget, param): status = widget.get_load_status() + if status == WebKit.LoadStatus.FAILED: self._label.set_text(self._title) elif WebKit.LoadStatus.PROVISIONAL = status \ diff --git a/webactivity.py b/webactivity.py index 24f3b44..88555e6 100644 --- a/webactivity.py +++ b/webactivity.py @@ -54,6 +54,9 @@ from sugar3.graphics.toolbarbox import ToolbarButton PROFILE_VERSION = 2 +NORMAL_CURSOR = Gdk.Cursor(Gdk.CursorType.LEFT_PTR) +WATCH_CURSOR = Gdk.Cursor(Gdk.CursorType.WATCH) + _profile_version = 0 _profile_path = os.path.join(activity.get_activity_root(), 'data/gecko') _version_file = os.path.join(_profile_path, 'version') @@ -169,6 +172,7 @@ class WebActivity(activity.Activity): self._force_close = False self._tabbed_view = TabbedView() self._tabbed_view.connect('focus-url-entry', self._on_focus_url_entry) +self._tabbed_view.connect('switch-page', self.__switch_page_cb) self._tray = HTray() self.set_tray(self._tray, Gtk.PositionType.BOTTOM) @@ -596,6 +600,18 @@ class WebActivity(activity.Activity): downloadmanager.remove_all_downloads() self.close() +def __switch_page_cb(self, tabbed_view, page, page_num): +browser = page._browser +status = browser.get_load_status() + +if status in (WebKit.LoadStatus.COMMITTED, + WebKit.LoadStatus.FIRST_VISUALLY_NON_EMPTY_LAYOUT): +self.get_window().set_cursor(WATCH_CURSOR) +elif status in (WebKit.LoadStatus.PROVISIONAL, +WebKit.LoadStatus.FAILED, +WebKit.LoadStatus.FINISHED): +self.get_window().set_cursor(NORMAL_CURSOR) + def get_document_path(self, async_cb, async_err_cb): browser = self._tabbed_view.props.current_browser browser.get_source(async_cb, async_err_cb) -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Error page SL #3500
On Wed, Sep 19, 2012 at 10:56 PM, Martin Langhoff martin.langh...@gmail.com wrote: You have the file on-disk. It is inefficient to base64-encode it. I'm not sure to understand what you are saying here. I'm not doing this each time the function is called. Here, I just showed what I did to get the base64 file encoded. I mean, I did this just once and I put the result inside the HTML file. Epiphany does the same: it has hardcoded the image inside the html. Is that a bad idea? -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Change back/forward navigation shortcut to Alt modifier SL #3536
Signed-off-by: Manuel Quiñones ma...@laptop.org Signed-off-by: Manuel Kaufmann humi...@gmail.com --- webactivity.py | 14 -- webtoolbar.py | 2 ++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/webactivity.py b/webactivity.py index 24f3b44..e911337 100644 --- a/webactivity.py +++ b/webactivity.py @@ -449,12 +449,6 @@ class WebActivity(activity.Activity): elif key_name == '0': _logger.debug('keyboard: Actual size') browser.set_zoom_level(ZOOM_ORIGINAL) -elif key_name == 'Left': -_logger.debug('keyboard: Go back') -browser.go_back() -elif key_name == 'Right': -_logger.debug('keyboard: Go forward') -browser.go_forward() elif key_name == 'r': _logger.debug('keyboard: Reload') browser.reload() @@ -465,6 +459,14 @@ class WebActivity(activity.Activity): return True +elif event.get_state() Gdk.ModifierType.MOD1_MASK: +if key_name == 'Left': +_logger.debug('keyboard: Go back') +browser.go_back() +elif key_name == 'Right': +_logger.debug('keyboard: Go forward') +browser.go_forward() + elif key_name in ('KP_Up', 'KP_Down', 'KP_Left', 'KP_Right'): scrolled_window = browser.get_parent() diff --git a/webtoolbar.py b/webtoolbar.py index 28bc015..5193d89 100644 --- a/webtoolbar.py +++ b/webtoolbar.py @@ -269,6 +269,7 @@ class PrimaryToolbar(ToolbarBase): self._back = ToolButton('go-previous-paired') self._back.set_tooltip(_('Back')) +self._back.props.accelerator = 'AltLeft' self._back.props.sensitive = False self._back.connect('clicked', self._go_back_cb) toolbar.insert(self._back, -1) @@ -283,6 +284,7 @@ class PrimaryToolbar(ToolbarBase): self._forward = ToolButton('go-next-paired') self._forward.set_tooltip(_('Forward')) +self._forward.props.accelerator = 'AltRight' self._forward.props.sensitive = False self._forward.connect('clicked', self._go_forward_cb) toolbar.insert(self._forward, -1) -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Error page SL #3500
On Tue, Sep 18, 2012 at 10:58 PM, James Cameron qu...@laptop.org wrote: Neat. What method did you use to convert the image? Python... It is my best friend :) import base64 base64.b64encode(open('browse-logo.png', 'r').read()) See you, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Error page SL #3500
On Wed, Sep 19, 2012 at 8:38 AM, Manuel Kaufmann humi...@gmail.com wrote: Added an Error page with Sugar style that informs the users about the the page could not be loaded for any reason. I had to add --no-validate to the git send-email command because this patch has a line longer than 998 chars and it's not valid due a SMTP limitation. I'm not sure if this patch will apply properly, if not, please download it from SugarLabs' Trac: * http://bugs.sugarlabs.org/attachment/ticket/3500/0001-Error-page-SL-3500.2.patch Thanks, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
On Mon, Sep 17, 2012 at 7:40 PM, James Cameron qu...@laptop.org wrote: I've no other comments about the patch. Thanks for your comments. I'm about to send a new patch. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH sugar-toolkit-gtk3 2/2] Signal to check free available space
Datastore will emit the 'datastore.error' signal when the free available space will be under SPACE_THRESHOLD. This will allow activities to handle this situation properly. For example, Browse could cancel a download in progress. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- src/sugar3/datastore/datastore.py | 18 ++ 1 file changed, 18 insertions(+) diff --git a/src/sugar3/datastore/datastore.py b/src/sugar3/datastore/datastore.py index 33100e8..6a39b4e 100644 --- a/src/sugar3/datastore/datastore.py +++ b/src/sugar3/datastore/datastore.py @@ -39,6 +39,11 @@ DS_DBUS_SERVICE = 'org.laptop.sugar.DataStore' DS_DBUS_INTERFACE = 'org.laptop.sugar.DataStore' DS_DBUS_PATH = '/org/laptop/sugar/DataStore' +SPACE_THRESHOLD = 52428800 # 50Mb + +# Error codes +LOW_SPACE = 1 + _data_store = None @@ -57,14 +62,25 @@ def _get_data_store(): return _data_store +def free_available_space(path='/'): +s = os.statvfs(path) +return s.f_bavail * s.f_frsize + + def __datastore_created_cb(object_id): metadata = _get_data_store().get_properties(object_id, byte_arrays=True) updated.send(None, object_id=object_id, metadata=metadata) +if free_available_space() SPACE_THRESHOLD: +error.send(None, errno=LOW_SPACE) def __datastore_updated_cb(object_id): metadata = _get_data_store().get_properties(object_id, byte_arrays=True) updated.send(None, object_id=object_id, metadata=metadata) +if free_available_space() SPACE_THRESHOLD: +logging.warning('Free space below SPACE_THRESHOLD: %s Kb', +SPACE_THRESHOLD) +error.send(None, errno=LOW_SPACE) def __datastore_deleted_cb(object_id): @@ -74,6 +90,8 @@ created = dispatch.Signal() deleted = dispatch.Signal() updated = dispatch.Signal() +error = dispatch.Signal() + _get_data_store() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse 1/2] Cancel a download if space is very tight SL #394
It checks for enough space (using Activity.enough_space) before downloading the file. If not, Browse will cancel the download process before starting it and an Alert will be shown to the user to inform this situation. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- downloadmanager.py | 63 +- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/downloadmanager.py b/downloadmanager.py index 9950c16..5ad1a6f 100644 --- a/downloadmanager.py +++ b/downloadmanager.py @@ -74,16 +74,18 @@ class Download(object): self._stop_alert = None # figure out download URI -temp_path = os.path.join(activity.get_activity_root(), 'instance') -if not os.path.exists(temp_path): -os.makedirs(temp_path) +self.temp_path = os.path.join(activity.get_activity_root(), 'instance') +if not os.path.exists(self.temp_path): +os.makedirs(self.temp_path) -fd, self._dest_path = tempfile.mkstemp(dir=temp_path, +fd, self._dest_path = tempfile.mkstemp(dir=self.temp_path, suffix=download.get_suggested_filename(), prefix='tmp') os.close(fd) logging.debug('Download destination path: %s' % self._dest_path) +# We have to start the download to get 'total-size' +# property. It not, 0 is returned self._download.set_destination_uri('file://' + self._dest_path) self._download.start() @@ -95,17 +97,48 @@ class Download(object): def __state_change_cb(self, download, gparamspec): state = self._download.get_status() if state == WebKit.DownloadStatus.STARTED: -self._create_journal_object() -self._object_id = self.dl_jobject.object_id - -alert = TimeoutAlert(9) -alert.props.title = _('Download started') -alert.props.msg = _('%s' % self._download.get_suggested_filename()) -self._activity.add_alert(alert) -alert.connect('response', self.__start_response_cb) -alert.show() -global _active_downloads -_active_downloads.append(self) +# Check free space and cancel the download if there is not enough. +total_size = self._download.get_total_size() +logging.debug('Total size of the file: %s', total_size) +enough_space = self._activity.enough_space( +total_size, path=self.temp_path) +if not enough_space: +logging.debug('Download canceled because of Disk Space') +self.cancel() + +self._canceled_alert = Alert() +self._canceled_alert.props.title = _('Not enough space ' + 'to download') + +total_size_mb = total_size / 1024.0 ** 2 +free_space_mb = datastore.free_available_space( +path=self.temp_path) - datastore.SPACE_THRESHOLD \ +/ 1024.0 ** 2 +filename = self._download.get_suggested_filename() +self._canceled_alert.props.msg = \ +_('Download %s requires %.2f MB of free space, only ' + '%.2f MB is available' % (filename, total_size_mb, + free_space_mb)) +ok_icon = Icon(icon_name='dialog-ok') +self._canceled_alert.add_button(Gtk.ResponseType.OK, +_('Ok'), ok_icon) +ok_icon.show() +self._canceled_alert.connect('response', + self.__stop_response_cb) +self._activity.add_alert(self._canceled_alert) +else: +self._create_journal_object() +self._object_id = self.dl_jobject.object_id + +alert = TimeoutAlert(9) +alert.props.title = _('Download started') +alert.props.msg = _('%s' % +self._download.get_suggested_filename()) +self._activity.add_alert(alert) +alert.connect('response', self.__start_response_cb) +alert.show() +global _active_downloads +_active_downloads.append(self) elif state == WebKit.DownloadStatus.FINISHED: self._stop_alert = Alert() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse 2/2] Handle datastore.error signal
Stop the downloading process when this signal is received with the datastore.LOW_SPACE error code. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- downloadmanager.py | 8 1 file changed, 8 insertions(+) diff --git a/downloadmanager.py b/downloadmanager.py index 5ad1a6f..bd8386d 100644 --- a/downloadmanager.py +++ b/downloadmanager.py @@ -65,6 +65,9 @@ class Download(object): self._download.connect('notify::status', self.__state_change_cb) self._download.connect('error', self.__error_cb) +# connect the error datastore signal to manage LOW_SPACE +datastore.error.connect(self.__datastore_error_cb) + self.datastore_deleted_handler = None self.dl_jobject = None @@ -89,6 +92,11 @@ class Download(object): self._download.set_destination_uri('file://' + self._dest_path) self._download.start() +def __datastore_error_cb(self, sender, **kwargs): +logging.debug('__datastore_error_cb') +if kwargs.get('errno', -1) == datastore.LOW_SPACE: +self._download.cancel() + def __progress_change_cb(self, download, something): progress = self._download.get_progress() self.dl_jobject.metadata['progress'] = str(int(progress * 100)) -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] Not enough space adventure
Hello people, I'd like to comment what I've been doing these days regarding Downloading a file with Browse without having enough space to keep it. * http://bugs.sugarlabs.org/ticket/394 We where discussing about this last week[1] and we found the root issue of this problem: Sugar is not handling ENOSPC error. This could cause some problems at boot time when the XO is restarted, but as we discussed[2], Linux has made some improvement on this side and it seems that it recovers without problem (we need more testing here, I think). So, there are different problems to manage here: 1. What are we going to do when ENOSPC is reached? I'm not sure about this point and I think we have to discuss what to do here and how implement this. There is an important ticket for this * http://bugs.sugarlabs.org/ticket/2317 2. How are we going to avoid ENOSCP? Well, this is the topic where I focused my work. Trying to avoid reaching ENOSCP. A good place to do some work is Browse (but this work include some extra modifications in other components as well) because it's the main activity that generate big files by downloading them from the internet. So, Gonzalo and I were discussing about a good implementation regarding this and we found, at least, an alternative. It consists in: - remove the annoying check of free space (sugar3.datastore.datastore.SPACE_THRESHOLD = 50Mb at the moment) from the Journal Activity that shows all the time the ModalAlert saying Your Journal is full. Please remove some entries every time and it doesn't allow you to do another things. - create a signal inside sugar-toolkit-gtk3 datastore that is emitted when free space is behind sugar3.datastore.datastore.SPACE_THRESHOLD. This check is done every time a model is updated or created by the datastore. - this signal can be connected from every activity that wants to handle this situation. For example in Browse we are cancelling the download in progress when we get that signal - the same signal is captured in Journal Activity to show the ModalAlert saying Your Journal is full that was shown before - create a helper function in sugar-toolkit-gtk3 activity Activity class to check if there is enough space to keep a new file (Browse uses this before downloading a file from the internet). I decided to put this helper inside Activity class because I think it could be useful for many activities. - compare (in Browse) the Content-Length with the free space available + SPACE_THRESHOLD (this is done by the helper function) and decide if the download is going to take place or not These are all the patches involved on this change: * http://patchwork.sugarlabs.org/patch/1749/ * http://patchwork.sugarlabs.org/patch/1750/ * http://patchwork.sugarlabs.org/patch/1751/ * http://patchwork.sugarlabs.org/patch/1752/ * http://patchwork.sugarlabs.org/patch/1753/ Thanks, comments and suggestions are welcomed. [1] http://lists.sugarlabs.org/archive/sugar-devel/2012-September/039516.html [2] http://lists.sugarlabs.org/archive/sugar-devel/2012-September/039576.html PD: Gonzalo, please, add whatever thing that I missed. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Error page SL #3500
Added an Error page with Sugar style that informs the users about they are not connected to the internet when the page can not reached for any reason. This patch contains a HTML template (error_page.tmpl) that is used to generate the error page with the correct language. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- browser.py | 31 + data/activity-web.png| Bin 0 - 6064 bytes data/browse-view-refresh.png | Bin 0 - 481 bytes data/error_page.tmpl | 53 +++ 4 files changed, 84 insertions(+) create mode 100644 data/activity-web.png create mode 100644 data/browse-view-refresh.png create mode 100644 data/error_page.tmpl diff --git a/browser.py b/browser.py index de546f2..c9bcc1c 100644 --- a/browser.py +++ b/browser.py @@ -58,6 +58,9 @@ _NON_SEARCH_REGEX = re.compile(''' ^file:.*$) ''', re.VERBOSE) +DEFAULT_ERROR_PAGE = os.path.join(activity.get_bundle_path(), + 'data/error_page.html') + class CommandListener(object): def __init__(self, window): @@ -462,6 +465,7 @@ class Browser(WebKit.WebView): self.__mime_type_policy_cb) self.connect('new-window-policy-decision-requested', self.__new_window_policy_cb) +self.connect('load-error', self.__load_error_cb) try: self.connect('run-file-chooser', self.__run_file_chooser) @@ -603,6 +607,33 @@ class Browser(WebKit.WebView): downloadmanager.add_download(download, browser) return True +def __create_error_page(self, url): +Create the error page in the correct language + +data = { +'page_title': _('You are not connected to the internet'), +'title': _('You are not connected to the internet'), +'message': _('You will need to connect using the ' + 'Neighborhoodbr /view in order ' + 'to continue browsing'), +'btn_value': _('Try again'), +'url': url, +} +filepath = os.path.join(activity.get_bundle_path(), +'data/error_page.tmpl') +html = open(filepath, 'r').read() % data + +f = open(DEFAULT_ERROR_PAGE, 'w') +f.write(html) +f.close() + +def __load_error_cb(self, web_view, web_frame, uri, web_error): +Show Sugar's error page + +self.__create_error_page(uri) +self.load_uri('file://' + DEFAULT_ERROR_PAGE) +return True + class PopupDialog(Gtk.Window): def __init__(self): diff --git a/data/activity-web.png b/data/activity-web.png new file mode 100644 index ..d27964350a22e13fef454fb1923a722b5d64a921 GIT binary patch literal 6064 zcmXw71yoe;)22Zhln{_cQX1*br9)t8kZxEIess5jbVw-OCE(Jrgn-1--7DQK^BY ze0$E_d+zT0O38wo@XLPQ(X}cn*tjN2?-CRBQABL!U1!4B$H!mGA+$p?S!FK41YK ze=MtL;Q57{l7R;j5^LP^h0MNGPXqk;+EX6vspD$n1_eAM)LOd=CpTl^suyWv*vV# z*nT?_qd-C;dk2z}{_tP+VUCfi@$7VPXEPFv9QXZPUw6C(Q~;x-zuU{n(rUooLD=PN zN?EsX(kvimYPOUEq7AlL%^4mD7~}9e5G9-%HdDb{0(zodl5F22W~usvM6Ue{IM) zVfO^vxYXR~?N^x=7(ENbekSm^ByxF58G!A{halMsBG9jX49tl3u*nwP?;9eI3x zi=?U$K)oob7()G;fx2@^1scFzW((E{#=xzxZpoZlprtOgGs=;x6PWtcD$$cQ} zVzHAy-+xvs!z#A_7m^GP4I(K;TY9lKiZYJkA6Z0x8EK))RLZsBL?O?uHi#qe#3O~ z_G|7Ob=466iT)bi3W^Y=EYG0F{lQRK#hjG_Rd@*w3We{@CJ(;4+c%$8LgDpW(2? z;#|X9Gg-3ZGFjJjoOLXhW_r(SA{=jW)@@+%*_9US)JNWBe;-bQfW$Nf1%ik#5 zHVd%NlwPAsPgsG6Uv*eB$YgScZnDEpat)njR`m?WcELzDp9gA`#a$fWnxUfY z5rAJxu8FiiIP;y!m25PCyI~!P7_cqds{*Bh+juOOtyq){{jO0EM4N;pqYjoQEWY z=ulpbj|}Rrkwsegw`vhAal2;QXKmLl)${10qz}t0DD?j$ks+!M-}4X;okgFqCN-3 z@X))7u6LO}qc}6PF)%QSd=wo5fncGbI4w4PX=xE5B_;kz%+AGC($!}vSRA%q|}@ zZ?DRRdr$P=EcfST@cXuG=~a|3)Touw}j`8Z5I?4hD*^(FJSLT3Xe90%EYdA%nc zanvy}QKKb9GIw(NoSRGC($a#35mx8ho8C2s2ir-|4I7U62B_hK1VuUUSVtvem-(y zLR*ZQ0IA#ju@?3pRn+5gU`T!V$^|W$$4MDeQUjG)nt*gwPij$JXBTdW5k#y$mYY{ z^x~i}Qa66p%|G(8tE5Yv`OwPBNfWq+TESUvMv+mF3k2C?Ag0gZ`+~izhZtm!Q zO=tY-vDw*OLD+EYpcDZV_d{UJdgUZb7%b~Ku;vtr1OLgVrH#l^+i1_mH|``y@= zbx-%(lK$r-f*W4vXJ_OT6xuB_`J|uTpl-wtu42srDpjG5;Y;J;-5d0)6zwWas3 zxZMXq48t*HfW%wHQBC;MFmI@8#v#d1Jpeo*I1;43SfF4w=FL4P7CgJcOogpX zbl1nL+oziY`P;8ZNg;bvdpHH=+)9~4C3PA`CjQf1Z_a{mK=atNlq!Xd=FUp~m!k zXlSEx*0i9d#aEXJV2GMocB)pRuv=5iVXR@U}!ucEN9F#2f!@DMRmHO(+8k(aQy z=V0o0C{SNtFXybdj{a!Xd7eS|Qoc4SjNsET7d!iAPXx{u0#W5Vaf_L=6@OiJxod zW@BS(_?McRDzB#YWlm#!VPPl?)6p*$cq34^brfss_WFB3$%w@g{3bk1)OeenW zQUrJ2Xl2K1JibU`})hnM949wqw+$f%Ef20+NzuqcAKqZdy5n-{W#PzyGorD zOJLL5rNe7u9KK|sER_`Xnrv_tQ0R{2M11^#!x9~F$=m1d8qBmJ^rN`aL63dNC zAauxUY7Fm@JQ?EBu_M=qoW%`-9msZIYjPc?R93Pwauwr~uv}nKUBgFmfxzlP# zz_O#FqN2Tv3u$85FYbCZTmLw45=go{bTZ^BI4umF)%SxtCu?hM7PKCY!vkMV1#| z7}r_nN2Jluxom2TyOENRkhuT-^O{MA96JK)d0WtM6mU^q@-_BU$$6rDh9CX zVt2BzWcagLKtTH$1ipU0k*`(#(K6u2^=%VCjw34PDJ^a`T=3tVm{jQ#=jaGPIeNV zhP%piN`4QjHO|8u8w8$+0NvQ$?*vY^j+@Hrq*~j8$Yl14!z?|bLx#I5h+XXJ|hz zN;f4|YXLNG4lw$w7O);cHur0+PSH;dU;|;VgNVA0G3C~t;{XkC+o1biwTu{Kc^LV zjA87n?onoFGPf
Re: [Sugar-devel] [PATCH Browse] Error page SL #3500
On Tue, Sep 18, 2012 at 1:55 PM, Manuel Kaufmann humi...@gmail.com wrote: This patch contains a HTML template (error_page.tmpl) that is used to generate the error page with the correct language. Please, comments and suggestions are welcomed here. I didn't find an existent way (inside Sugar) to translate html content, so I decide to make it by myself. I created a file called error_page.tmpl that contains the html structure of the page with some placeholders to put the translated strings (those placeholders are substituted with the % operator) and a new html file is create: error_page.html with the correct strings and url to try again. Then, this file is used to tell WekKit to load that file as an uri: self.load_uri('file://' + DEFAULT_ERROR_PAGE) That file is generated every time that the web page can't be reached for any reason. See you, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Error page SL #3500
On Tue, Sep 18, 2012 at 2:54 PM, Daniel Narvaez dwnarv...@gmail.com wrote: Oh cool, load_alternate_string definitely looks like the way to go. (it doesn't break history etc). Yeah! http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitwebview.html#WebKitWebView--load-status Thanks, I will patch my patch :) , I will send it again :) -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Error page SL #3500
On Tue, Sep 18, 2012 at 2:21 PM, Daniel Narvaez dwnarv...@gmail.com wrote: Perhaps you could use the data protocol to avoid the temporary file http://www.ietf.org/rfc/rfc2397.txt I used this to put the images inside the html-string. img id=browse-logo src=data:image/png;base64,iVBO (...) /img Thanks! -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
It checks if there will be more than MIN_DISKFREE_AFTER_DOWNLOAD (20Mb) after downloading the file. If not, Browse will cancel the download process before starting it and an Alert will be shown to the user to inform this situation. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- downloadmanager.py | 29 +++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/downloadmanager.py b/downloadmanager.py index 9950c16..b3d4feb 100644 --- a/downloadmanager.py +++ b/downloadmanager.py @@ -35,6 +35,8 @@ DS_DBUS_SERVICE = 'org.laptop.sugar.DataStore' DS_DBUS_INTERFACE = 'org.laptop.sugar.DataStore' DS_DBUS_PATH = '/org/laptop/sugar/DataStore' +MIN_DISKFREE_AFTER_DOWNLOAD = 20 * 1024 * 1024 + _active_downloads = [] _dest_to_window = {} @@ -55,6 +57,11 @@ def remove_all_downloads(): download.cleanup() +def free_space(path): +s = os.statvfs(path) +return s.f_bavail * s.f_frsize + + class Download(object): def __init__(self, download, browser): self._download = download @@ -84,8 +91,26 @@ class Download(object): os.close(fd) logging.debug('Download destination path: %s' % self._dest_path) -self._download.set_destination_uri('file://' + self._dest_path) -self._download.start() +# Check free space and if the downloaded file plus an extra +# space will fit on the disk. If not, cancel the download. +total_size = self._download.get_total_size() +logging.debug('Total size of the file: %s', total_size) +if free_space('/') - total_size MIN_DISKFREE_AFTER_DOWNLOAD: +logging.debug('Download canceled because of Disk Space') +self._canceled_alert = Alert() +self._canceled_alert.props.title = _('Download canceled ' + 'because of Disk Space') +self._canceled_alert.props.msg = \ +_('%s' % self._download.get_suggested_filename()) +ok_icon = Icon(icon_name='dialog-ok') +self._canceled_alert.add_button(Gtk.ResponseType.OK, + _('Ok'), ok_icon) +ok_icon.show() +self._canceled_alert.connect('response', self.__stop_response_cb) +self._activity.add_alert(self._canceled_alert) +else: +self._download.set_destination_uri('file://' + self._dest_path) +self._download.start() def __progress_change_cb(self, download, something): progress = self._download.get_progress() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH sugar 1/2] ModalAlert ported to Gtk3
Gtk.VBox.pack_start() and Gtk.Alignment.new() fixed to run over Gtk3 Signed-off-by: Manuel Kaufmann humi...@gmail.com --- src/jarabe/journal/modalalert.py | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/jarabe/journal/modalalert.py b/src/jarabe/journal/modalalert.py index 36f076e..186fd1a 100644 --- a/src/jarabe/journal/modalalert.py +++ b/src/jarabe/journal/modalalert.py @@ -56,25 +56,27 @@ class ModalAlert(Gtk.Window): icon = Icon(icon_name='activity-journal', pixel_size=style.XLARGE_ICON_SIZE, xo_color=color) -self._vbox.pack_start(icon, False) +self._vbox.pack_start(icon, expand=False, fill=False, padding=0) icon.show() self._title = Gtk.Label() self._title.modify_fg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color()) self._title.set_markup('b%s/b' % _('Your Journal is full')) -self._vbox.pack_start(self._title, False) +self._vbox.pack_start(self._title, expand=False, fill=False, padding=0) self._title.show() self._message = Gtk.Label(label=_('Please delete some old Journal' ' entries to make space for new ones.')) self._message.modify_fg(Gtk.StateType.NORMAL, style.COLOR_WHITE.get_gdk_color()) -self._vbox.pack_start(self._message, False) +self._vbox.pack_start(self._message, expand=False, + fill=False, padding=0) self._message.show() -alignment = Gtk.Alignment.new(xalign=0.5, yalign=0.5) -self._vbox.pack_start(alignment, False, True, 0) +alignment = Gtk.Alignment.new(xalign=0.5, yalign=0.5, + xscale=0.0, yscale=0.0) +self._vbox.pack_start(alignment, expand=False, fill=True, padding=0) alignment.show() self._show_journal = Gtk.Button() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] Adventures in the land of ENOSPC
On Thu, Sep 13, 2012 at 4:47 PM, Martin Langhoff martin.langh...@gmail.com wrote: Manuel Kaufmann has been looking at SL#394, and looking at the bug report, it struck me that it was reported backwards. I would have written: I filled up my disk and it knocked the system out, Sugar would not start again, etc. Oh, btw, it was with Browse. There is a ticket already reported (that I found today) mentioning this situation: * http://dev.laptop.org/ticket/10481 In fact, it seems that you passed over it some months ago. We were discussing about it with Gonzalo today in the morning. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
On Tue, Sep 11, 2012 at 10:27 PM, Martin Langhoff martin.langh...@gmail.com wrote: - During the webkit download -- most probable stage where you'll hit it. How does Webkit behave? Does Browse need to do anything? I'm attaching an example that downloads a file with WebKit. I tried it setting up a tmpfs with 1Mb as you suggested and aftert that, I ran this script. WebKit tells us about the insufficient space on the disk by raising the error signal. I catched it and I printed the arguments of the signal: 'Error downloading URI code %s, detail %s: %s' % (err_code, err_detail, reason) === Error downloading URI code 0, detail 1: Error writing to file: No space left on device err_detail: http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitdownload.html#WebKitDownloadError * WEBKIT_DOWNLOAD_ERROR_DESTINATION - The download failed due to disk write failure I will keep taking a look at the other possibilities. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ download_file_with_webkit.py Description: Binary data ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
On Tue, Sep 11, 2012 at 10:27 PM, Martin Langhoff martin.langh...@gmail.com wrote: - During datastore.write() -- I truly believe that the datastore.write() call doesn't literally make a copy of the file -- should just create/update the hardlink and associated metadata (including progress bar). It is not very likely that we'll run out of space during this call, but it should be handled, I believe. OK. I was taking a look at the datastore source code and I understood that the file is copied, using the traditional way and when the copy finishes the source file is unlinked. Here are the source files that I took a look and how I found this: sugar-toolkit-gtk3/src/sugar3/datastore/datastore.py L340 (def write) --- L316 (def _update_ds_entry) --- L45 (def _get_data_store) sugar-datastore/src/carquinyol/datastore.py L242 (def update) src/carquinyol/filestore.py L34 (def store) --- L215 (def start) --- L181 (def _copy_block) Please, let me know if I am wrong. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
On Wed, Sep 12, 2012 at 9:21 AM, Martin Langhoff martin.langh...@gmail.com wrote: That's very good handling on webkit's side. And does it remove the file? IOWs, when you get the signal, what do you see in the tmpfs? Is there a file filling it, or has the file been removed? Oh, sorry. I forgot to mention this. The file is still there with the size that webkit could get (in my case 904kb). Webkit didn't remove it. -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
On Mon, Sep 10, 2012 at 9:49 PM, Martin Langhoff martin.langh...@gmail.com wrote: Here, get the content-length... and compare with the free bytes (plus some padding, say, 15%). Maybe we still want to preserve a minimum disk space. For example: don't let a download put you below 50MB or 10MB free -- in that case do the multiplication in a constant definition. MIN_DISKFREE_AFTER_DOWNLOAD = 50 * 1024 * 1024 If we are going to use this approach, I have to change the logic about where I should check this. Now, I'm checking this every time that the progress[1] changes but I think we should use total-size[2] to get the Content-Length in Download.__init__() and decide there what to do. I mean, decide whether cancel or not before starting the download. What do you say? [1] http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitdownload.html#WebKitDownload--progress [2] http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitdownload.html#WebKitDownload--total-size -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
It checks if there will be more than MIN_DISKFREE_AFTER_DOWNLOAD (50Mb) after downloading the file. If not, Browse will cancel the download process before starting it and an Alert will be shown to the user to inform this situation. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- downloadmanager.py | 28 ++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/downloadmanager.py b/downloadmanager.py index 9950c16..0240941 100644 --- a/downloadmanager.py +++ b/downloadmanager.py @@ -35,6 +35,8 @@ DS_DBUS_SERVICE = 'org.laptop.sugar.DataStore' DS_DBUS_INTERFACE = 'org.laptop.sugar.DataStore' DS_DBUS_PATH = '/org/laptop/sugar/DataStore' +MIN_DISKFREE_AFTER_DOWNLOAD = 50 * 1024 * 1024 + _active_downloads = [] _dest_to_window = {} @@ -55,6 +57,11 @@ def remove_all_downloads(): download.cleanup() +def free_space(path): +s = os.statvfs(path) +return s.f_bavail * s.f_frsize + + class Download(object): def __init__(self, download, browser): self._download = download @@ -84,8 +91,25 @@ class Download(object): os.close(fd) logging.debug('Download destination path: %s' % self._dest_path) -self._download.set_destination_uri('file://' + self._dest_path) -self._download.start() +# Check free space and if the downloaded file plus an extra +# space will fit on the disk. If not, cancel the download. +total_size = self._download.get_total_size() +logging.debug('Total size of the file: %s', total_size) +if free_space('/') - total_size MIN_DISKFREE_AFTER_DOWNLOAD: +logging.debug('Download canceled because of Disk Space') +self._canceled_alert = Alert() +self._canceled_alert.props.title = _('Download canceled ' + 'because of Disk Space') +self._canceled_alert.props.msg = \ +_('%s' % self._download.get_suggested_filename()) +ok_icon = Icon(icon_name='dialog-ok') +self._canceled_alert.add_button(Gtk.ResponseType.OK, + _('Ok'), ok_icon) +ok_icon.show() +self._canceled_alert.connect('response', self.__stop_response_cb) +self._activity.add_alert(self._canceled_alert) +else: +self._download.set_destination_uri('file://' + self._dest_path) def __progress_change_cb(self, download, something): progress = self._download.get_progress() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
On Tue, Sep 11, 2012 at 8:03 PM, Gonzalo Odiard gonz...@laptop.org wrote: Can you try almost fill the xo and copy a big file with the journal from a pendrive? I remember a big message in the screen when this happen, and will point you to the code. Yes, I've already try that and I commented what I get here: * http://bugs.sugarlabs.org/ticket/394#comment:7 I didn't find an exception raised by Sugar when this happens. The check is done[1] when a new Model is created[2] or updated[3] inside the Journal, and if there are less than 50Mb a ModelAlert is shown but no exception is raised. Maybe we can write the portion of code here to raise that exception before show the ModelAlert and if it's not managed we can call the ModelAlert. [1] sugar/src/jarabe/journal/journalactivity.py L336 [2] sugar/src/jarabe/journal/journalactivity.py L274 [3] sugar/src/jarabe/journal/journalactivity.py L265 The browser is downloading the file in a temporary place and later moving to the journal or is creating a object in the journal while downloading? The file is downloaded in a temporary directory and then copied to the Journal: temp_path = os.path.join(activity.get_activity_root(), 'instance') fd, self._dest_path = tempfile.mkstemp(dir=temp_path, suffix=download.get_suggested_filename(), prefix='tmp') That is something like (I guess): ~/.sugar/default/org.laptop.WebActivity/instance When the download finishes: (...) self.dl_jobject = datastore.create() (...) datastore.write(self.dl_jobject, transfer_ownership=True, reply_handler=self.__internal_save_cb, error_handler=self.__internal_error_cb, timeout=360) (...) Is important to know if the control in the journal will work or not. but, we are updating a Journal entry every time that the progress of the download changes to show the progress bar in the Journal: browse/downloadmanager.py L90 def __progress_change_cb(self, download, something): progress = self._download.get_progress() self.dl_jobject.metadata['progress'] = str(int(progress * 100)) datastore.write(self.dl_jobject) so, we are updating a model inside the datastore... If we had the ENOSPC exception we could manage it there. I insist this goes in a different ticket and a different patch. See you, -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
Re: [Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
On Tue, Sep 11, 2012 at 8:50 PM, Martin Langhoff martin.langh...@gmail.com wrote: mkdir /tmp/foo sudo mount -t tmpfs -o size=1M none /tmp/foo Now write there to a file in /tmp/foo to see what happens, exactly. This is what I got: [olpc@xo-07-30-50 ~]$ mkdir /tmp/foo [olpc@xo-07-30-50 ~]$ sudo mount -t tmpfs -o size=1M none /tmp/foo [olpc@xo-07-30-50 ~]$ python Python 2.7.3 (default, Apr 30 2012, 23:07:00) [GCC 4.7.0 20120416 (Red Hat 4.7.0-2)] on linux2 Type help, copyright, credits or license for more information. f = open('/tmp/foo/cl.txt', 'w') f.write('w' * 200 ** 2) (...) f.write('w' * 2000) Traceback (most recent call last): File stdin, line 1, in module IOError: [Errno 28] No space left on device So, we should handle this exception inside the Journal Activity, when an object is created or updated. How is the correct way that I have to follow to inform about this exception to the other activities? -- Kaufmann Manuel Blog: http://humitos.wordpress.com/ Porfolio: http://fotos.mkaufmann.com.ar/ PyAr: http://www.python.com.ar/ ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Busy indication SL #851
Show WATCH Cursor when the page is loading and LEFT_PTR when the load finishes. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- browser.py | 4 1 file changed, 4 insertions(+) diff --git a/browser.py b/browser.py index 7379d2b..90378cb 100644 --- a/browser.py +++ b/browser.py @@ -404,14 +404,18 @@ class TabLabel(Gtk.HBox): def __load_status_changed_cb(self, widget, param): status = widget.get_load_status() if status == WebKit.LoadStatus.FAILED: +self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.LEFT_PTR)) self._label.set_text(self._title) elif WebKit.LoadStatus.PROVISIONAL = status \ WebKit.LoadStatus.FINISHED: +self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH)) self._label.set_text(_('Loading...')) elif status == WebKit.LoadStatus.FINISHED: if widget.props.title == None: self._label.set_text(_('Untitled')) self._title = _('Untitled') +self.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.LEFT_PTR)) + class Browser(WebKit.WebView): -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Don't call .start after .set_destination_uri SL #3878
Do not call WebKitDownload.start after .set_destination_uri because it is no needed. The download will start automatically after .set_destination_uri. http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitwebview.html#WebKitWebView-download-requested Signed-off-by: Manuel Kaufmann humi...@gmail.com --- downloadmanager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/downloadmanager.py b/downloadmanager.py index 9950c16..ab9fec2 100644 --- a/downloadmanager.py +++ b/downloadmanager.py @@ -85,7 +85,6 @@ class Download(object): logging.debug('Download destination path: %s' % self._dest_path) self._download.set_destination_uri('file://' + self._dest_path) -self._download.start() def __progress_change_cb(self, download, something): progress = self._download.get_progress() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH Browse] Cancel a download if space is very tight SL #394
If there are less than 50Mb free on the Hard Disk the downloading process is canceled and this is informed to the user via an Alert. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- downloadmanager.py | 29 +++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/downloadmanager.py b/downloadmanager.py index ab9fec2..749eb38 100644 --- a/downloadmanager.py +++ b/downloadmanager.py @@ -55,6 +55,13 @@ def remove_all_downloads(): download.cleanup() +# http://stackoverflow.com/questions/787776/find-free-disk-space-in-python-on-os-x +def free_space(path): +global k +s = os.statvfs(path) +return (s.f_bavail * s.f_frsize) / 1024 / 1024 + + class Download(object): def __init__(self, download, browser): self._download = download @@ -88,8 +95,26 @@ class Download(object): def __progress_change_cb(self, download, something): progress = self._download.get_progress() -self.dl_jobject.metadata['progress'] = str(int(progress * 100)) -datastore.write(self.dl_jobject) + +# Check free space and if there is less than 50Mb, then cancel +# the download +if free_space('/') 50: +self.cancel() + +self._canceled_alert = Alert() +self._canceled_alert.props.title = _('Download canceled ' + 'because of Disk Space') +self._canceled_alert.props.msg = \ +_('%s' % self._download.get_suggested_filename()) +ok_icon = Icon(icon_name='dialog-ok') +self._canceled_alert.add_button(Gtk.ResponseType.OK, + _('Ok'), ok_icon) +ok_icon.show() +self._canceled_alert.connect('response', self.__stop_response_cb) +self._activity.add_alert(self._canceled_alert) +else: +self.dl_jobject.metadata['progress'] = str(int(progress * 100)) +datastore.write(self.dl_jobject) def __state_change_cb(self, download, gparamspec): state = self._download.get_status() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel
[Sugar-devel] [PATCH [v2] Browse] Cancel a download if space is very tight SL #394
If there are less than 50Mb free on the Hard Disk the downloading process is canceled and this is informed to the user via an Alert. Signed-off-by: Manuel Kaufmann humi...@gmail.com --- downloadmanager.py | 28 ++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/downloadmanager.py b/downloadmanager.py index ab9fec2..b63f0fe 100644 --- a/downloadmanager.py +++ b/downloadmanager.py @@ -55,6 +55,12 @@ def remove_all_downloads(): download.cleanup() +# http://stackoverflow.com/questions/787776/find-free-disk-space-in-python-on-os-x +def free_space(path): +s = os.statvfs(path) +return (s.f_bavail * s.f_frsize) / 1024 / 1024 + + class Download(object): def __init__(self, download, browser): self._download = download @@ -88,8 +94,26 @@ class Download(object): def __progress_change_cb(self, download, something): progress = self._download.get_progress() -self.dl_jobject.metadata['progress'] = str(int(progress * 100)) -datastore.write(self.dl_jobject) + +# Check free space and if there is less than 50Mb, then cancel +# the download +if free_space('/') 50: +self.cancel() + +self._canceled_alert = Alert() +self._canceled_alert.props.title = _('Download canceled ' + 'because of Disk Space') +self._canceled_alert.props.msg = \ +_('%s' % self._download.get_suggested_filename()) +ok_icon = Icon(icon_name='dialog-ok') +self._canceled_alert.add_button(Gtk.ResponseType.OK, + _('Ok'), ok_icon) +ok_icon.show() +self._canceled_alert.connect('response', self.__stop_response_cb) +self._activity.add_alert(self._canceled_alert) +else: +self.dl_jobject.metadata['progress'] = str(int(progress * 100)) +datastore.write(self.dl_jobject) def __state_change_cb(self, download, gparamspec): state = self._download.get_status() -- 1.7.11.4 ___ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel