From f699b1f6dc897a96e4323db65961190e65690eef Mon Sep 17 00:00:00 2001 From: Aleksey Lim Date: Wed, 16 Dec 2009 19:36:06 +0000 Subject: Switch to services --- diff --git a/activity.py b/activity.py index 970397d..c30a8ce 100644 --- a/activity.py +++ b/activity.py @@ -21,8 +21,11 @@ logger = logging.getLogger('cartoon-builder') from sugar.graphics.toolbutton import ToolButton from sugar.graphics.toggletoolbutton import ToggleToolButton from sugar.activity.activity import ActivityToolbox -from port.activity import SharedActivity -from port.temposlider import TempoSlider + +from widgets.temposlider import TempoSlider +from toolkit.activity import SharedActivity +from toolkit.toolbarbox import ToolbarBox +from toolkit.activity_widgets import * import montage import lessons @@ -34,6 +37,7 @@ import theme from messenger import Messenger, SERVICE from utils import * + class CartoonBuilderActivity(SharedActivity): def __init__(self, handle): self.notebook = gtk.Notebook() @@ -49,20 +53,41 @@ class CartoonBuilderActivity(SharedActivity): self.lessons.show() self.notebook.append_page(self.lessons) - toolbox = ActivityToolbox(self) + toolbox = ToolbarBox() toolbox.show() - toolbox.connect('current-toolbar-changed', self._toolbar_changed_cb) - self.set_toolbox(toolbox) - montage_bar = MontageToolbar(self.montage) - montage_bar.show() - toolbox.add_toolbar(_('Montage'), montage_bar) + toolbox.toolbar.insert(ActivityToolbarButton(self), -1) + + separator = gtk.SeparatorToolItem() + separator.set_draw(False) + toolbox.toolbar.insert(separator, -1) + + lessons_button = ToggleToolButton('mamamedia') + lessons_button.connect('toggled', self.__toggled_lessons_button_cb) + lessons_button.set_tooltip(_('Lessons')) + toolbox.toolbar.insert(lessons_button, -1) + + separator = gtk.SeparatorToolItem() + separator.set_draw(False) + toolbox.toolbar.insert(separator, -1) + + self.notebook_toolbar = gtk.Notebook() + self.notebook_toolbar.props.show_border = False + self.notebook_toolbar.props.show_tabs = False + self.notebook_toolbar.append_page(self._create_montage_toolbar()) + self.notebook_toolbar.append_page(self._create_lessons_toolbar()) + self.notebook_toolbar.show() - lessons_bar = LessonsToolbar() - lessons_bar.show() - toolbox.add_toolbar(_('Lessons'), lessons_bar) + notebook_item = gtk.ToolItem() + notebook_item.set_expand(True) + notebook_item.add(self.notebook_toolbar) + notebook_item.show() + toolbox.toolbar.insert(notebook_item, -1) - toolbox.set_current_toolbar(1) + toolbox.toolbar.insert(StopButton(self), -1) + + toolbox.show_all() + self.toolbar_box = toolbox def new_instance(self): logger.debug('new_instance') @@ -84,90 +109,85 @@ class CartoonBuilderActivity(SharedActivity): logger.debug('share_instance') self.messenger = Messenger(tube_conn, initiating, self.montage) - def _toolbar_changed_cb(self, widget, index): - if index == 2: - self.notebook.set_current_page(1) - else: - self.notebook.set_current_page(0) - -class MontageToolbar(gtk.Toolbar): - def __init__(self, montage): - gtk.Toolbar.__init__(self) - self.montage = montage + def _create_montage_toolbar(self): + toolbar = gtk.Toolbar() - self.playButton = ToggleToolButton('media-playback-start') - self.playButton.connect('toggled', self._play_cb) - self.insert(self.playButton, -1) - self.playButton.set_tooltip(_('Play / Pause')) + playButtonImg = gtk.Image() + playButtonImg.show() + playButtonImg.set_from_icon_name('media-playback-start', + gtk.ICON_SIZE_LARGE_TOOLBAR) - # Play button Image - self.playButtonImg = gtk.Image() - self.playButtonImg.show() - self.playButtonImg.set_from_icon_name('media-playback-start', gtk.ICON_SIZE_LARGE_TOOLBAR) + pauseButtonImg = gtk.Image() + pauseButtonImg.show() + pauseButtonImg.set_from_icon_name('media-playback-pause', + gtk.ICON_SIZE_LARGE_TOOLBAR) - # Pause button Image - self.pauseButtonImg = gtk.Image() - self.pauseButtonImg.show() - self.pauseButtonImg.set_from_icon_name('media-playback-pause', gtk.ICON_SIZE_LARGE_TOOLBAR) + playButton = ToggleToolButton('media-playback-start') + playButton.connect('toggled', self.__play_cb, playButtonImg, + pauseButtonImg) + toolbar.insert(playButton, -1) + playButton.set_tooltip(_('Play / Pause')) tempo = TempoSlider(0, 10) - tempo.adjustment.connect("value-changed", self._tempo_cb) + tempo.adjustment.connect("value-changed", self.__tempo_cb) tempo.set_size_request(250, -1) tempo.set_value(5) tempo_item = gtk.ToolItem() tempo_item.add(tempo) - self.insert(tempo_item, -1) + toolbar.insert(tempo_item, -1) separator = gtk.SeparatorToolItem() - self.insert(separator,-1) + toolbar.insert(separator,-1) clear_tape = ToolButton('sl-reset') - clear_tape.connect('clicked', self._clear_tape_cb) + clear_tape.connect('clicked', self.__clear_tape_cb) clear_tape.set_tooltip(_('Reset')) - self.insert(clear_tape, -1) + toolbar.insert(clear_tape, -1) + + toolbar.show_all() - self.show_all() + return toolbar - def _clear_tape_cb(self, widget): + def __clear_tape_cb(self, widget): for i in range(theme.TAPE_COUNT): self.montage.props.frame = (i, None) - def _tempo_cb(self, widget): + def __tempo_cb(self, widget): self.montage.set_tempo(widget.value) - def _play_cb(self, widget): + def __play_cb(self, widget, playButtonImg, pauseButtonImg): if widget.get_active(): - widget.set_icon_widget(self.pauseButtonImg) + widget.set_icon_widget(pauseButtonImg) sound.play() self.montage.play() else: - widget.set_icon_widget(self.playButtonImg) + widget.set_icon_widget(playButtonImg) sound.stop() self.montage.stop() -class LessonsToolbar(gtk.Toolbar): - def __init__(self): - gtk.Toolbar.__init__(self) - self._mask = False + def _create_lessons_toolbar(self): + toolbar = gtk.Toolbar() for lesson in lessons.THEMES: - button = gtk.ToggleToolButton() + button = gtk.RadioToolButton() button.set_label(lesson.name) - button.connect('clicked', self._lessons_cb, lesson) - self.insert(button, -1) + if toolbar.get_n_items(): + button.props.group = toolbar.get_nth_item(0) + button.connect('clicked', self.__lesson_clicked_cb, lesson) + toolbar.insert(button, -1) - self.get_nth_item(0).set_active(True) - self.show_all() + toolbar.get_nth_item(0).set_active(True) + toolbar.show_all() - def _lessons_cb(self, widget, lesson): - if self._mask: - return - self._mask = True + return toolbar - for i, j in enumerate(lessons.THEMES): - if j != lesson: - self.get_nth_item(i).set_active(False) - - widget.props.active = True + def __lesson_clicked_cb(self, widget, lesson): lesson.change() - self._mask = False + + def __toggled_lessons_button_cb(self, button): + page = button.props.active and 1 or 0 + self.notebook_toolbar.set_current_page(page) + self.notebook.set_current_page(page) + + sound.stop() + self.montage.stop() diff --git a/char.py b/char.py index 2ee1543..131c14d 100644 --- a/char.py +++ b/char.py @@ -17,11 +17,12 @@ import gtk import glob from gettext import gettext as _ -import port.chooser as chooser -import port.pixbuf as pixbuf +import toolkit.chooser as chooser +from toolkit import pixbuf import theme + def load(): from document import Document diff --git a/document.py b/document.py index d751eb9..99f1a04 100644 --- a/document.py +++ b/document.py @@ -14,12 +14,9 @@ import os import gtk - import logging -logger = logging.getLogger('cartoon-builder') -import port.json as json -from port.tarball import Tarball +import toolkit.json as json import theme from sound import * @@ -27,6 +24,11 @@ from ground import * from utils import * from char import * +from toolkit.tarball import Tarball + +logger = logging.getLogger('cartoon-builder') + + class Document: tape = [] ground = None diff --git a/ground.py b/ground.py index a65b657..25139fe 100644 --- a/ground.py +++ b/ground.py @@ -16,11 +16,12 @@ import os import gtk from gettext import gettext as _ -import port.chooser as chooser -import port.pixbuf as pixbuf +import toolkit.chooser as chooser +from toolkit import pixbuf import theme + def load(): from document import Document diff --git a/icons/mamamedia.svg b/icons/mamamedia.svg new file mode 100644 index 0000000..a74f45a --- /dev/null +++ b/icons/mamamedia.svg @@ -0,0 +1,203 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/messenger.py b/messenger.py index 35f36f8..c03005e 100644 --- a/messenger.py +++ b/messenger.py @@ -17,7 +17,7 @@ import dbus from dbus.gobject_service import ExportedGObject from dbus.service import method, signal -import port.json as json +import toolkit.json as json from sugar.presence import presenceservice import char diff --git a/montage.py b/montage.py index b403fc7..9f5fdbc 100644 --- a/montage.py +++ b/montage.py @@ -23,7 +23,7 @@ import gobject import logging from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT -from port.scrolledbox import VScrolledBox +from widgets.scrolledbox import VScrolledBox import theme import char @@ -38,9 +38,9 @@ logger = logging.getLogger('cartoon-builder') class View(gtk.EventBox): __gsignals__ = { - 'frame-changed' : (SIGNAL_RUN_FIRST, None, 2*[TYPE_PYOBJECT]), - 'ground-changed': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), - 'sound-changed' : (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]) } + 'frame-changed' : (SIGNAL_RUN_FIRST, None, 2*[TYPE_PYOBJECT]), + 'ground-changed': (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]), + 'sound-changed' : (SIGNAL_RUN_FIRST, None, [TYPE_PYOBJECT]) } def set_frame(self, value): tape_num, frame = value diff --git a/port/COPYING b/port/COPYING deleted file mode 100644 index 623b625..0000000 --- a/port/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. diff --git a/port/README b/port/README deleted file mode 100644 index 256200d..0000000 --- a/port/README +++ /dev/null @@ -1,18 +0,0 @@ -About ------ - -A set of sugar components/libraries/etc to simplify writing activities. - -Cornerstone purposes for this project: -* Total backwards compatibility for sugar-port API -* Run on all sugar platforms beginning from 0.82 - -In most cases sugar-port could be embedded to activity's directory tree. -There is no need to include the whole sugar-port project only top level -files/directories you are using directly - sugar-port's top level entities -don't import each other. - -Get it ------- - -http://wiki.sugarlabs.org/go/Development_Team/sugar-port diff --git a/port/__init__.py b/port/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/port/__init__.py +++ /dev/null diff --git a/port/activity.py b/port/activity.py deleted file mode 100644 index e3b6fdd..0000000 --- a/port/activity.py +++ /dev/null @@ -1,305 +0,0 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -"""Extend sugar-toolkit activity class""" - -import gtk -import logging -import telepathy -import gobject - -import sugar.activity.activity as toolkit -from sugar.presence.sugartubeconn import SugarTubeConnection -from sugar.graphics.alert import ConfirmationAlert, NotifyAlert - -_NEW_INSTANCE = 0 -_NEW_INSTANCE = 1 -_PRE_INSTANCE = 2 -_POST_INSTANCE = 3 - -class CursorFactory: - __shared_state = {"cursors": {}} - - def __init__(self): - self.__dict__ = self.__shared_state - - def get_cursor(self, cur_type): - if not self.cursors.has_key(cur_type): - cur = gtk.gdk.Cursor(cur_type) - self.cursors[cur_type] = cur - return self.cursors[cur_type] - -class Activity(toolkit.Activity): - """Basic activity class""" - - def new_instance(self): - """ - New instance was created. - - Will be invoked after __init__() instead of resume_instance(). - Subclass should implement this method to catch creation stage. - """ - pass - - def resume_instance(self, filepath): - """ - Instance was resumed. - - Will be invoked after __init__() instead of new_instance(). - Subclass should implement this method to catch resuming stage. - - """ - pass - - def save_instance(self, filepath): - """ - Save activity instance. - - Subclass should implement this method to save activity data. - """ - raise NotImplementedError - - def on_save_instance(self, cb, *args): - """ Register callback which will be invoked before save_instance """ - self.__on_save_instance.append((cb, args)) - - def share_instance(self, connection, is_initiator): - """ - Activity was shared/joined. - - connection -- SugarTubeConnection object - wich represents telepathy connection - - is_initiator -- boolean - if True activity was shared and - (current activity is an initiator of sharing) - otherwise activity was joined(to existed sharing session) - - Will be invoked after __init__() and {new,resume}_instance(). - Subclass should implement this method to catch sharing stage. - """ - pass - - def notify_alert(self, title, msg): - """Raise standard notify alert""" - alert = NotifyAlert(title=title, msg=msg) - - def response(alert, response_id, self): - self.remove_alert(alert) - - alert.connect('response', response, self) - alert.show_all() - self.add_alert(alert) - - def confirmation_alert(self, title, msg, cb, *cb_args): - """Raise standard confirmation alert""" - alert = ConfirmationAlert(title=title, msg=msg) - - def response(alert, response_id, self, cb, *cb_args): - self.remove_alert(alert) - if response_id is gtk.RESPONSE_OK: - cb(*cb_args) - - alert.connect('response', response, self, cb, *cb_args) - alert.show_all() - self.add_alert(alert) - - def get_cursor(self): - return self._cursor - - def set_cursor(self, cursor): - if not isinstance(cursor, gtk.gdk.Cursor): - cursor = CursorFactory().get_cursor(cursor) - - if self._cursor != cursor: - self._cursor = cursor - self.window.set_cursor(self._cursor) - - def __init__(self, canvas, handle): - """ - Initialise the Activity. - - canvas -- gtk.Widget - root widget for activity content - - handle -- sugar.activity.activityhandle.ActivityHandle - instance providing the activity id and access to the - presence service which *may* provide sharing for this - application - - """ - toolkit.Activity.__init__(self, handle) - - if handle.object_id: - self.__state = _NEW_INSTANCE - else: - self.__state = _NEW_INSTANCE - - self.__resume_filename = None - self.__postponed_share = [] - self.__on_save_instance = [] - - self._cursor = None - self.set_cursor(gtk.gdk.LEFT_PTR) - - # XXX do it after(possible) read_file() invoking - # have to rely on calling read_file() from map_cb in sugar-toolkit - canvas.connect_after('map', self.__map_canvasactivity_cb) - self.set_canvas(canvas) - - def __instance(self): - logging.debug('Activity.__instance') - - if self.__resume_filename: - self.resume_instance(self.__resume_filename) - else: - self.new_instance() - - for i in self.__postponed_share: - self.share_instance(*i) - self.__postponed_share = [] - - self.__state = _POST_INSTANCE - - def read_file(self, filepath): - """Subclass should not override this method""" - logging.debug('Activity.read_file state=%s' % self.__state) - - self.__resume_filename = filepath - - if self.__state == _NEW_INSTANCE: - self.__state = _PRE_INSTANCE - elif self.__state == _PRE_INSTANCE: - self.__instance(); - - def write_file(self, filepath): - """Subclass should not override this method""" - for cb, args in self.__on_save_instance: - cb(*args) - self.save_instance(filepath) - - def __map_canvasactivity_cb(self, widget): - logging.debug('Activity.__map_canvasactivity_cb state=%s' % \ - self.__state) - - if self.__state == _NEW_INSTANCE: - self.__instance() - elif self.__state == _NEW_INSTANCE: - self.__state = _PRE_INSTANCE - elif self.__state == _PRE_INSTANCE: - self.__instance(); - - return False - - def _share(self, tube_conn, initiator): - logging.debug('Activity._share state=%s' % self.__state) - - if self.__state == _NEW_INSTANCE: - self.__postponed_share.append((tube_conn, initiator)) - self.__state = _PRE_INSTANCE - elif self.__state == _PRE_INSTANCE: - self.__postponed_share.append((tube_conn, initiator)) - self.__instance(); - elif self.__state == _POST_INSTANCE: - self.share_instance(tube_conn, initiator) - -class SharedActivity(Activity): - """Basic activity class with sharing features""" - - def __init__(self, canvas, service, handle): - """ - Initialise the Activity. - - canvas -- gtk.Widget - root widget for activity content - - service -- string - dbus service for activity - - handle -- sugar.activity.activityhandle.ActivityHandle - instance providing the activity id and access to the - presence service which *may* provide sharing for this - application - - """ - Activity.__init__(self, canvas, handle) - self.service = service - - self.connect('shared', self._shared_cb) - - # Owner.props.key - if self._shared_activity: - # We are joining the activity - self.connect('joined', self._joined_cb) - if self.get_shared(): - # We've already joined - self._joined_cb() - - def _shared_cb(self, activity): - logging.debug('My activity was shared') - self.__initiator = True - self._sharing_setup() - - logging.debug('This is my activity: making a tube...') - id = self._tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube( - self.service, {}) - - def _joined_cb(self, activity): - if not self._shared_activity: - return - - logging.debug('Joined an existing shared activity') - - self.__initiator = False - self._sharing_setup() - - logging.debug('This is not my activity: waiting for a tube...') - self._tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes( - reply_handler=self._list_tubes_reply_cb, - error_handler=self._list_tubes_error_cb) - - def _sharing_setup(self): - if self._shared_activity is None: - logging.error('Failed to share or join activity') - return - self._conn = self._shared_activity.telepathy_conn - self._tubes_chan = self._shared_activity.telepathy_tubes_chan - self._text_chan = self._shared_activity.telepathy_text_chan - - self._tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal( - 'NewTube', self._new_tube_cb) - - def _list_tubes_reply_cb(self, tubes): - for tube_info in tubes: - self._new_tube_cb(*tube_info) - - def _list_tubes_error_cb(self, e): - logging.error('ListTubes() failed: %s', e) - - def _new_tube_cb(self, id, initiator, type, service, params, state): - logging.debug('New tube: ID=%d initator=%d type=%d service=%s ' - 'params=%r state=%d', id, initiator, type, service, - params, state) - - if (type == telepathy.TUBE_TYPE_DBUS and - service == self.service): - if state == telepathy.TUBE_STATE_LOCAL_PENDING: - self._tubes_chan[telepathy.CHANNEL_TYPE_TUBES] \ - .AcceptDBusTube(id) - - tube_conn = SugarTubeConnection(self._conn, - self._tubes_chan[telepathy.CHANNEL_TYPE_TUBES], id, - group_iface=self._text_chan[telepathy.CHANNEL_INTERFACE_GROUP]) - - self._share(tube_conn, self.__initiator) diff --git a/port/chooser.py b/port/chooser.py deleted file mode 100644 index e2df259..0000000 --- a/port/chooser.py +++ /dev/null @@ -1,66 +0,0 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -"""Object chooser method""" - -import gtk -import logging - -from sugar import mime -from sugar.graphics.objectchooser import ObjectChooser - -TEXT = hasattr(mime, 'GENERIC_TYPE_TEXT') and mime.GENERIC_TYPE_TEXT or None -IMAGE = hasattr(mime, 'GENERIC_TYPE_IMAGE') and mime.GENERIC_TYPE_IMAGE or None -AUDIO = hasattr(mime, 'GENERIC_TYPE_AUDIO') and mime.GENERIC_TYPE_AUDIO or None -VIDEO = hasattr(mime, 'GENERIC_TYPE_VIDEO') and mime.GENERIC_TYPE_VIDEO or None -LINK = hasattr(mime, 'GENERIC_TYPE_LINK') and mime.GENERIC_TYPE_LINK or None - -def pick(cb=None, default=None, parent=None, what=None): - """ - Opens object chooser. - - Method returns: - - * cb(jobject), if object was choosen and cb is not None - * jobject, if object was choosen and cb is None - * default, otherwise - - NOTE: 'what' makes sense only for sugar >= 0.84 - """ - what = what and {'what_filter': what} or {} - chooser = ObjectChooser(parent=parent, **what) - - jobject = None - out = None - - try: - if chooser.run() == gtk.RESPONSE_ACCEPT: - jobject = chooser.get_selected_object() - logging.debug('ObjectChooser: %r' % jobject) - - if jobject and jobject.file_path: - if cb: - out = cb(jobject) - else: - out = jobject - finally: - if jobject and id(jobject) != id(out): - jobject.destroy() - chooser.destroy() - del chooser - - if out: - return out - else: - return default diff --git a/port/json.py b/port/json.py deleted file mode 100644 index d464abb..0000000 --- a/port/json.py +++ /dev/null @@ -1,33 +0,0 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -""" -Unify usage of simplejson in Python 2.5/2.6 - -In Python 2.5 it imports simplejson module, in 2.6 native json module. - -Usage: - - import port.json as json - - # and using regular simplejson interface with module json - json.dumps([]) - -""" - -try: - from json import * - dumps -except (ImportError, NameError): - from simplejson import * diff --git a/port/pixbuf.py b/port/pixbuf.py deleted file mode 100644 index ba6d0f5..0000000 --- a/port/pixbuf.py +++ /dev/null @@ -1,213 +0,0 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -"""gtk.gdk.Pixbuf extensions""" - -import re -import os -import cStringIO -import gtk -import rsvg -import cairo -import logging - -from sugar.graphics.xocolor import XoColor -from sugar.util import LRU - -def to_file(pixbuf): - """Convert pixbuf object to file object""" - - def push(pixbuf, buffer): - buffer.write(pixbuf) - - buffer = cStringIO.StringIO() - pixbuf.save_to_callback(push, 'png', user_data=buffer) - buffer.seek(0) - - return buffer - -def to_str(pixbuf): - """Convert pixbuf object to string""" - return to_file(pixbuf).getvalue() - -def from_str(str): - """Convert string to pixbuf object""" - - loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') - loader.write(str) - loader.close() - - return loader.get_pixbuf() - -def from_svg_at_size(filename=None, width=None, height=None, handle=None, - keep_ratio=True): - """Scale and load SVG into pixbuf""" - - if not handle: - handle = rsvg.Handle(filename) - - dimensions = handle.get_dimension_data() - icon_width = dimensions[0] - icon_height = dimensions[1] - - if icon_width != width or icon_height != height: - ratio_width = float(width) / icon_width - ratio_height = float(height) / icon_height - - if keep_ratio: - ratio = min(ratio_width, ratio_height) - if ratio_width != ratio: - ratio_width = ratio - width = int(icon_width * ratio) - elif ratio_height != ratio: - ratio_height = ratio - height = int(icon_height * ratio) - else: - ratio_width = 1 - ratio_height = 1 - - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) - context.scale(ratio_width, ratio_height) - handle.render_cairo(context) - - loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') - surface.write_to_png(loader) - loader.close() - - return loader.get_pixbuf() - -def sugar_icon(file_name=None, icon_name=None, - width=None, height=None, - color=None, - insensitive_widget=None): - """Load sugar icon into pixbuf - - NOTE: Function can load all image formats but makes sense only for SVG - (due to color argument, see load_svg()) - - NOTE: Function caches results - - Arguments: - file_name path to filename with image - (mutually exclusive for icon_name) - icon_name name of icon - (mutually exclusive for icon_name) - width width of final image - height height of final image - color defines stroke and fill colors for final SVG image - in string notion, could be: - * tuple of (stroke_color, fill_color) - * XoColor - * scalar value for stroke and fill colors - insensitive_widget render icon in insensitive mode - """ - def load_svg(): - entities = {} - if fill_color: - entities['fill_color'] = fill_color - if stroke_color: - entities['stroke_color'] = stroke_color - - f = open(icon_filename, 'r') - icon = f.read() - f.close() - - for entity, value in entities.items(): - xml = '' % (entity, value) - icon = re.sub('' % entity, xml, icon) - - return rsvg.Handle(data=icon) - - def get_insensitive_pixbuf(): - if not (insensitive_widget and insensitive_widget.style): - return pixbuf - - icon_source = gtk.IconSource() - # Special size meaning "don't touch" - icon_source.set_size(-1) - icon_source.set_pixbuf(pixbuf) - icon_source.set_state(gtk.STATE_INSENSITIVE) - icon_source.set_direction_wildcarded(False) - icon_source.set_size_wildcarded(False) - - # Please note that the pixbuf returned by this function is leaked - # with current stable versions of pygtk. The relevant bug is - # http://bugzilla.gnome.org/show_bug.cgi?id=502871 - # -- 2007-12-14 Benjamin Berg - pixbuf = insensitive_widget.style.render_icon(icon_source, - insensitive_widget.get_direction(), gtk.STATE_INSENSITIVE, -1, - insensitive_widget, "sugar-icon") - - return pixbuf - - def get_cache_key(): - return (icon_filename, fill_color, stroke_color, width, height, - insensitive_widget is None) - - if isinstance(color, XoColor): - stroke_color = color.get_stroke_color() - fill_color = color.get_fill_color() - elif isinstance(color, tuple): - stroke_color = color[0] - fill_color = color[1] - else: - stroke_color = color - fill_color = color - - if file_name: - icon_filename = file_name - elif icon_name: - theme = gtk.icon_theme_get_default() - info = theme.lookup_icon(icon_name, width or 50, 0) - if info: - icon_filename = info.get_filename() - del info - else: - logging.warning('No icon with the name %s ' - 'was found in the theme.' % icon_name) - else: - return None - - cache_key = get_cache_key() - if cache_key in _sugar_icon_cache: - return _sugar_icon_cache[cache_key] - - logging.debug('sugar_icon: file_name=%s icon_name=%s width=%s height=%s ' \ - 'color=%s' % (file_name, icon_name, width, height, color)) - - is_svg = icon_filename.endswith('.svg') - - if is_svg: - handle = load_svg() - if width and height: - pixbuf = from_svg_at_size(handle=handle, width=width, height=height, - keep_ratio=True) - else: - pixbuf = handle.get_pixbuf() - else: - if width and height: - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(icon_filename, - width, height) - else: - pixbuf = gtk.gdk.pixbuf_new_from_file(icon_filename) - - if insensitive_widget: - pixbuf = get_insensitive_pixbuf() - - _sugar_icon_cache[cache_key] = pixbuf - - return pixbuf - -_sugar_icon_cache = LRU(50) diff --git a/port/scrolledbox.py b/port/scrolledbox.py deleted file mode 100644 index c2bbb38..0000000 --- a/port/scrolledbox.py +++ /dev/null @@ -1,179 +0,0 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gtk - -from sugar.graphics.icon import Icon - -class ScrollButton(gtk.ToolButton): - def __init__(self, icon_name): - gtk.ToolButton.__init__(self) - - icon = Icon(icon_name = icon_name, - icon_size=gtk.ICON_SIZE_SMALL_TOOLBAR) - # The alignment is a hack to work around gtk.ToolButton code - # that sets the icon_size when the icon_widget is a gtk.Image - alignment = gtk.Alignment(0.5, 0.5) - alignment.add(icon) - self.set_icon_widget(alignment) - -class ScrolledBox(gtk.EventBox): - def __init__(self, orientation, arrows_policy = gtk.POLICY_AUTOMATIC): - gtk.EventBox.__init__(self) - self.orientation = orientation - self._viewport = None - self._abox = None - self._aviewport = None - self._aviewport_sig = None - self._arrows_policy = arrows_policy - self._left = None - self._right = None - - if orientation == gtk.ORIENTATION_HORIZONTAL: - box = gtk.HBox() - else: - box = gtk.VBox() - if self._arrows_policy == gtk.POLICY_AUTOMATIC: - box.connect("size-allocate", self._box_allocate_cb) - self.add(box) - - if self._arrows_policy != gtk.POLICY_NEVER: - if orientation == gtk.ORIENTATION_HORIZONTAL: - self._left = ScrollButton('go-left') - else: - self._left = ScrollButton('go-up') - self._left.connect('clicked', self._scroll_cb, 'left') - box.pack_start(self._left, False, False, 0) - - self._scrolled = gtk.ScrolledWindow() - if orientation == gtk.ORIENTATION_HORIZONTAL: - self._scrolled.set_policy(arrows_policy, gtk.POLICY_NEVER) - else: - self._scrolled.set_policy(gtk.POLICY_NEVER, arrows_policy) - self._scrolled.connect('scroll-event', self._scroll_event_cb) - box.pack_start(self._scrolled, True, True, 0) - - if orientation == gtk.ORIENTATION_HORIZONTAL: - self._adj = self._scrolled.get_hadjustment() - else: - self._adj = self._scrolled.get_vadjustment() - self._adj.connect('changed', self._scroll_changed_cb) - self._adj.connect('value-changed', self._scroll_changed_cb) - - if self._arrows_policy != gtk.POLICY_NEVER: - if orientation == gtk.ORIENTATION_HORIZONTAL: - self._right = ScrollButton('go-right') - else: - self._right = ScrollButton('go-down') - self._right.connect('clicked', self._scroll_cb, 'right') - box.pack_start(self._right, False, False, 0) - - def modify_fg(self, state, bg): - gtk.EventBox.modify_fg(self, state, bg) - self._viewport.get_parent().modify_fg(state, bg) - - def modify_bg(self, state, bg): - gtk.EventBox.modify_bg(self, state, bg) - self._viewport.get_parent().modify_bg(state, bg) - - def set_viewport(self, widget): - if widget == self._viewport: return - if self._viewport and self._aviewport_sig: - self._viewport.disconnect(self._aviewport_sig) - self._viewport = widget - - if self._arrows_policy == gtk.POLICY_AUTOMATIC: - self._aviewport_sig = self._viewport.connect('size-allocate', - self._viewport_allocate_cb) - - self._scrolled.add_with_viewport(widget) - - def get_viewport_allocation(self): - alloc = self._scrolled.get_allocation() - alloc.x -= self._adj.get_value() - return alloc - - def get_adjustment(self): - return self._adj - - def _box_allocate_cb(self, w, a): - self._abox = a - self._update_arrows() - - def _viewport_allocate_cb(self, w, a): - self._aviewport = a - self._update_arrows() - - def _update_arrows(self): - if not self._abox or not self._aviewport: return - - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - show_flag = self._abox.width < self._aviewport.width - else: - show_flag = self._abox.height < self._aviewport.height - - if show_flag: - self._left.show() - self._right.show() - else: - self._left.hide() - self._right.hide() - - def _scroll_event_cb(self, widget, event): - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - if event.direction == gtk.gdk.SCROLL_UP: - event.direction = gtk.gdk.SCROLL_LEFT - if event.direction == gtk.gdk.SCROLL_DOWN: - event.direction = gtk.gdk.SCROLL_RIGHT - else: - if event.direction == gtk.gdk.SCROLL_LEFT: - event.direction = gtk.gdk.SCROLL_UP - if event.direction == gtk.gdk.SCROLL_RIGHT: - event.direction = gtk.gdk.SCROLL_DOWN - return False - - def _scroll_cb(self, widget, data): - if data == 'left': - val = max(self._adj.get_property('lower'), self._adj.get_value() - - self._adj.get_property('page_increment')) - else: - val = min(self._adj.get_property('upper') - - self._adj.get_property('page_size'), - self._adj.get_value() - + self._adj.get_property('page_increment')) - - self._adj.set_value(val) - - def _scroll_changed_cb(self, widget): - val = self._adj.get_value() - if self._left: - if val == 0: - self._left.set_sensitive(False) - else: - self._left.set_sensitive(True) - - if self._right: - if val >= self._adj.get_property('upper') - \ - self._adj.get_property('page_size'): - self._right.set_sensitive(False) - else: - self._right.set_sensitive(True) - -class HScrolledBox(ScrolledBox): - def __init__(self, *args): - ScrolledBox.__init__(self, gtk.ORIENTATION_HORIZONTAL, *args) - -class VScrolledBox(ScrolledBox): - def __init__(self, *args): - ScrolledBox.__init__(self, gtk.ORIENTATION_VERTICAL, *args) diff --git a/port/tarball.py b/port/tarball.py deleted file mode 100644 index 9e842b9..0000000 --- a/port/tarball.py +++ /dev/null @@ -1,159 +0,0 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -"""Simplify tarfile module usage""" - -import os -import time -import tarfile -import cStringIO -import gtk -import zipfile -import tempfile -import shutil - -class TarballError(Exception): - """Base Tarball exception.""" - pass - -class BadDataTypeError(TarballError): - """Exception for unsupported data type in read/write methods.""" - pass - -class Tarball: - """ - Wrap standart tarfile module to simplify read/write operations with - most popular data types. - - In read mode Tarball can load zip files as well. - - Supprted types: - - * string - * gtk.gdk.Pixbuf - - Write usage: - - # create Tarball object - # to see all supported modes use - # http://docs.python.org/library/tarfile.html#tarfile.open - tar = Tarball(tarfile, 'w') - - # write string to file in tarball - tar.write('name within tarball', 'string to write') - - # write pixbuf to file in tarball - tar.write('name within tarball', pixbuf_object) - - # save and close tarball file - tar.close() - - Read usage: - - # create Tarball object - tar = Tarball(tarfile) - - # read content of file in tarball to string - str_content = tar.read('name within tarball') - - # read content of file in tarball to pixbuf object - pixbuf_content = tar.read_pixbuf('name within tarball') - """ - - def __init__(self, name=None, mode='r', mtime=None): - if not mode.startswith('r') or tarfile.is_tarfile(name): - self.__tar = tarfile.TarFile(name=name, mode=mode) - else: - # convert for tar - - if not zipfile.is_zipfile(name): - raise tarfile.ReadError() - - try: - tmp_dir = tempfile.mkdtemp() - tmp_fd, tmp_name = tempfile.mkstemp() - tmp_fo = os.fdopen(tmp_fd, 'w') - - zip = zipfile.ZipFile(name) - zip.extractall(tmp_dir) - - tar = tarfile.TarFile(fileobj=tmp_fo, mode='w') - tar.add(tmp_dir, arcname='') - tar.close() - - self.__tar = tarfile.TarFile(name=tmp_name, mode=mode) - finally: - tmp_fo.close() - os.unlink(tmp_name) - shutil.rmtree(tmp_dir) - - if mtime: - self.mtime = mtime - else: - self.mtime = time.time() - - def close(self): - """Save(if 'r' mode was given) and close tarball file.""" - self.__tar.close() - - def getnames(self): - """Return names of members sorted by creation order.""" - return self.__tar.getnames() - - def read(self, arcname): - """Returns sring with content of given file from tarball.""" - file_o = self.__tar.extractfile(arcname.encode('utf8')) - if not file_o: - return None - out = file_o.read() - file_o.close() - return out - - def read_pixbuf(self, arcname): - """Returns pixbuf object of given file from tarball.""" - loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') - loader.write(self.read(arcname)) - loader.close() - return loader.get_pixbuf() - - def write(self, arcname, data, mode=0644): - """ - Stores given object to file in tarball. - Raises BadDataTypeError exception If data type isn't supported. - """ - info = tarfile.TarInfo(arcname.encode('utf8')) - info.mode = mode - info.mtime = self.mtime - - if isinstance(data, str): - self.__write_str(info, data) - elif isinstance(data, gtk.gdk.Pixbuf): - self.__write_pixbuf(info, data) - else: - raise BadDataTypeError() - - def __write_str(self, info, data): - info.size = len(data) - self.__tar.addfile(info, cStringIO.StringIO(data)) - - def __write_pixbuf(self, info, data): - def push(pixbuf, buffer): - buffer.write(pixbuf) - - buffer = cStringIO.StringIO() - data.save_to_callback(push, 'png', user_data=buffer) - - info.size = buffer.tell() - buffer.seek(0) - self.__tar.addfile(info, buffer) diff --git a/port/temposlider.py b/port/temposlider.py deleted file mode 100644 index 6950453..0000000 --- a/port/temposlider.py +++ /dev/null @@ -1,215 +0,0 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -import gtk -import rsvg -import cairo - -from sugar.graphics import style - -class TempoSlider(gtk.HBox): - def __init__(self, min_value, max_value): - gtk.HBox.__init__(self) - - self._pixbuf = [None] * 8 - self._image = gtk.Image() - self._image.show() - - # used to store tempo updates while the slider is active - self._delayed = 0 - self._active = False - - self.adjustment = gtk.Adjustment(min_value, min_value, max_value, - (max_value - min_value) / 8, (max_value - min_value) / 8, 0) - self._adjustment_h = self.adjustment.connect('value-changed', - self._changed_cb) - - slider = gtk.HScale(adjustment = self.adjustment) - slider.show() - slider.set_draw_value(False) - slider.connect("button-press-event", self._press_cb) - slider.connect("button-release-event", self._release_cb) - - self.pack_start(slider, True, True) - self.pack_end(self._image, False, False) - - def set_value(self, tempo, quiet = False): - if self._active: - self._delayed = tempo - elif quiet: - self.adjustment.handler_block(self._adjustment_h) - self.adjustment.set_value(tempo) - self._update(tempo) - self.adjustment.handler_unblock(self._adjustment_h) - else: - self.adjustment.set_value(tempo) - - def _changed_cb(self, widget): - self._update(widget.get_value()) - - def _update(self, tempo): - def map_range(value, ilower, iupper, olower, oupper): - if value == iupper: - return oupper - return olower + int((oupper-olower+1) * (value-ilower) / - float(iupper-ilower)) - - img = map_range(tempo, self.adjustment.lower, - self.adjustment.upper, 0, 7) - - if not self._pixbuf[img]: - svg = rsvg.Handle(data=IMAGE[img]) - self._pixbuf[img] = _from_svg_at_size(handle=svg, - width=style.STANDARD_ICON_SIZE, - height=style.STANDARD_ICON_SIZE) - - self._image.set_from_pixbuf(self._pixbuf[img]) - - def _press_cb(self, widget, event): - self._active = True - - def _release_cb(self, widget, event): - self._active = False - if self._delayed != 0: - self.set_value(self._delayed, True) - self._delayed = 0 - -def _from_svg_at_size(filename=None, width=None, height=None, handle=None, - keep_ratio=True): - """ import from pixbuf.py """ - - if not handle: - handle = rsvg.Handle(filename) - - dimensions = handle.get_dimension_data() - icon_width = dimensions[0] - icon_height = dimensions[1] - - if icon_width != width or icon_height != height: - ratio_width = float(width) / icon_width - ratio_height = float(height) / icon_height - - if keep_ratio: - ratio = min(ratio_width, ratio_height) - if ratio_width != ratio: - ratio_width = ratio - width = int(icon_width * ratio) - elif ratio_height != ratio: - ratio_height = ratio - height = int(icon_height * ratio) - else: - ratio_width = 1 - ratio_height = 1 - - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) - context.scale(ratio_width, ratio_height) - handle.render_cairo(context) - - loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') - surface.write_to_png(loader) - loader.close() - - return loader.get_pixbuf() - -IMAGE = [None] * 8 - -IMAGE[0] = """ - - - - - -""" - -IMAGE[1] = """ - - - - - -""" - -IMAGE[2] = """ - - - - - -""" - -IMAGE[3] = """ - - - - - -""" - -IMAGE[4] = """ - - - - - -""" - -IMAGE[5] = """ - - - - - - -""" - -IMAGE[6] = """ - - - - - -""" - -IMAGE[7] = """ - - - - - -""" diff --git a/sound.py b/sound.py index b473ca9..82c9cfb 100644 --- a/sound.py +++ b/sound.py @@ -19,12 +19,13 @@ import shutil from glob import glob from gettext import gettext as _ -import port.chooser as chooser +import toolkit.chooser as chooser import theme from utils import * from sugar.activity.activity import get_bundle_path + def load(): from document import Document -- cgit v0.9.1