diff options
Diffstat (limited to 'port')
-rw-r--r-- | port/AUTHORS | 1 | ||||
-rw-r--r-- | port/COPYING | 340 | ||||
-rw-r--r-- | port/NEWS | 8 | ||||
-rw-r--r-- | port/README | 13 | ||||
-rw-r--r-- | port/TODO | 0 | ||||
-rw-r--r-- | port/__init__.py | 0 | ||||
-rw-r--r-- | port/activity.py | 271 | ||||
-rw-r--r-- | port/chooser.py | 66 | ||||
-rw-r--r-- | port/epydoc | 21 | ||||
-rw-r--r-- | port/images/tempo1.svg | 8 | ||||
-rw-r--r-- | port/images/tempo2.svg | 9 | ||||
-rw-r--r-- | port/images/tempo3.svg | 8 | ||||
-rw-r--r-- | port/images/tempo4.svg | 9 | ||||
-rw-r--r-- | port/images/tempo5.svg | 9 | ||||
-rw-r--r-- | port/images/tempo6.svg | 11 | ||||
-rw-r--r-- | port/images/tempo7.svg | 9 | ||||
-rw-r--r-- | port/images/tempo8.svg | 10 | ||||
-rw-r--r-- | port/json.py | 33 | ||||
-rw-r--r-- | port/pixbuf.py | 50 | ||||
l--------- | port/port | 1 | ||||
-rw-r--r-- | port/scrolledbox.py | 179 | ||||
-rw-r--r-- | port/tarball.py | 154 | ||||
-rw-r--r-- | port/temposlider.py | 85 |
23 files changed, 1295 insertions, 0 deletions
diff --git a/port/AUTHORS b/port/AUTHORS new file mode 100644 index 0000000..47ead6c --- /dev/null +++ b/port/AUTHORS @@ -0,0 +1 @@ +Aleksey Lim <alsroot@member.fsf.org> diff --git a/port/COPYING b/port/COPYING new file mode 100644 index 0000000..623b625 --- /dev/null +++ b/port/COPYING @@ -0,0 +1,340 @@ + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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. + + <signature of Ty Coon>, 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/NEWS b/port/NEWS new file mode 100644 index 0000000..0dcfeb5 --- /dev/null +++ b/port/NEWS @@ -0,0 +1,8 @@ +1 + +* Add tarball.py +* Add json import wrapper +* Add object chooser +* Add activity classes +* Add pixbuf methods +* Add TempoSlider and ScrolledBox widgets diff --git a/port/README b/port/README new file mode 100644 index 0000000..bd0dade --- /dev/null +++ b/port/README @@ -0,0 +1,13 @@ +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 + +Get it +------ + +http://wiki.sugarlabs.org/go/Development_Team/sugar-port diff --git a/port/TODO b/port/TODO new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/port/TODO diff --git a/port/__init__.py b/port/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/port/__init__.py diff --git a/port/activity.py b/port/activity.py new file mode 100644 index 0000000..dfe6a4a --- /dev/null +++ b/port/activity.py @@ -0,0 +1,271 @@ +# 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 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 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 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 __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 = [] + + # 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""" + 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 new file mode 100644 index 0000000..b7046be --- /dev/null +++ b/port/chooser.py @@ -0,0 +1,66 @@ +# 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 + * None, otherwise + + NOTE: what make 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/epydoc b/port/epydoc new file mode 100644 index 0000000..3e4852c --- /dev/null +++ b/port/epydoc @@ -0,0 +1,21 @@ +[epydoc] + +modules: *.py +output: html +target: html/ +verbosity: 0 +debug: 0 + +# Generation options +docformat: epytext +parse: yes +introspect: no +inheritance: listed +private: no +imports: no +sourcecode: yes + +# Output options +name: sugar-port +url: http://wiki.sugarlabs.org/go/Development_Team/sugar-port +frames: yes diff --git a/port/images/tempo1.svg b/port/images/tempo1.svg new file mode 100644 index 0000000..bb9aeec --- /dev/null +++ b/port/images/tempo1.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M23.5,6.5c3,3,7,7,9,11c-7,5-4,6-3,26c-1,1-8,1-9,0c0,0,2,1,2-1
+ c0-3-2-7-2-11c0-2,1-4,1-6c0-3-2-1-2-3c0-3,3-8,3-11c0-2-1-1-2-2v-3H23.5z"/>
+</svg>
diff --git a/port/images/tempo2.svg b/port/images/tempo2.svg new file mode 100644 index 0000000..4a98310 --- /dev/null +++ b/port/images/tempo2.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M27.5,44.5v-3C28.5,42.5,28.5,43.5,27.5,44.5z M26.5,10.5
+ c2,2,2,6,2,8c0,4-3,11-3,13s4,7,7,10c-2,2-4,3-5,5h-6c1-1,2-3,2-5c0-3-2-9-3-14c0,0,0-1-1,0v-6c0-3,3-8,3-11c0-1-2-2-2-6h3
+ C23.5,5.5,26.5,9.5,26.5,10.5z"/>
+</svg>
diff --git a/port/images/tempo3.svg b/port/images/tempo3.svg new file mode 100644 index 0000000..bd893bd --- /dev/null +++ b/port/images/tempo3.svg @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M30.5,17.5c0,3-2,2-2,4c0,3,4,14,7,21c-1,0-3,1-5,1c1-1,2,0,2-3
+ c0-2-4-7-6-10c-3,3-5,8-7,13c-1,0-3-1-4-1c3-3,7-14,7-18s-1-3-4-4c3-2,4-8,4-14h3C23.5,9.5,30.5,14.5,30.5,17.5z"/>
+</svg>
diff --git a/port/images/tempo4.svg b/port/images/tempo4.svg new file mode 100644 index 0000000..6fa5afa --- /dev/null +++ b/port/images/tempo4.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M34.5,22.5c-1-1-2-4-5-6c-1,2,0,3,0,6c0,2-3,4-3,7c0,2,4,2,4,4
+ c0,3-1,4-2,5c0-1,0-3-1-4c-1,3-2,7-3,10c-4-3,0-6,0-9s-3-11-4-17l-4,4c1-5,8.25-11.12,7.25-16.12c0.68,0.68,3.029,0,2.87,2.12
+ C26.5,10.25,33.62,17.75,34.5,22.5z"/>
+</svg>
diff --git a/port/images/tempo5.svg b/port/images/tempo5.svg new file mode 100644 index 0000000..9500e7e --- /dev/null +++ b/port/images/tempo5.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M24.5,13.5c2,1,5,3,5,6c0,2-2,3-2,5c0,9,11,4,11,13c-1,0-3-2-4-3
+ c-3-1-9,1-10-3c-2,3-5,7-7,11c-3,0-3-1-4-1c0-2,3-3,4-6s4-8,4-10c0-3-1-3-2-5c-1,0-2,1-3,2c0-1,2-3,2-4c1-2,3-5,2-8c0,0,1-1,4-2
+ C25.5,9.5,25.5,11.5,24.5,13.5z"/>
+</svg>
diff --git a/port/images/tempo6.svg b/port/images/tempo6.svg new file mode 100644 index 0000000..9844fd6 --- /dev/null +++ b/port/images/tempo6.svg @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M22.5,10.5c3,2,7,5,7,7c0,3-4,8-4,10c0,3,1,3,1,5h5l2-2l2,2v4
+ c-1,0-3-2-5-2c-3,0-5,1-8,1c-1,3-2,7-2,10h-5c1-1,3-3,3-4c1-5,1-11,1-18l-1-1c-1,1-1.75,2.88-2.75,2.88c0,0-0.25-0.63-0.25-1.63
+ c4-4,2-8.25,2-13.25c0-1,0.25-2.5,0.38-5.38L22.5,5.5C23.12,6.5,22.5,8.5,22.5,10.5z"/>
+<polygon fill-rule="evenodd" clip-rule="evenodd" fill="#333333" stroke="#333333" stroke-linecap="round" stroke-linejoin="round" points="
+ 25,20 25.25,16.75 26.5,17.88 "/>
+</svg>
diff --git a/port/images/tempo7.svg b/port/images/tempo7.svg new file mode 100644 index 0000000..54bed80 --- /dev/null +++ b/port/images/tempo7.svg @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M20.5,7.5c1,1,1,3,1,4c10,4,8,6,8,14c0,2,6,9,10,13c-1,2-2,4-4,5
+ c1.62-8.88-8.75-13.88-12-15c-1,1-1,0-1,2c0,3,2,5,3,7c-1,1-3,2-6,2c0-1,2-1,2-4c0-2-4-4-4-6c0-3,3-4,5-6c-3-8-8-2-11-6h6
+ c0-1,1,0,1-3c0-2-1-1-2-2l1-5H20.5z"/>
+</svg>
diff --git a/port/images/tempo8.svg b/port/images/tempo8.svg new file mode 100644 index 0000000..2c0154f --- /dev/null +++ b/port/images/tempo8.svg @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="50px" height="50px" viewBox="0 0 50 50" enable-background="new 0 0 50 50" xml:space="preserve">
+<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M20.5,12.5c0.67,0.4,0.4,1.9,1.75,2.25s1.05-0.38,1.5-0.37
+ c4.971,0,10.95-0.88,11.75,7.12c-1-2-3-4-5-5l-4,1c1,2,4,4,5,7c1,1,1,4,1,6c3,3,8-1,11,6c-2.88-0.82-4.25-2.62-12.75-2.75
+ c-1.561-0.02-2.34-1.561-3.75-1.87c-3.42-0.76-4.67-0.38-5.5-0.38c-3,0-8,7-11,7c-2,0-3-1-3-2c4,2,8-4,9-7c2-1,5-1,8-3c-2-4-6-5-8-3
+ l-6-6l2-2c1,1,1,2,1,4c1,0,4.12,0.38,6.12-0.62L16.5,17.5v-5H20.5z"/>
+</svg>
diff --git a/port/json.py b/port/json.py new file mode 100644 index 0000000..d464abb --- /dev/null +++ b/port/json.py @@ -0,0 +1,33 @@ +# 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 new file mode 100644 index 0000000..4390fef --- /dev/null +++ b/port/pixbuf.py @@ -0,0 +1,50 @@ +# 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 os +import cStringIO +import tempfile +import gtk + +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""" + + file_d, path = tempfile.mkstemp() + + file_o = os.fdopen(file_d, 'w') + file_o.write(str) + file_o.close() + + out = gtk.gdk.pixbuf_new_from_file(path) + os.unlink(path) + + return out diff --git a/port/port b/port/port new file mode 120000 index 0000000..945c9b4 --- /dev/null +++ b/port/port @@ -0,0 +1 @@ +.
\ No newline at end of file diff --git a/port/scrolledbox.py b/port/scrolledbox.py new file mode 100644 index 0000000..c2bbb38 --- /dev/null +++ b/port/scrolledbox.py @@ -0,0 +1,179 @@ +# 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 new file mode 100644 index 0000000..d07a3e1 --- /dev/null +++ b/port/tarball.py @@ -0,0 +1,154 @@ +# 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 + +import port.pixbuf as pixbuf + +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.""" + return pixbuf.from_str(self.read(arcname)) + + 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): + buffer = pixbuf.to_file(data) + buffer.seek(0, os.SEEK_END) + info.size = buffer.tell() + buffer.seek(0) + self.__tar.addfile(info, buffer) diff --git a/port/temposlider.py b/port/temposlider.py new file mode 100644 index 0000000..9d14be8 --- /dev/null +++ b/port/temposlider.py @@ -0,0 +1,85 @@ +# 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 os +import gtk + +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]: + self._pixbuf[img] = gtk.gdk.pixbuf_new_from_file_at_size( + os.path.join(os.path.dirname(__file__), 'images', + 'tempo' + str(img+1) + '.svg'), + style.STANDARD_ICON_SIZE, 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 |