From cba851bc93993db9422913059fc858ba390ced49 Mon Sep 17 00:00:00 2001 From: Marco Pesenti Gritti Date: Wed, 06 Feb 2008 09:37:37 +0000 Subject: Delete the library, it's now splitted out to sugar-toolkit. --- diff --git a/COPYING.LIB b/COPYING.LIB deleted file mode 100644 index 5ab7695..0000000 --- a/COPYING.LIB +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 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. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, 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 library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete 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 distribute a copy of this License along with the -Library. - - 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 Library or any portion -of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -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 Library, 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 Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you 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. - - If distribution of 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 satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be 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. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library 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. - - 9. 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 Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -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 with -this License. - - 11. 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 Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library 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 Library. - -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. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library 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. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -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 Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -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 - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. 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 LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. 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 library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; 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. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/Makefile.am b/Makefile.am index 0c2d35b..11777bce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,4 @@ -ACLOCAL_AMFLAGS = -I m4 - -SUBDIRS = bin data lib po src service +SUBDIRS = bin data po src service DISTCLEANFILES = \ intltool-extract \ @@ -9,7 +7,6 @@ DISTCLEANFILES = \ EXTRA_DIST = \ $(bin_SCRIPTS) \ - COPYING.LIB \ intltool-merge.in \ intltool-update.in \ intltool-extract.in diff --git a/autogen.sh b/autogen.sh index eaf5ff8..5b0385d 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,6 +1,4 @@ #!/bin/sh -export ACLOCAL="aclocal -I m4" - autoreconf -i intltoolize ./configure "$@" diff --git a/configure.ac b/configure.ac index 8af8f4e..41673e0 100644 --- a/configure.ac +++ b/configure.ac @@ -7,23 +7,10 @@ AC_CONFIG_SRCDIR([configure.ac]) AM_INIT_AUTOMAKE([1.9 foreign dist-bzip2 no-dist-gzip]) -AC_DISABLE_STATIC -AC_PROG_LIBTOOL - -AC_PATH_PROG([GLIB_GENMARSHAL], [glib-genmarshal]) - AM_PATH_PYTHON -AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)]) - -AC_PATH_PROG(PYGTK_CODEGEN, pygtk-codegen-2.0, no) PKG_CHECK_MODULES(SHELL, pygtk-2.0 gtk+-2.0) -PKG_CHECK_MODULES(LIB, pygtk-2.0 gtk+-2.0) - -PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0` -AC_SUBST(PYGTK_DEFSDIR) - # Setup GETTEXT # ALL_LINGUAS="am ar ay bn de dz el en es fa fr ha hi ig is it ja ko mk ml ne nl pa pl pt pt_BR qu ro ru rw th ur yo zh_CN zh_TW" @@ -53,14 +40,6 @@ AC_OUTPUT([ Makefile bin/Makefile data/Makefile -lib/Makefile -lib/sugar/Makefile -lib/sugar/activity/Makefile -lib/sugar/bundle/Makefile -lib/sugar/clipboard/Makefile -lib/sugar/graphics/Makefile -lib/sugar/presence/Makefile -lib/sugar/datastore/Makefile service/Makefile src/Makefile src/controlpanel/Makefile diff --git a/lib/.gitignore b/lib/.gitignore deleted file mode 100644 index 26353e1..0000000 --- a/lib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -sugar-marshal.* diff --git a/lib/Makefile.am b/lib/Makefile.am deleted file mode 100644 index 4fa44db..0000000 --- a/lib/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = sugar diff --git a/lib/sugar/.gitignore b/lib/sugar/.gitignore deleted file mode 100644 index f880b0e..0000000 --- a/lib/sugar/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -_sugarext.c -_sugarext.c diff --git a/lib/sugar/.license b/lib/sugar/.license deleted file mode 100644 index 6989ebe..0000000 --- a/lib/sugar/.license +++ /dev/null @@ -1 +0,0 @@ -LGPL diff --git a/lib/sugar/Makefile.am b/lib/sugar/Makefile.am deleted file mode 100644 index e9b92f7..0000000 --- a/lib/sugar/Makefile.am +++ /dev/null @@ -1,64 +0,0 @@ -SUBDIRS = activity bundle clipboard graphics presence datastore - -sugardir = $(pythondir)/sugar -sugar_PYTHON = \ - env.py \ - network.py \ - profile.py \ - util.py \ - wm.py - -pkgpyexecdir = $(pythondir)/sugar - -pkgpyexec_LTLIBRARIES = _sugarext.la - -_sugarext_la_CFLAGS = \ - $(LIB_CFLAGS) \ - $(PYTHON_INCLUDES) - -_sugarext_la_LDFLAGS = -module -avoid-version -_sugarext_la_LIBADD = $(LIB_LIBS) - -_sugarext_la_SOURCES = \ - $(BUILT_SOURCES) \ - _sugarextmodule.c \ - eggaccelerators.c \ - eggaccelerators.h \ - sexy-icon-entry.h \ - sexy-icon-entry.c \ - sugar-address-entry.c \ - sugar-address-entry.h \ - sugar-key-grabber.c \ - sugar-key-grabber.h \ - sugar-menu.h \ - sugar-menu.c \ - sugar-preview.h \ - sugar-preview.c - -BUILT_SOURCES = \ - _sugarext.c \ - sugar-marshal.c \ - sugar-marshal.h - -_sugarext.c: _sugarext.defs _sugarext.override - -.defs.c: - (cd $(srcdir)\ - && $(PYGTK_CODEGEN) \ - --register $(PYGTK_DEFSDIR)/gdk-types.defs \ - --register $(PYGTK_DEFSDIR)/gtk-types.defs \ - --override $*.override \ - --prefix py$* $*.defs) > gen-$*.c \ - && cp gen-$*.c $*.c \ - && rm -f gen-$*.c - -sugar-marshal.c: sugar-marshal.list - $(GLIB_GENMARSHAL) --prefix=sugar_marshal \ - $(srcdir)/sugar-marshal.list --header --body > sugar-marshal.c - -sugar-marshal.h: sugar-marshal.list - $(GLIB_GENMARSHAL) --prefix=sugar_marshal \ - $(srcdir)/sugar-marshal.list --header > sugar-marshal.h - -CLEANFILES = $(BUILT_SOURCES) -EXTRA_DIST = sugar-marshal.list _sugarext.defs _sugarext.override diff --git a/lib/sugar/_sugarext.defs b/lib/sugar/_sugarext.defs deleted file mode 100644 index 1c9812e..0000000 --- a/lib/sugar/_sugarext.defs +++ /dev/null @@ -1,196 +0,0 @@ -;; -*- scheme -*- -; object definitions - -(define-object AddressEntry - (in-module "Sugar") - (parent "GtkEntry") - (c-name "SugarAddressEntry") - (gtype-id "SUGAR_TYPE_ADDRESS_ENTRY") -) - -(define-object KeyGrabber - (in-module "Sugar") - (parent "GObject") - (c-name "SugarKeyGrabber") - (gtype-id "SUGAR_TYPE_KEY_GRABBER") -) - -(define-object Menu - (in-module "Sugar") - (parent "GtkMenu") - (c-name "SugarMenu") - (gtype-id "SUGAR_TYPE_MENU") -) - -(define-object Preview - (in-module "Sugar") - (parent "GObject") - (c-name "SugarPreview") - (gtype-id "SUGAR_TYPE_PREVIEW") -) - -(define-object IconEntry - (in-module "Sexy") - (parent "GtkEntry") - (c-name "SexyIconEntry") - (gtype-id "SEXY_TYPE_ICON_ENTRY") -) - -;; Enumerations and flags ... - -(define-enum IconEntryPosition - (in-module "Sexy") - (c-name "SexyIconEntryPosition") - (gtype-id "SEXY_TYPE_ICON_ENTRY_POSITION") - (values - '("primary" "SEXY_ICON_ENTRY_PRIMARY") - '("secondary" "SEXY_ICON_ENTRY_SECONDARY") - ) -) - -;; From sugar-menu.h - -(define-method set_active - (of-object "SugarMenu") - (c-name "sugar_menu_set_active") - (return-type "none") - (parameters - '("gboolean" "active") - ) -) - -(define-method embed - (of-object "SugarMenu") - (c-name "sugar_menu_embed") - (return-type "none") - (parameters - '("GtkContainer" "container") - ) -) - -(define-method unembed - (of-object "SugarMenu") - (c-name "sugar_menu_unembed") - (return-type "none") -) - -;; From sugar-key-grabber.h - -(define-function sugar_key_grabber_get_type - (c-name "sugar_key_grabber_get_type") - (return-type "GType") -) - -(define-method grab - (of-object "SugarKeyGrabber") - (c-name "sugar_key_grabber_grab") - (return-type "none") - (parameters - '("const-char*" "key") - ) -) - -(define-method get_key - (of-object "SugarKeyGrabber") - (c-name "sugar_key_grabber_get_key") - (return-type "char*") - (parameters - '("guint" "keycode") - '("guint" "state") - ) -) - -;; From sexy-icon-entry.h - -(define-function sexy_icon_entry_get_type - (c-name "sexy_icon_entry_get_type") - (return-type "GType") -) - -(define-function sexy_icon_entry_new - (c-name "sexy_icon_entry_new") - (is-constructor-of "SexyIconEntry") - (return-type "GtkWidget*") -) - -(define-method set_icon - (of-object "SexyIconEntry") - (c-name "sexy_icon_entry_set_icon") - (return-type "none") - (parameters - '("SexyIconEntryPosition" "position") - '("GtkImage*" "icon" (null-ok)) - ) -) - -(define-method set_icon_highlight - (of-object "SexyIconEntry") - (c-name "sexy_icon_entry_set_icon_highlight") - (return-type "none") - (parameters - '("SexyIconEntryPosition" "position") - '("gboolean" "highlight") - ) -) - -(define-method get_icon - (of-object "SexyIconEntry") - (c-name "sexy_icon_entry_get_icon") - (return-type "GtkImage*") - (parameters - '("SexyIconEntryPosition" "position") - ) -) - -(define-method get_icon_highlight - (of-object "SexyIconEntry") - (c-name "sexy_icon_entry_get_icon_highlight") - (return-type "gboolean") - (parameters - '("SexyIconEntryPosition" "position") - ) -) - -(define-method add_clear_button - (of-object "SexyIconEntry") - (c-name "sexy_icon_entry_add_clear_button") - (return-type "none") -) - -;; From sugar-preview.h - -(define-function sugar_preview_get_type - (c-name "sugar_preview_get_type") - (return-type "GType") -) - -(define-method take_screenshot - (of-object "SugarPreview") - (c-name "sugar_preview_take_screenshot") - (return-type "none") - (parameters - '("GdkDrawable" "drawable") - ) -) - -(define-method set_size - (of-object "SugarPreview") - (c-name "sugar_preview_set_size") - (return-type "none") - (parameters - '("int" "width") - '("int" "height") - ) -) - -(define-method clear - (of-object "SugarPreview") - (c-name "sugar_preview_clear") - (return-type "none") -) - -(define-method get_pixbuf - (of-object "SugarPreview") - (c-name "sugar_preview_get_pixbuf") - (return-type "GdkPixbuf*") -) diff --git a/lib/sugar/_sugarext.override b/lib/sugar/_sugarext.override deleted file mode 100644 index 61fb815..0000000 --- a/lib/sugar/_sugarext.override +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4 -*- */ -%% -headers -#include - -#include "pygobject.h" -#include "sugar-address-entry.h" -#include "sugar-key-grabber.h" -#include "sugar-menu.h" -#include "sugar-preview.h" -#include "sexy-icon-entry.h" - -#include -#include - -%% -modulename _sugarext -%% -import gobject.GObject as PyGObject_Type -import gtk.Entry as PyGtkEntry_Type -import gtk.Menu as PyGtkMenu_Type -import gtk.Container as PyGtkContainer_Type -import gtk.gdk.Window as PyGdkWindow_Type -import gtk.gdk.Drawable as PyGdkDrawable_Type -import gtk.Image as PyGtkImage_Type -%% -ignore-glob - *_get_type - _* -%% diff --git a/lib/sugar/_sugarextmodule.c b/lib/sugar/_sugarextmodule.c deleted file mode 100644 index 6f6af6d..0000000 --- a/lib/sugar/_sugarextmodule.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2006-2007, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* include this first, before NO_IMPORT_PYGOBJECT is defined */ -#include - -extern PyMethodDef py_sugarext_functions[]; - -void py_sugarext_register_classes (PyObject *d); -void py_sugarext_add_constants (PyObject *module, const gchar *strip_prefix); - -DL_EXPORT(void) -init_sugarext(void) -{ - PyObject *m, *d; - - init_pygobject (); - - m = Py_InitModule ("_sugarext", py_sugarext_functions); - d = PyModule_GetDict (m); - - py_sugarext_register_classes (d); - py_sugarext_add_constants(m, "SEXY_"); - - if (PyErr_Occurred ()) { - Py_FatalError ("can't initialise module _sugarext"); - } -} diff --git a/lib/sugar/activity/Makefile.am b/lib/sugar/activity/Makefile.am deleted file mode 100644 index 9dfc8de..0000000 --- a/lib/sugar/activity/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -sugardir = $(pythondir)/sugar/activity -sugar_PYTHON = \ - __init__.py \ - activity.py \ - activityfactory.py \ - activityhandle.py \ - activityservice.py \ - bundlebuilder.py \ - registry.py diff --git a/lib/sugar/activity/__init__.py b/lib/sugar/activity/__init__.py deleted file mode 100644 index 8a984ad..0000000 --- a/lib/sugar/activity/__init__.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -"""Activity implementation code for Sugar-based activities - -Each activity within the OLPC environment must provide two -dbus services. The first, patterned after the - - sugar.activity.activityfactory.ActivityFactory - -class is responsible for providing a "create" method which -takes a small dictionary with values corresponding to a - - sugar.activity.activityhandle.ActivityHandle - -describing an individual instance of the activity. - -Each activity so registered is described by a - - sugar.activity.bundle.Bundle - -instance, which parses a specially formatted activity.info -file (stored in the activity directory's ./activity -subdirectory). The - - sugar.activity.bundlebuilder - -module provides facilities for the standard setup.py module -which produces and registers bundles from activity source -directories. - -Once instantiated by the ActivityFactory's create method, -each activity must provide an introspection API patterned -after the - - sugar.activity.activityservice.ActivityService - -class. This class allows for querying the ID of the root -window, requesting sharing across the network, and basic -"what type of application are you" queries. -""" -from sugar.activity.registry import ActivityRegistry -from sugar.activity.registry import get_registry -from sugar.activity.registry import ActivityInfo diff --git a/lib/sugar/activity/__init__py b/lib/sugar/activity/__init__py deleted file mode 100644 index e69de29..0000000 --- a/lib/sugar/activity/__init__py +++ /dev/null diff --git a/lib/sugar/activity/activity.py b/lib/sugar/activity/activity.py deleted file mode 100644 index 9d87e9e..0000000 --- a/lib/sugar/activity/activity.py +++ /dev/null @@ -1,933 +0,0 @@ -"""Base class for activities written in Python - -This is currently the only definitive reference for what an -activity must do to participate in the Sugar desktop. - - A Basic Activity - -All activities must implement a class derived from 'Activity' in this class. -The convention is to call it ActivitynameActivity, but this is not required as -the activity.info file associated with your activity will tell the sugar-shell -which class to start. - -For example the most minimal Activity: - - - from sugar.activity import activity - - class ReadActivity(activity.Activity): - pass - -To get a real, working activity, you will at least have to implement: - __init__(), read_file() and write_file() - -Aditionally, you will probably need a at least a Toolbar so you can have some -interesting buttons for the user, like for example 'exit activity' - -See the methods of the Activity class below for more information on what you -will need for a real activity. -""" -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -from gettext import gettext as _ -import logging -import os -import time -import tempfile -from hashlib import sha1 -import traceback - -import gtk, gobject -import dbus -import dbus.service -import json - -from sugar import util -from sugar.presence import presenceservice -from sugar.activity.activityservice import ActivityService -from sugar.graphics import style -from sugar.graphics.window import Window -from sugar.graphics.toolbox import Toolbox -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.toolcombobox import ToolComboBox -from sugar.graphics.alert import Alert -from sugar.graphics.icon import Icon -from sugar.datastore import datastore -from sugar import wm -from sugar import profile -from sugar import _sugarbaseext -from sugar import _sugarext - -SCOPE_PRIVATE = "private" -SCOPE_INVITE_ONLY = "invite" # shouldn't be shown in UI, it's implicit when you invite somebody -SCOPE_NEIGHBORHOOD = "public" - -J_DBUS_SERVICE = 'org.laptop.Journal' -J_DBUS_PATH = '/org/laptop/Journal' -J_DBUS_INTERFACE = 'org.laptop.Journal' - -class ActivityToolbar(gtk.Toolbar): - """The Activity toolbar with the Journal entry title, sharing, Keep and Stop buttons - - All activities should have this toolbar. It is easiest to add it to your - Activity by using the ActivityToolbox. - """ - def __init__(self, activity): - gtk.Toolbar.__init__(self) - - self._activity = activity - self._updating_share = False - - activity.connect('shared', self.__activity_shared_cb) - activity.connect('joined', self.__activity_shared_cb) - activity.connect('notify::max_participants', - self.__max_participants_changed_cb) - - if activity.metadata: - self.title = gtk.Entry() - self.title.set_size_request(int(gtk.gdk.screen_width() / 6), -1) - self.title.set_text(activity.metadata['title']) - self.title.connect('changed', self.__title_changed_cb) - self._add_widget(self.title) - - activity.metadata.connect('updated', self.__jobject_updated_cb) - - separator = gtk.SeparatorToolItem() - separator.props.draw = False - separator.set_expand(True) - self.insert(separator, -1) - separator.show() - - self.share = ToolComboBox(label_text=_('Share with:')) - self.share.combo.connect('changed', self.__share_changed_cb) - self.share.combo.append_item(SCOPE_PRIVATE, _('Private'), 'zoom-home') - self.share.combo.append_item(SCOPE_NEIGHBORHOOD, _('My Neighborhood'), - 'zoom-neighborhood') - self.insert(self.share, -1) - self.share.show() - - self._update_share() - - self.keep = ToolButton('document-save') - self.keep.set_tooltip(_('Keep')) - self.keep.connect('clicked', self.__keep_clicked_cb) - self.insert(self.keep, -1) - self.keep.show() - - self.stop = ToolButton('activity-stop') - self.stop.set_tooltip(_('Stop')) - self.stop.connect('clicked', self.__stop_clicked_cb) - self.insert(self.stop, -1) - self.stop.show() - - self._update_title_sid = None - - def _update_share(self): - self._updating_share = True - - if self._activity.props.max_participants == 1: - self.share.hide() - - if self._activity.get_shared(): - self.share.set_sensitive(False) - self.share.combo.set_active(1) - else: - self.share.set_sensitive(True) - self.share.combo.set_active(0) - - self._updating_share = False - - def __share_changed_cb(self, combo): - if self._updating_share: - return - - model = self.share.combo.get_model() - it = self.share.combo.get_active_iter() - (scope, ) = model.get(it, 0) - if scope == SCOPE_NEIGHBORHOOD: - self._activity.share() - - def __keep_clicked_cb(self, button): - self._activity.copy() - - def __stop_clicked_cb(self, button): - self._activity.take_screenshot() - self._activity.close() - - def __jobject_updated_cb(self, jobject): - self.title.set_text(jobject['title']) - - def __title_changed_cb(self, entry): - if not self._update_title_sid: - self._update_title_sid = gobject.timeout_add(1000, self.__update_title_cb) - - def __update_title_cb(self): - title = self.title.get_text() - - self._activity.metadata['title'] = title - self._activity.metadata['title_set_by_user'] = '1' - self._activity.save() - - shared_activity = self._activity._shared_activity - if shared_activity: - shared_activity.props.name = title - - self._update_title_sid = None - return False - - def _add_widget(self, widget, expand=False): - tool_item = gtk.ToolItem() - tool_item.set_expand(expand) - - tool_item.add(widget) - widget.show() - - self.insert(tool_item, -1) - tool_item.show() - - def __activity_shared_cb(self, activity): - self._update_share() - - def __max_participants_changed_cb(self, activity, pspec): - self._update_share() - -class EditToolbar(gtk.Toolbar): - """Provides the standard edit toolbar for Activities. - - Members: - undo -- the undo button - redo -- the redo button - copy -- the copy button - paste -- the paste button - separator -- A separator between undo/redo and copy/paste - - This class only provides the 'edit' buttons in a standard layout, your activity - will need to either hide buttons which make no sense for your Activity, or you - need to connect the button events to your own callbacks: - - ## Example from Read.activity: - # Create the edit toolbar: - self._edit_toolbar = EditToolbar(self._view) - # Hide undo and redo, they're not needed - self._edit_toolbar.undo.props.visible = False - self._edit_toolbar.redo.props.visible = False - # Hide the separator too: - self._edit_toolbar.separator.props.visible = False - - # As long as nothing is selected, copy needs to be insensitive: - self._edit_toolbar.copy.set_sensitive(False) - # When the user clicks the button, call _edit_toolbar_copy_cb() - self._edit_toolbar.copy.connect('clicked', self._edit_toolbar_copy_cb) - - # Add the edit toolbar: - toolbox.add_toolbar(_('Edit'), self._edit_toolbar) - # And make it visible: - self._edit_toolbar.show() - """ - def __init__(self): - gtk.Toolbar.__init__(self) - - self.undo = ToolButton('edit-undo') - self.undo.set_tooltip(_('Undo')) - self.insert(self.undo, -1) - self.undo.show() - - self.redo = ToolButton('edit-redo') - self.redo.set_tooltip(_('Redo')) - self.insert(self.redo, -1) - self.redo.show() - - self.separator = gtk.SeparatorToolItem() - self.separator.set_draw(True) - self.insert(self.separator, -1) - self.separator.show() - - self.copy = ToolButton('edit-copy') - self.copy.set_tooltip(_('Copy')) - self.insert(self.copy, -1) - self.copy.show() - - self.paste = ToolButton('edit-paste') - self.paste.set_tooltip(_('Paste')) - self.insert(self.paste, -1) - self.paste.show() - -class ActivityToolbox(Toolbox): - """Creates the Toolbox for the Activity - - By default, the toolbox contains only the ActivityToolbar. After creating the - toolbox, you can add your activity specific toolbars, for example the - EditToolbar. - - To add the ActivityToolbox to your Activity in MyActivity.__init__() do: - - # Create the Toolbar with the ActivityToolbar: - toolbox = activity.ActivityToolbox(self) - ... your code, inserting all other toolbars you need, like EditToolbar ... - - # Add the toolbox to the activity frame: - self.set_toolbox(toolbox) - # And make it visible: - toolbox.show() - """ - def __init__(self, activity): - Toolbox.__init__(self) - - self._activity_toolbar = ActivityToolbar(activity) - self.add_toolbar('Activity', self._activity_toolbar) - self._activity_toolbar.show() - - def get_activity_toolbar(self): - return self._activity_toolbar - -class Activity(Window, gtk.Container): - """This is the base Activity class that all other Activities derive from. This is where your activity starts. - - To get a working Activity: - 0. Derive your Activity from this class: - class MyActivity(activity.Activity): - ... - - 1. implement an __init__() method for your Activity class. - - Use your init method to create your own ActivityToolbar which will - contain some standard buttons: - toolbox = activity.ActivityToolbox(self) - - Add extra Toolbars to your toolbox. - - You should setup Activity sharing here too. - - Finaly, your Activity may need some resources which you can claim - here too. - - The __init__() method is also used to make the distinction between - being resumed from the Journal, or starting with a blank document. - - 2. Implement read_file() and write_file() - Most activities revolve around creating and storing Journal entries. - For example, Write: You create a document, it is saved to the Journal - and then later you resume working on the document. - - read_file() and write_file() will be called by sugar to tell your - Activity that it should load or save the document the user is working - on. - - 3. Implement our Activity Toolbars. - The Toolbars are added to your Activity in step 1 (the toolbox), but - you need to implement them somewhere. Now is a good time. - - There are a number of standard Toolbars. The most basic one, the one - your almost absolutely MUST have is the ActivityToolbar. Without - this, you're not really making a proper Sugar Activity (which may be - okay, but you should really stop and think about why not!) You do - this with the ActivityToolbox(self) call in step 1. - - Usually, you will also need the standard EditToolbar. This is the one - which has the standard copy and paste buttons. You need to derive - your own EditToolbar class from sugar.EditToolbar: - class EditToolbar(activity.EditToolbar): - ... - - See EditToolbar for the methods you should implement in your class. - - Finaly, your Activity will very likely need some activity specific - buttons and options you can create your own toolbars by deriving a - class from gtk.Toolbar: - class MySpecialToolbar(gtk.Toolbar): - ... - - 4. Use your creativity. Make your Activity something special and share - it with your friends! - - Read through the methods of the Activity class below, to learn more about - how to make an Activity work. - - Hint: A good and simple Activity to learn from is the Read activity. To - create your own activity, you may want to copy it and use it as a template. - """ - __gtype_name__ = 'SugarActivity' - - __gsignals__ = { - 'shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - 'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) - } - - __gproperties__ = { - 'active' : (bool, None, None, False, - gobject.PARAM_READWRITE), - 'max-participants': (int, None, None, 0, 1000, 0, - gobject.PARAM_READWRITE) - } - - def __init__(self, handle, create_jobject=True): - """Initialise the Activity - - handle -- sugar.activity.activityhandle.ActivityHandle - instance providing the activity id and access to the - presence service which *may* provide sharing for this - application - - create_jobject -- boolean - define if it should create a journal object if we are - not resuming - - Side effects: - - Sets the gdk screen DPI setting (resolution) to the - Sugar screen resolution. - - Connects our "destroy" message to our _destroy_cb - method. - - Creates a base gtk.Window within this window. - - Creates an ActivityService (self._bus) servicing - this application. - - Usage: - If your Activity implements __init__(), it should call - the base class __init()__ before doing Activity specific things. - - """ - Window.__init__(self) - - # process titles will only show 15 characters - # but they get truncated anyway so if more characters - # are supported in the future we will get a better view - # of the processes - proc_title = "%s <%s>" % (get_bundle_name(), handle.activity_id) - util.set_proc_title(proc_title) - - self.connect('realize', self.__realize_cb) - self.connect('delete-event', self.__delete_event_cb) - self.connect("key_press_event", self.__key_press_event_cb) - - self._active = False - self._activity_id = handle.activity_id - self._pservice = presenceservice.get_instance() - self._shared_activity = None - self._share_id = None - self._join_id = None - self._preview = _sugarext.Preview() - self._updating_jobject = False - self._closing = False - self._deleting = False - self._max_participants = 0 - self._invites_queue = [] - - self._bus = ActivityService(self) - self._owns_file = False - - share_scope = SCOPE_PRIVATE - - if handle.object_id: - self._jobject = datastore.get(handle.object_id) - # TODO: Don't create so many objects until we have versioning - # support in the datastore - #self._jobject.object_id = '' - #del self._jobject.metadata['ctime'] - del self._jobject.metadata['mtime'] - - self.set_title(self._jobject.metadata['title']) - - if self._jobject.metadata.has_key('share-scope'): - share_scope = self._jobject.metadata['share-scope'] - - elif create_jobject: - logging.debug('Creating a jobject.') - self._jobject = datastore.create() - self._jobject.metadata['title'] = _('%s Activity') % get_bundle_name() - self.set_title(self._jobject.metadata['title']) - self._jobject.metadata['title_set_by_user'] = '0' - self._jobject.metadata['activity'] = self.get_bundle_id() - self._jobject.metadata['activity_id'] = self.get_id() - self._jobject.metadata['keep'] = '0' - self._jobject.metadata['preview'] = '' - self._jobject.metadata['share-scope'] = SCOPE_PRIVATE - - if self._shared_activity is not None: - icon_color = self._shared_activity.props.color - else: - icon_color = profile.get_color().to_string() - - self._jobject.metadata['icon-color'] = icon_color - - self._jobject.file_path = '' - # Cannot call datastore.write async for creates: https://dev.laptop.org/ticket/3071 - datastore.write(self._jobject) - else: - self._jobject = None - - # handle activity share/join - mesh_instance = self._pservice.get_activity(self._activity_id, - warn_if_none=False) - logging.debug("*** Act %s, mesh instance %r, scope %s", - self._activity_id, mesh_instance, share_scope) - if mesh_instance is not None: - # There's already an instance on the mesh, join it - logging.debug("*** Act %s joining existing mesh instance %r", self._activity_id, mesh_instance) - self._shared_activity = mesh_instance - self._shared_activity.connect('notify::private', - self.__privacy_changed_cb) - self._join_id = self._shared_activity.connect("joined", self.__joined_cb) - if not self._shared_activity.props.joined: - self._shared_activity.join() - else: - self.__joined_cb(self._shared_activity, True, None) - elif share_scope != SCOPE_PRIVATE: - logging.debug("*** Act %s no existing mesh instance, but used to be shared, will share" % self._activity_id) - # no existing mesh instance, but activity used to be shared, so - # restart the share - if share_scope == SCOPE_INVITE_ONLY: - self.share(private=True) - elif share_scope == SCOPE_NEIGHBORHOOD: - self.share(private=False) - else: - logging.debug("Unknown share scope %r" % share_scope) - - def do_set_property(self, pspec, value): - if pspec.name == 'active': - if self._active != value: - self._active = value - if not self._active and self._jobject: - self.save() - elif pspec.name == 'max-participants': - self._max_participants = value - else: - Window.do_set_property(self, pspec, value) - - def do_get_property(self, pspec): - if pspec.name == 'active': - return self._active - elif pspec.name == 'max-participants': - return self._max_participants - else: - return Window.do_get_property(self, pspec) - - def get_id(self): - """Returns the activity id of the current instance of your activity. - - The activity id is sort-of-like the unix process id (PID). However, - unlike PIDs it is only different for each new instance (with - create_jobject = True set) and stays the same everytime a user - resumes an activity. This is also the identity of your Activity to other - XOs for use when sharing. - """ - return self._activity_id - - def get_bundle_id(self): - """Returns the bundle_id from the activity.info file""" - return os.environ['SUGAR_BUNDLE_ID'] - - def set_canvas(self, canvas): - """Sets the 'work area' of your activity with the canvas of your choice. - - One commonly used canvas is gtk.ScrolledWindow - """ - Window.set_canvas(self, canvas) - canvas.connect('map', self.__canvas_map_cb) - - def __canvas_map_cb(self, canvas): - if self._jobject and self._jobject.file_path: - self.read_file(self._jobject.file_path) - - def __jobject_create_cb(self): - pass - - def __jobject_error_cb(self, err): - logging.debug("Error creating activity datastore object: %s" % err) - - def get_activity_root(self): - """ FIXME: Deprecated. This part of the API has been moved - out of this class to the module itself - - Returns a path for saving Activity specific preferences, etc. - - Returns a path to the location in the filesystem where the activity can - store activity related data that doesn't pertain to the current - execution of the activity and thus cannot go into the DataStore. - - Currently, this will return something like ~/.sugar/default/MyActivityName/ - - Activities should ONLY save settings, user preferences and other data - which isn't specific to a journal item here. If (meta-)data is in anyway - specific to a journal entry, it MUST be stored in the DataStore. - """ - if os.environ.has_key('SUGAR_ACTIVITY_ROOT') and \ - os.environ['SUGAR_ACTIVITY_ROOT']: - return os.environ['SUGAR_ACTIVITY_ROOT'] - else: - return '/' - - def read_file(self, file_path): - """ - Subclasses implement this method if they support resuming objects from - the journal. 'file_path' is the file to read from. - - You should immediately open the file from the file_path, because the - file_name will be deleted immediately after returning from read_file(). - Once the file has been opened, you do not have to read it immediately: - After you have opened it, the file will only be really gone when you - close it. - - Although not required, this is also a good time to read all meta-data: - the file itself cannot be changed externally, but the title, description - and other metadata['tags'] may change. So if it is important for you to - notice changes, this is the time to record the originals. - """ - raise NotImplementedError - - def write_file(self, file_path): - """ - Subclasses implement this method if they support saving data to objects - in the journal. 'file_path' is the file to write to. - - If the user did make changes, you should create the file_path and save - all document data to it. - - Additionally, you should also write any metadata needed to resume your - activity. For example, the Read activity saves the current page and zoom - level, so it can display the page. - - Note: Currently, the file_path *WILL* be different from the one you - received in file_read(). Even if you kept the file_path from file_read() - open until now, you must still write the entire file to this file_path. - """ - raise NotImplementedError - - def __save_cb(self): - logging.debug('Activity.__save_cb') - self._updating_jobject = False - if self._closing: - self._cleanup_jobject() - self.destroy() - - def __save_error_cb(self, err): - logging.debug('Activity.__save_error_cb') - self._updating_jobject = False - if self._closing: - self._cleanup_jobject() - self.destroy() - logging.debug("Error saving activity object to datastore: %s" % err) - - def _cleanup_jobject(self): - if self._jobject: - if self._owns_file and os.path.isfile(self._jobject.file_path): - logging.debug('_cleanup_jobject: removing %r' % self._jobject.file_path) - os.remove(self._jobject.file_path) - self._owns_file = False - self._jobject.destroy() - self._jobject = None - - def _get_preview(self): - pixbuf = self._preview.get_pixbuf() - if pixbuf is None: - return None - - pixbuf = pixbuf.scale_simple(style.zoom(300), style.zoom(225), - gtk.gdk.INTERP_BILINEAR) - - # TODO: Find a way of taking a png out of the pixbuf without saving - # to a temp file. Impementing gtk.gdk.Pixbuf.save_to_buffer in pygtk - # would solve this. - fd, file_path = tempfile.mkstemp('.png') - del fd - - pixbuf.save(file_path, 'png') - f = open(file_path) - try: - preview_data = f.read() - finally: - f.close() - os.remove(file_path) - - self._preview.clear() - - return preview_data - - def _get_buddies(self): - if self._shared_activity is not None: - buddies = {} - for buddy in self._shared_activity.get_joined_buddies(): - if not buddy.props.owner: - buddy_id = sha1(buddy.props.key).hexdigest() - buddies[buddy_id] = [buddy.props.nick, buddy.props.color] - return buddies - else: - return {} - - def take_screenshot(self): - if self.canvas and self.canvas.window: - self._preview.take_screenshot(self.canvas.window) - - def save(self): - """Request that the activity is saved to the Journal. - - This method is called by the close() method below. In general, - activities should not override this method. This method is part of the - public API of an Acivity, and should behave in standard ways. Use your - own implementation of write_file() to save your Activity specific data. - """ - - logging.debug('Activity.save: %r' % self._jobject.object_id) - - if self._updating_jobject: - logging.info('Activity.save: still processing a previous request.') - return - - buddies_dict = self._get_buddies() - if buddies_dict: - self.metadata['buddies_id'] = json.write(buddies_dict.keys()) - self.metadata['buddies'] = json.write(self._get_buddies()) - - preview = self._get_preview() - if self._preview: - self.metadata['preview'] = dbus.ByteArray(preview) - - try: - file_path = os.path.join(self.get_activity_root(), 'instance', - '%i' % time.time()) - self.write_file(file_path) - self._owns_file = True - self._jobject.file_path = file_path - except NotImplementedError: - pass - - # Cannot call datastore.write async for creates: https://dev.laptop.org/ticket/3071 - if self._jobject.object_id is None: - datastore.write(self._jobject, transfer_ownership=True) - else: - self._updating_jobject = True - datastore.write(self._jobject, - transfer_ownership=True, - reply_handler=self.__save_cb, - error_handler=self.__save_error_cb) - - def copy(self): - """Request that the activity 'Keep in Journal' the current state of the activity. - - Activities should not override this method. Instead, like save() do any - copy work that needs to be done in write_file() - """ - logging.debug('Activity.copy: %r' % self._jobject.object_id) - self.save() - self._jobject.object_id = None - - def __privacy_changed_cb(self, shared_activity, param_spec): - if shared_activity.props.private: - self._jobject.metadata['share-scope'] = SCOPE_INVITE_ONLY - else: - self._jobject.metadata['share-scope'] = SCOPE_NEIGHBORHOOD - - def __joined_cb(self, activity, success, err): - """Callback when join has finished""" - self._shared_activity.disconnect(self._join_id) - self._join_id = None - if not success: - logging.debug("Failed to join activity: %s" % err) - return - - self.present() - self.emit('joined') - self.__privacy_changed_cb(self._shared_activity, None) - - def get_shared(self): - """Returns TRUE if the activity is shared on the mesh.""" - if not self._shared_activity: - return False - return self._shared_activity.props.joined - - def __share_cb(self, ps, success, activity, err): - self._pservice.disconnect(self._share_id) - self._share_id = None - if not success: - logging.debug('Share of activity %s failed: %s.' % (self._activity_id, err)) - return - - logging.debug('Share of activity %s successful, PS activity is %r.', - self._activity_id, activity) - - activity.props.name = self._jobject.metadata['title'] - - self._shared_activity = activity - self._shared_activity.connect('notify::private', - self.__privacy_changed_cb) - self.emit('shared') - self.__privacy_changed_cb(self._shared_activity, None) - - self._send_invites() - - def _invite_response_cb(self, error): - if error: - logging.error('Invite failed: %s' % error) - - def _send_invites(self): - while self._invites_queue: - buddy_key = self._invites_queue.pop() - buddy = self._pservice.get_buddy(buddy_key) - if buddy: - self._shared_activity.invite(buddy, '', self._invite_response_cb) - else: - logging.error('Cannot invite %s, no such buddy.' % buddy_key) - - def invite(self, buddy_key): - """Invite a buddy to join this Activity. - - Side Effects: - Calls self.share(True) to privately share the activity if it wasn't - shared before. - """ - self._invites_queue.append(buddy_key) - - if (self._shared_activity is None - or not self._shared_activity.props.joined): - self.share(True) - else: - self._send_invites() - - def share(self, private=False): - """Request that the activity be shared on the network. - - private -- bool: True to share by invitation only, - False to advertise as shared to everyone. - - Once the activity is shared, its privacy can be changed by setting - its 'private' property. - """ - if self._shared_activity and self._shared_activity.props.joined: - raise RuntimeError("Activity %s already shared." % - self._activity_id) - verb = private and 'private' or 'public' - logging.debug('Requesting %s share of activity %s.' % - (verb, self._activity_id)) - self._share_id = self._pservice.connect("activity-shared", - self.__share_cb) - self._pservice.share_activity(self, private=private) - - def _display_keep_failed_dialog(self): - alert = Alert() - alert.props.title = _('Keep error') - alert.props.msg = _('Keep error: all changes will be lost') - - cancel_icon = Icon(icon_name='dialog-cancel') - alert.add_button(gtk.RESPONSE_CANCEL, _('Don\'t stop'), cancel_icon) - - stop_icon = Icon(icon_name='dialog-ok') - alert.add_button(gtk.RESPONSE_OK, _('Stop anyway'), stop_icon) - - self.add_alert(alert) - alert.connect('response', self._keep_failed_dialog_response_cb) - - def _keep_failed_dialog_response_cb(self, alert, response_id): - self.remove_alert(alert) - if response_id == gtk.RESPONSE_OK: - self.close(skip_save=True) - - def can_close(self): - """Activities should override this function if they want to perform - extra checks before actually closing.""" - - return True - - def close(self, force=False, skip_save=False): - """Request that the activity be stopped and saved to the Journal - - Activities should not override this method, but should implement write_file() to - do any state saving instead. If the application wants to control wether it can - close, it should override can_close(). - """ - - if not force: - if not self.can_close(): - return - - try: - if not skip_save: - self.save() - except: - logging.info(traceback.format_exc()) - self._display_keep_failed_dialog() - return - - if self._shared_activity: - self._shared_activity.leave() - - if self._updating_jobject: - self._closing = True - else: - self.destroy() - - # Make the exported object inaccessible - dbus.service.Object.remove_from_connection(self._bus) - - def __realize_cb(self, window): - wm.set_bundle_id(window.window, self.get_bundle_id()) - wm.set_activity_id(window.window, str(self._activity_id)) - - def __delete_event_cb(self, widget, event): - self.close() - return True - - def get_metadata(self): - """Returns the jobject metadata or None if there is no jobject. - - Activities can set metadata in write_file() using: - self.metadata['MyKey'] = "Something" - - and retrieve metadata in read_file() using: - self.metadata.get('MyKey', 'aDefaultValue') - - Note: Make sure your activity works properly if one or more of the - metadata items is missing. Never assume they will all be present. - """ - if self._jobject: - return self._jobject.metadata - else: - return None - - metadata = property(get_metadata, None) - - def __key_press_event_cb(self, widget, event): - key = gtk.gdk.keyval_name(event.keyval) - if key == 's' and (event.state & gtk.gdk.CONTROL_MASK): - logging.debug('Keep requested') - self.copy() - return True - -def get_bundle_name(): - """Return the bundle name for the current process' bundle""" - return os.environ['SUGAR_BUNDLE_NAME'] - -def get_bundle_path(): - """Return the bundle path for the current process' bundle""" - return os.environ['SUGAR_BUNDLE_PATH'] - -def get_activity_root(): - """Returns a path for saving Activity specific preferences, etc.""" - if os.environ.has_key('SUGAR_ACTIVITY_ROOT') and \ - os.environ['SUGAR_ACTIVITY_ROOT']: - return os.environ['SUGAR_ACTIVITY_ROOT'] - else: - raise RuntimeError("No SUGAR_ACTIVITY_ROOT set.") - -def show_object_in_journal(object_id): - bus = dbus.SessionBus() - obj = bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH) - journal = dbus.Interface(obj, J_DBUS_INTERFACE) - journal.ShowObject(object_id) diff --git a/lib/sugar/activity/activityfactory.py b/lib/sugar/activity/activityfactory.py deleted file mode 100644 index 1638197..0000000 --- a/lib/sugar/activity/activityfactory.py +++ /dev/null @@ -1,316 +0,0 @@ -"""Shell side object which manages request to start activity""" -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging -import subprocess -import signal - -import dbus -import gobject - -from sugar.presence import presenceservice -from sugar.activity.activityhandle import ActivityHandle -from sugar.activity import registry -from sugar import util -from sugar import env - -from errno import EEXIST - -import os - -# #3903 - this constant can be removed and assumed to be 1 when dbus-python -# 0.82.3 is the only version used -if dbus.version >= (0, 82, 3): - DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND = 1 -else: - DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND = 1000 - -_SHELL_SERVICE = "org.laptop.Shell" -_SHELL_PATH = "/org/laptop/Shell" -_SHELL_IFACE = "org.laptop.Shell" - -_DS_SERVICE = "org.laptop.sugar.DataStore" -_DS_INTERFACE = "org.laptop.sugar.DataStore" -_DS_PATH = "/org/laptop/sugar/DataStore" - -_ACTIVITY_FACTORY_INTERFACE = "org.laptop.ActivityFactory" - -_RAINBOW_SERVICE_NAME = "org.laptop.security.Rainbow" -_RAINBOW_ACTIVITY_FACTORY_PATH = "/" -_RAINBOW_ACTIVITY_FACTORY_INTERFACE = "org.laptop.security.Rainbow" - -_children_pid = [] - -def _sigchild_handler(signum, frame): - for child_pid in _children_pid: - pid, status = os.waitpid(child_pid, os.WNOHANG) - if pid > 0: - _children_pid.remove(pid) - -signal.signal(signal.SIGCHLD, _sigchild_handler) - -def create_activity_id(): - """Generate a new, unique ID for this activity""" - pservice = presenceservice.get_instance() - - # create a new unique activity ID - i = 0 - act_id = None - while i < 10: - act_id = util.unique_id() - i += 1 - - # check through network activities - found = False - activities = pservice.get_activities() - for act in activities: - if act_id == act.props.id: - found = True - break - if not found: - return act_id - raise RuntimeError("Cannot generate unique activity id.") - -def get_environment(activity): - environ = os.environ.copy() - - bin_path = os.path.join(activity.path, 'bin') - - activity_root = env.get_profile_path(activity.bundle_id) - if not os.path.exists(activity_root): - os.mkdir(activity_root) - - data_dir = os.path.join(activity_root, 'instance') - if not os.path.exists(data_dir): - os.mkdir(data_dir) - - data_dir = os.path.join(activity_root, 'data') - if not os.path.exists(data_dir): - os.mkdir(data_dir) - - tmp_dir = os.path.join(activity_root, 'tmp') - if not os.path.exists(tmp_dir): - os.mkdir(tmp_dir) - - environ['SUGAR_BUNDLE_PATH'] = activity.path - environ['SUGAR_BUNDLE_ID'] = activity.bundle_id - environ['SUGAR_ACTIVITY_ROOT'] = activity_root - environ['PATH'] = bin_path + ':' + environ['PATH'] - #environ['RAINBOW_STRACE_LOG'] = '1' - - if activity.bundle_id in [ 'org.laptop.WebActivity', - 'org.laptop.GmailActivity', - 'org.laptop.WikiBrowseActivity' - ]: - environ['RAINBOW_CONSTANT_UID'] = 'yes' - - return environ - -def get_command(activity, activity_id=None, object_id=None, uri=None): - if not activity_id: - activity_id = create_activity_id() - - command = activity.command.split(' ') - command.extend(['-b', activity.bundle_id]) - command.extend(['-a', activity_id]) - - if object_id is not None: - command.extend(['-o', object_id]) - if uri is not None: - command.extend(['-u', uri]) - - print command - - return command - -def open_log_file(activity): - i = 1 - while True: - path = env.get_logs_path('%s-%s.log' % (activity.bundle_id, i)) - try: - fd = os.open(path, os.O_EXCL | os.O_CREAT \ - | os.O_SYNC | os.O_WRONLY, 0644) - f = os.fdopen(fd, 'w', 0) - return (path, f) - except OSError, e: - if e.errno == EEXIST: - i += 1 - else: - raise e - -class ActivityCreationHandler(gobject.GObject): - """Sugar-side activity creation interface - - This object uses a dbus method on the ActivityFactory - service to create the new activity. It generates - GObject events in response to the success/failure of - activity startup using callbacks to the service's - create call. - """ - - def __init__(self, service_name, handle): - """Initialise the handler - - service_name -- the service name of the bundle factory - activity_handle -- stores the values which are to - be passed to the service to uniquely identify - the activity to be created and the sharing - service that may or may not be connected with it - - sugar.activity.activityhandle.ActivityHandle instance - - calls the "create" method on the service for this - particular activity type and registers the - _reply_handler and _error_handler methods on that - call's results. - - The specific service which creates new instances of this - particular type of activity is created during the activity - registration process in shell bundle registry which creates - service definition files for each registered bundle type. - - If the file '/etc/olpc-security' exists, then activity launching - will be delegated to the prototype 'Rainbow' security service. - """ - gobject.GObject.__init__(self) - - self._service_name = service_name - self._handle = handle - - self._use_rainbow = os.path.exists('/etc/olpc-security') - if service_name in [ 'org.laptop.JournalActivity', - 'org.laptop.Terminal', - 'org.laptop.LogViewer', - 'org.laptop.Analyze' - ]: - self._use_rainbow = False - - bus = dbus.SessionBus() - - bus_object = bus.get_object(_SHELL_SERVICE, _SHELL_PATH) - self._shell = dbus.Interface(bus_object, _SHELL_IFACE) - - if handle.activity_id is not None and \ - handle.object_id is None: - datastore = dbus.Interface( - bus.get_object(_DS_SERVICE, _DS_PATH), _DS_INTERFACE) - datastore.find({ 'activity_id': self._handle.activity_id }, [], - reply_handler=self._find_object_reply_handler, - error_handler=self._find_object_error_handler) - else: - self._launch_activity() - - def _launch_activity(self): - if self._handle.activity_id != None: - self._shell.ActivateActivity(self._handle.activity_id, - reply_handler=self._activate_reply_handler, - error_handler=self._activate_error_handler) - else: - self._create_activity() - - def _create_activity(self): - if self._handle.activity_id is None: - self._handle.activity_id = create_activity_id() - - self._shell.NotifyLaunch( - self._service_name, self._handle.activity_id, - reply_handler=self._no_reply_handler, - error_handler=self._notify_launch_error_handler) - - activity_registry = registry.get_registry() - activity = activity_registry.get_activity(self._service_name) - if activity: - environ = get_environment(activity) - (log_path, log_file) = open_log_file(activity) - command = get_command(activity, self._handle.activity_id, - self._handle.object_id, - self._handle.uri) - - if not self._use_rainbow: - p = subprocess.Popen(command, env=environ, cwd=activity.path, - stdout=log_file, stderr=log_file) - _children_pid.append(p.pid) - else: - log_file.close() - system_bus = dbus.SystemBus() - factory = system_bus.get_object(_RAINBOW_SERVICE_NAME, - _RAINBOW_ACTIVITY_FACTORY_PATH) - factory.CreateActivity( - log_path, - environ, - command, - environ['SUGAR_BUNDLE_PATH'], - environ['SUGAR_BUNDLE_ID'], - timeout=30 * DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND, - reply_handler=self._create_reply_handler, - error_handler=self._create_error_handler, - dbus_interface=_RAINBOW_ACTIVITY_FACTORY_INTERFACE) - - def _no_reply_handler(self, *args): - pass - - def _notify_launch_failure_error_handler(self, err): - logging.error('Notify launch failure failed %s' % err) - - def _notify_launch_error_handler(self, err): - logging.debug('Notify launch failed %s' % err) - - def _activate_reply_handler(self, activated): - if not activated: - self._create_activity() - - def _activate_error_handler(self, err): - logging.error("Activity activation request failed %s" % err) - - def _create_reply_handler(self): - logging.debug("Activity created %s (%s)." % - (self._handle.activity_id, self._service_name)) - - def _create_error_handler(self, err): - logging.error("Couldn't create activity %s (%s): %s" % - (self._handle.activity_id, self._service_name, err)) - self._shell.NotifyLaunchFailure( - self._handle.activity_id, reply_handler=self._no_reply_handler, - error_handler=self._notify_launch_failure_error_handler) - - def _find_object_reply_handler(self, jobjects, count): - if count > 0: - if count > 1: - logging.debug("Multiple objects has the same activity_id.") - self._handle.object_id = jobjects[0]['uid'] - self._create_activity() - - def _find_object_error_handler(self, err): - logging.error("Datastore find failed %s" % err) - self._create_activity() - -def create(service_name, activity_handle=None): - """Create a new activity from its name.""" - if not activity_handle: - activity_handle = ActivityHandle() - return ActivityCreationHandler(service_name, activity_handle) - -def create_with_uri(service_name, uri): - """Create a new activity and pass the uri as handle.""" - activity_handle = ActivityHandle(uri=uri) - return ActivityCreationHandler(service_name, activity_handle) - -def create_with_object_id(service_name, object_id): - """Create a new activity and pass the object id as handle.""" - activity_handle = ActivityHandle(object_id=object_id) - return ActivityCreationHandler(service_name, activity_handle) diff --git a/lib/sugar/activity/activityhandle.py b/lib/sugar/activity/activityhandle.py deleted file mode 100644 index f91651e..0000000 --- a/lib/sugar/activity/activityhandle.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -from sugar.presence import presenceservice - -class ActivityHandle(object): - """Data structure storing simple activity metadata""" - def __init__( - self, activity_id=None, object_id=None, uri=None - ): - """Initialise the handle from activity_id - - activity_id -- unique id for the activity to be - created - object_id -- identity of the journal object - associated with the activity. It was used by - the journal prototype implementation, might - change when we do the real one. - - When you resume an activity from the journal - the object_id will be passed in. It's optional - since new activities does not have an - associated object (yet). - - XXX Not clear how this relates to the activity - id yet, i.e. not sure we really need both. TBF - uri -- URI associated with the activity. Used when - opening an external file or resource in the - activity, rather than a journal object - (downloads stored on the file system for - example or web pages) - """ - self.activity_id = activity_id - self.object_id = object_id - self.uri = uri - - def get_dict(self): - """Retrieve our settings as a dictionary""" - result = { 'activity_id' : self.activity_id } - if self.object_id: - result['object_id'] = self.object_id - if self.uri: - result['uri'] = self.uri - - return result - -def create_from_dict(handle_dict): - """Create a handle from a dictionary of parameters""" - result = ActivityHandle( - handle_dict['activity_id'], - object_id = handle_dict.get('object_id'), - uri = handle_dict.get('uri'), - ) - return result diff --git a/lib/sugar/activity/activityservice.py b/lib/sugar/activity/activityservice.py deleted file mode 100644 index c884fcb..0000000 --- a/lib/sugar/activity/activityservice.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging - -import dbus -import dbus.service - -_ACTIVITY_SERVICE_NAME = "org.laptop.Activity" -_ACTIVITY_SERVICE_PATH = "/org/laptop/Activity" -_ACTIVITY_INTERFACE = "org.laptop.Activity" - -class ActivityService(dbus.service.Object): - """Base dbus service object that each Activity uses to export dbus methods. - - The dbus service is separate from the actual Activity object so that we can - tightly control what stuff passes through the dbus python bindings.""" - - def __init__(self, activity): - """Initialise the service for the given activity - - activity -- sugar.activity.activity.Activity instance - - Creates dbus services that use the instance's activity_id - as discriminants among all active services - of this type. That is, the services are all available - as names/paths derived from the instance's activity_id. - - The various methods exposed on dbus are just forwarded - to the client Activity object's equally-named methods. - """ - activity.realize() - - activity_id = activity.get_id() - service_name = _ACTIVITY_SERVICE_NAME + activity_id - object_path = _ACTIVITY_SERVICE_PATH + "/" + activity_id - - bus = dbus.SessionBus() - bus_name = dbus.service.BusName(service_name, bus=bus) - dbus.service.Object.__init__(self, bus_name, object_path) - - self._activity = activity - - @dbus.service.method(_ACTIVITY_INTERFACE) - def SetActive(self, active): - logging.debug('ActivityService.set_active: %s.' % active) - self._activity.props.active = active - - @dbus.service.method(_ACTIVITY_INTERFACE) - def Invite(self, buddy_key): - self._activity.invite(buddy_key) - - @dbus.service.method(_ACTIVITY_INTERFACE) - def TakeScreenshot(self): - self._activity.take_screenshot() - diff --git a/lib/sugar/activity/bundlebuilder.py b/lib/sugar/activity/bundlebuilder.py deleted file mode 100644 index e992557..0000000 --- a/lib/sugar/activity/bundlebuilder.py +++ /dev/null @@ -1,382 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import sys -import os -import zipfile -import shutil -import subprocess -import re -import gettext - -from sugar import env -from sugar.bundle.activitybundle import ActivityBundle - -class _SvnFileList(list): - def __init__(self): - f = os.popen('svn list -R') - for line in f.readlines(): - filename = line.strip() - if os.path.isfile(filename): - self.append(filename) - f.close() - -class _GitFileList(list): - def __init__(self): - f = os.popen('git-ls-files') - for line in f.readlines(): - filename = line.strip() - if not filename.startswith('.'): - self.append(filename) - f.close() - -class _DefaultFileList(list): - def __init__(self): - for name in os.listdir('activity'): - if name.endswith('.svg'): - self.append(os.path.join('activity', name)) - - self.append('activity/activity.info') - - if os.path.isfile(_get_source_path('NEWS')): - self.append('NEWS') - -class _ManifestFileList(_DefaultFileList): - def __init__(self, manifest): - _DefaultFileList.__init__(self) - self.append(manifest) - - f = open(manifest,'r') - for line in f.readlines(): - stripped_line = line.strip() - if stripped_line and not stripped_line in self: - self.append(stripped_line) - f.close() - -def _extract_bundle(source_file, dest_dir): - if not os.path.exists(dest_dir): - os.mkdir(dest_dir) - - zf = zipfile.ZipFile(source_file) - - for i, name in enumerate(zf.namelist()): - path = os.path.join(dest_dir, name) - - if not os.path.exists(os.path.dirname(path)): - os.makedirs(os.path.dirname(path)) - - outfile = open(path, 'wb') - outfile.write(zf.read(name)) - outfile.flush() - outfile.close() - -def _get_source_path(path=None): - if path: - return os.path.join(os.getcwd(), path) - else: - return os.getcwd() - -def _get_bundle_dir(): - bundle_name = os.path.basename(_get_source_path()) - return bundle_name + '.activity' - -def _get_install_dir(prefix): - return os.path.join(prefix, 'share/activities') - -def _get_package_name(bundle_name): - bundle = ActivityBundle(_get_source_path()) - zipname = '%s-%d.xo' % (bundle_name, bundle.get_activity_version()) - return zipname - -def _delete_backups(arg, dirname, names): - for name in names: - if name.endswith('~') or name.endswith('pyc'): - os.remove(os.path.join(dirname, name)) - -def _get_bundle_id(): - bundle = ActivityBundle(_get_source_path()) - return bundle.get_bundle_id() - -def cmd_help(): - print 'Usage: \n\ -setup.py dev - setup for development \n\ -setup.py dist - create a bundle package \n\ -setup.py install [dirname] - install the bundle \n\ -setup.py uninstall [dirname] - uninstall the bundle \n\ -setup.py genpot - generate the gettext pot file \n\ -setup.py genl10n - generate localization files \n\ -setup.py clean - clean the directory \n\ -setup.py release - do a new release of the bundle \n\ -setup.py help - print this message \n\ -' - -def cmd_dev(): - bundle_path = env.get_user_activities_path() - if not os.path.isdir(bundle_path): - os.mkdir(bundle_path) - bundle_path = os.path.join(bundle_path, _get_bundle_dir()) - try: - os.symlink(_get_source_path(), bundle_path) - except OSError: - if os.path.islink(bundle_path): - print 'ERROR - The bundle has been already setup for development.' - else: - print 'ERROR - A bundle with the same name is already installed.' - -def _get_file_list(manifest): - if os.path.isfile(manifest): - return _ManifestFileList(manifest) - elif os.path.isdir('.git'): - return _GitFileList() - elif os.path.isdir('.svn'): - return _SvnFileList() - else: - return _DefaultFileList() - -def _get_po_list(manifest): - file_list = {} - - po_regex = re.compile("po/(.*)\.po$") - for file_name in _get_file_list(manifest): - match = po_regex.match(file_name) - if match: - file_list[match.group(1)] = file_name - - return file_list - -def _get_l10n_list(manifest): - l10n_list = [] - - for lang in _get_po_list(manifest).keys(): - filename = _get_bundle_id() + '.mo' - l10n_list.append(os.path.join('locale', lang, 'LC_MESSAGES', filename)) - l10n_list.append(os.path.join('locale', lang, 'activity.linfo')) - - return l10n_list - -def _get_activity_name(): - info_path = os.path.join(_get_source_path(), 'activity', 'activity.info') - f = open(info_path,'r') - info = f.read() - f.close() - match = re.search('^name\s*=\s*(.*)$', info, flags = re.MULTILINE) - return match.group(1) - -def cmd_dist(bundle_name, manifest): - cmd_genl10n(bundle_name, manifest) - file_list = _get_file_list(manifest) - - zipname = _get_package_name(bundle_name) - bundle_zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) - base_dir = bundle_name + '.activity' - - for filename in file_list: - bundle_zip.write(filename, os.path.join(base_dir, filename)) - - for filename in _get_l10n_list(manifest): - bundle_zip.write(filename, os.path.join(base_dir, filename)) - - bundle_zip.close() - -def cmd_install(bundle_name, manifest, prefix): - cmd_dist(bundle_name, manifest) - cmd_uninstall(prefix) - - _extract_bundle(_get_package_name(bundle_name), - _get_install_dir(prefix)) - -def cmd_uninstall(prefix): - path = os.path.join(_get_install_dir(prefix), _get_bundle_dir()) - if os.path.isdir(path): - shutil.rmtree(path) - -def cmd_genpot(bundle_name, manifest): - po_path = os.path.join(_get_source_path(), 'po') - if not os.path.isdir(po_path): - os.mkdir(po_path) - - python_files = [] - file_list = _get_file_list(manifest) - for file_name in file_list: - if file_name.endswith('.py'): - python_files.append(file_name) - - # First write out a stub .pot file containing just the translated - # activity name, then have xgettext merge the rest of the - # translations into that. (We can't just append the activity name - # to the end of the .pot file afterwards, because that might - # create a duplicate msgid.) - pot_file = os.path.join('po', '%s.pot' % bundle_name) - activity_name = _get_activity_name() - escaped_name = re.sub('([\\\\"])', '\\\\\\1', activity_name) - f = open(pot_file, 'w') - f.write('#: activity/activity.info:2\n') - f.write('msgid "%s"\n' % escaped_name) - f.write('msgstr ""\n') - f.close() - - args = [ 'xgettext', '--join-existing', '--language=Python', - '--keyword=_', '--add-comments=TRANS:', '--output=%s' % pot_file ] - - args += python_files - retcode = subprocess.call(args) - if retcode: - print 'ERROR - xgettext failed with return code %i.' % retcode - - -def cmd_genl10n(bundle_name, manifest): - source_path = _get_source_path() - activity_name = _get_activity_name() - - po_list = _get_po_list(manifest) - for lang in po_list.keys(): - file_name = po_list[lang] - - localedir = os.path.join(source_path, 'locale', lang) - mo_path = os.path.join(localedir, 'LC_MESSAGES') - if not os.path.isdir(mo_path): - os.makedirs(mo_path) - - mo_file = os.path.join(mo_path, "%s.mo" % _get_bundle_id()) - args = ["msgfmt", "--output-file=%s" % mo_file, file_name] - retcode = subprocess.call(args) - if retcode: - print 'ERROR - msgfmt failed with return code %i.' % retcode - - cat = gettext.GNUTranslations(open(mo_file, 'r')) - translated_name = cat.gettext(activity_name) - linfo_file = os.path.join(localedir, 'activity.linfo') - f = open(linfo_file, 'w') - f.write('[Activity]\nname = %s\n' % translated_name) - f.close() - -def cmd_release(bundle_name, manifest): - if not os.path.isdir('.git'): - print 'ERROR - this command works only for git repositories' - - retcode = subprocess.call(['git', 'pull']) - if retcode: - print 'ERROR - cannot pull from git' - - print 'Bumping activity version...' - - info_path = os.path.join(_get_source_path(), 'activity', 'activity.info') - f = open(info_path,'r') - info = f.read() - f.close() - - exp = re.compile('activity_version\s?=\s?([0-9]*)') - match = re.search(exp, info) - version = int(match.group(1)) + 1 - info = re.sub(exp, 'activity_version = %d' % version, info) - - f = open(info_path, 'w') - f.write(info) - f.close() - - news_path = os.path.join(_get_source_path(), 'NEWS') - - if os.environ.has_key('SUGAR_NEWS'): - print 'Update NEWS.sugar...' - - sugar_news_path = os.environ['SUGAR_NEWS'] - if os.path.isfile(sugar_news_path): - f = open(sugar_news_path,'r') - sugar_news = f.read() - f.close() - else: - sugar_news = '' - - sugar_news += '%s - %d\n\n' % (bundle_name, version) - - f = open(news_path,'r') - for line in f.readlines(): - if len(line.strip()) > 0: - sugar_news += line - else: - break - f.close() - - sugar_news += '\n' - - f = open(sugar_news_path, 'w') - f.write(sugar_news) - f.close() - - print 'Update NEWS...' - - f = open(news_path,'r') - news = f.read() - f.close() - - news = '%d\n\n' % version + news - - f = open(news_path, 'w') - f.write(news) - f.close() - - print 'Committing to git...' - - changelog = 'Release version %d.' % version - retcode = subprocess.call(['git', 'commit', '-a', '-m % s' % changelog]) - if retcode: - print 'ERROR - cannot commit to git' - - retcode = subprocess.call(['git', 'push']) - if retcode: - print 'ERROR - cannot push to git' - - print 'Creating the bundle...' - cmd_dist(bundle_name, manifest) - - print 'Done.' - -def cmd_clean(): - os.path.walk('.', _delete_backups, None) - -def sanity_check(): - if not os.path.isfile(_get_source_path('NEWS')): - print 'WARNING: NEWS file is missing.' - -def start(bundle_name, manifest='MANIFEST'): - sanity_check() - - if len(sys.argv) < 2: - cmd_help() - elif sys.argv[1] == 'build': - pass - elif sys.argv[1] == 'dev': - cmd_dev() - elif sys.argv[1] == 'dist': - cmd_dist(bundle_name, manifest) - elif sys.argv[1] == 'install' and len(sys.argv) == 3: - cmd_install(bundle_name, manifest, sys.argv[2]) - elif sys.argv[1] == 'uninstall' and len(sys.argv) == 3: - cmd_uninstall(sys.argv[2]) - elif sys.argv[1] == 'genpot': - cmd_genpot(bundle_name, manifest) - elif sys.argv[1] == 'genl10n': - cmd_genl10n(bundle_name, manifest) - elif sys.argv[1] == 'clean': - cmd_clean() - elif sys.argv[1] == 'release': - cmd_release(bundle_name, manifest) - else: - cmd_help() - -if __name__ == '__main__': - start() diff --git a/lib/sugar/activity/registry.py b/lib/sugar/activity/registry.py deleted file mode 100644 index ac672d5..0000000 --- a/lib/sugar/activity/registry.py +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# Copyright (C) 2007 One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging - -import dbus -import gobject - -_ACTIVITY_REGISTRY_SERVICE_NAME = 'org.laptop.ActivityRegistry' -_ACTIVITY_REGISTRY_IFACE = 'org.laptop.ActivityRegistry' -_ACTIVITY_REGISTRY_PATH = '/org/laptop/ActivityRegistry' - -def _activity_info_from_dict(info_dict): - if not info_dict: - return None - return ActivityInfo(info_dict['name'], info_dict['icon'], - info_dict['bundle_id'], info_dict['version'], - info_dict['path'], info_dict['show_launcher'], - info_dict['command']) - -class ActivityInfo(object): - def __init__(self, name, icon, bundle_id, version, - path, show_launcher, command): - self.name = name - self.icon = icon - self.bundle_id = bundle_id - self.version = version - self.path = path - self.command = command - self.show_launcher = show_launcher - -class ActivityRegistry(gobject.GObject): - __gsignals__ = { - 'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) - } - def __init__(self): - gobject.GObject.__init__(self) - - bus = dbus.SessionBus() - - # NOTE: We need to follow_name_owner_changes here - # because we can not connect to a signal unless - # we follow the changes or we start the service - # before we connect. Starting the service here - # causes a major bottleneck during startup - bus_object = bus.get_object(_ACTIVITY_REGISTRY_SERVICE_NAME, - _ACTIVITY_REGISTRY_PATH, - follow_name_owner_changes = True) - self._registry = dbus.Interface(bus_object, _ACTIVITY_REGISTRY_IFACE) - self._registry.connect_to_signal('ActivityAdded', self._activity_added_cb) - self._registry.connect_to_signal('ActivityRemoved', self._activity_removed_cb) - - # Two caches fo saving some travel across dbus. - self._service_name_to_activity_info = {} - self._mime_type_to_activities = {} - - def _convert_info_list(self, info_list): - result = [] - - for info_dict in info_list: - result.append(_activity_info_from_dict(info_dict)) - - return result - - def get_activities(self): - info_list = self._registry.GetActivities() - return self._convert_info_list(info_list) - - def _get_activities_cb(self, reply_handler, info_list): - result = [] - i = 0 - for info_dict in info_list: - result.append(_activity_info_from_dict(info_dict)) - - reply_handler(result) - - def _get_activities_error_cb(self, error_handler, e): - if error_handler: - error_handler(e) - else: - logging.error('Error getting activities async: %s' % str(e)) - - def get_activities_async(self, reply_handler=None, error_handler=None): - if not reply_handler: - logging.error('Function get_activities_async called without a reply handler. Can not run.') - return - - self._registry.GetActivities( - reply_handler=lambda info_list:self._get_activities_cb(reply_handler, info_list), - error_handler=lambda e:self._get_activities_error_cb(error_handler, e)) - - def get_activity(self, service_name): - if self._service_name_to_activity_info.has_key(service_name): - return self._service_name_to_activity_info[service_name] - - info_dict = self._registry.GetActivity(service_name) - activity_info = _activity_info_from_dict(info_dict) - - self._service_name_to_activity_info[service_name] = activity_info - return activity_info - - def find_activity(self, name): - info_list = self._registry.FindActivity(name) - return self._convert_info_list(info_list) - - def get_activities_for_type(self, mime_type): - if self._mime_type_to_activities.has_key(mime_type): - return self._mime_type_to_activities[mime_type] - - info_list = self._registry.GetActivitiesForType(mime_type) - activities = self._convert_info_list(info_list) - - self._mime_type_to_activities[mime_type] = activities - return activities - - def add_bundle(self, bundle_path): - result = self._registry.AddBundle(bundle_path) - # Need to invalidate here because get_activity could be called after - # add_bundle and before we receive activity-added, causing a race. - self._invalidate_cache() - return result - - def _activity_added_cb(self, info_dict): - logging.debug('ActivityRegistry._activity_added_cb: invalidating cache') - self._invalidate_cache() - self.emit('activity-added', _activity_info_from_dict(info_dict)) - - def _invalidate_cache(self): - self._service_name_to_activity_info.clear() - self._mime_type_to_activities.clear() - - def remove_bundle(self, bundle_path): - self._service_name_to_activity_info.clear() - self._mime_type_to_activities.clear() - return self._registry.RemoveBundle(bundle_path) - - def _activity_removed_cb(self, info_dict): - logging.debug('ActivityRegistry._activity_removed_cb: flushing caches') - self._service_name_to_activity_info.clear() - self._mime_type_to_activities.clear() - self.emit('activity-removed', _activity_info_from_dict(info_dict)) - -_registry = None - -def get_registry(): - global _registry - if not _registry: - _registry = ActivityRegistry() - return _registry diff --git a/lib/sugar/bundle/Makefile.am b/lib/sugar/bundle/Makefile.am deleted file mode 100644 index f1af791..0000000 --- a/lib/sugar/bundle/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pythondir)/sugar/bundle -sugar_PYTHON = \ - __init__.py \ - bundle.py \ - activitybundle.py \ - contentbundle.py diff --git a/lib/sugar/bundle/__init__.py b/lib/sugar/bundle/__init__.py deleted file mode 100644 index 85ebced..0000000 --- a/lib/sugar/bundle/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. diff --git a/lib/sugar/bundle/activitybundle.py b/lib/sugar/bundle/activitybundle.py deleted file mode 100644 index ee72f80..0000000 --- a/lib/sugar/bundle/activitybundle.py +++ /dev/null @@ -1,321 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -"""Sugar activity bundles""" - -from ConfigParser import ConfigParser -import locale -import os -import tempfile - -from sugar.bundle.bundle import Bundle, MalformedBundleException, \ - AlreadyInstalledException, RegistrationException, \ - NotInstalledException - -from sugar import activity -from sugar import env - -import logging - -class ActivityBundle(Bundle): - """A Sugar activity bundle - - See http://wiki.laptop.org/go/Activity_bundles for details - """ - - MIME_TYPE = 'application/vnd.olpc-sugar' - DEPRECATED_MIME_TYPE = 'application/vnd.olpc-x-sugar' - - _zipped_extension = '.xo' - _unzipped_extension = '.activity' - _infodir = 'activity' - - def __init__(self, path): - Bundle.__init__(self, path) - self.activity_class = None - self.bundle_exec = None - - self._name = None - self._icon = None - self._bundle_id = None - self._mime_types = None - self._show_launcher = True - self._activity_version = 0 - - info_file = self._get_file('activity/activity.info') - if info_file is None: - raise MalformedBundleException('No activity.info file') - self._parse_info(info_file) - - linfo_file = self._get_linfo_file() - if linfo_file: - self._parse_linfo(linfo_file) - - def _parse_info(self, info_file): - cp = ConfigParser() - cp.readfp(info_file) - - section = 'Activity' - - if cp.has_option(section, 'bundle_id'): - self._bundle_id = cp.get(section, 'bundle_id') - # FIXME deprecated - elif cp.has_option(section, 'service_name'): - self._bundle_id = cp.get(section, 'service_name') - else: - raise MalformedBundleException( - 'Activity bundle %s does not specify a bundle id' % - self._path) - - if cp.has_option(section, 'name'): - self._name = cp.get(section, 'name') - else: - raise MalformedBundleException( - 'Activity bundle %s does not specify a name' % self._path) - - # FIXME class is deprecated - if cp.has_option(section, 'class'): - self.activity_class = cp.get(section, 'class') - elif cp.has_option(section, 'exec'): - self.bundle_exec = cp.get(section, 'exec') - else: - raise MalformedBundleException( - 'Activity bundle %s must specify either class or exec' % - self._path) - - if cp.has_option(section, 'mime_types'): - mime_list = cp.get(section, 'mime_types').strip(';') - self._mime_types = [ mime.strip() for mime in mime_list.split(';') ] - - if cp.has_option(section, 'show_launcher'): - if cp.get(section, 'show_launcher') == 'no': - self._show_launcher = False - - if cp.has_option(section, 'icon'): - self._icon = cp.get(section, 'icon') - - if cp.has_option(section, 'activity_version'): - version = cp.get(section, 'activity_version') - try: - self._activity_version = int(version) - except ValueError: - raise MalformedBundleException( - 'Activity bundle %s has invalid version number %s' % - (self._path, version)) - - def _get_linfo_file(self): - lang = locale.getdefaultlocale()[0] - if not lang: - return None - - linfo_path = os.path.join('locale', lang, 'activity.linfo') - linfo_file = self._get_file(linfo_path) - if linfo_file is not None: - return linfo_file - - linfo_path = os.path.join('locale', lang[:2], 'activity.linfo') - linfo_file = self._get_file(linfo_path) - if linfo_file is not None: - return linfo_file - - return None - - def _parse_linfo(self, linfo_file): - cp = ConfigParser() - cp.readfp(linfo_file) - - section = 'Activity' - - if cp.has_option(section, 'name'): - self._name = cp.get(section, 'name') - - def get_locale_path(self): - """Get the locale path inside the (installed) activity bundle.""" - if not self._unpacked: - raise NotInstalledException - return os.path.join(self._path, 'locale') - - def get_icons_path(self): - """Get the icons path inside the (installed) activity bundle.""" - if not self._unpacked: - raise NotInstalledException - return os.path.join(self._path, 'icons') - - def get_path(self): - """Get the activity bundle path.""" - return self._path - - def get_name(self): - """Get the activity user visible name.""" - return self._name - - def get_bundle_id(self): - """Get the activity bundle id""" - return self._bundle_id - - # FIXME: this should return the icon data, not a filename, so that - # we don't need to create a temp file in the zip case - def get_icon(self): - """Get the activity icon name""" - icon_path = os.path.join('activity', self._icon + '.svg') - if self._unpacked: - return os.path.join(self._path, icon_path) - else: - icon_data = self._get_file(icon_path).read() - temp_file, temp_file_path = tempfile.mkstemp(self._icon) - os.write(temp_file, icon_data) - os.close(temp_file) - return temp_file_path - - def get_activity_version(self): - """Get the activity version""" - return self._activity_version - - def get_command(self): - """Get the command to execute to launch the activity factory""" - if self.bundle_exec: - command = os.path.expandvars(self.bundle_exec) - else: - command = 'sugar-activity ' + self.activity_class - - return command - - - def get_mime_types(self): - """Get the MIME types supported by the activity""" - return self._mime_types - - def get_show_launcher(self): - """Get whether there should be a visible launcher for the activity""" - return self._show_launcher - - def is_installed(self): - if activity.get_registry().get_activity(self._bundle_id): - return True - else: - return False - - def need_upgrade(self): - act = activity.get_registry().get_activity(self._bundle_id) - if act is None or act.version != self._activity_version: - return True - else: - return False - - def install(self): - act = activity.get_registry().get_activity(self._bundle_id) - if act is not None and act.path.startswith(env.get_user_activities_path()): - raise AlreadyInstalledException - - install_dir = env.get_user_activities_path() - self._unzip(install_dir) - - install_path = os.path.join(install_dir, self._zip_root_dir) - - xdg_data_home = os.getenv('XDG_DATA_HOME', os.path.expanduser('~/.local/share')) - - mime_path = os.path.join(install_path, 'activity', 'mimetypes.xml') - if os.path.isfile(mime_path): - mime_dir = os.path.join(xdg_data_home, 'mime') - mime_pkg_dir = os.path.join(mime_dir, 'packages') - if not os.path.isdir(mime_pkg_dir): - os.makedirs(mime_pkg_dir) - installed_mime_path = os.path.join(mime_pkg_dir, '%s.xml' % self._bundle_id) - os.symlink(mime_path, installed_mime_path) - os.spawnlp(os.P_WAIT, 'update-mime-database', - 'update-mime-database', mime_dir) - - mime_types = self.get_mime_types() - if mime_types is not None: - installed_icons_dir = os.path.join(xdg_data_home, - 'icons/sugar/scalable/mimetypes') - if not os.path.isdir(installed_icons_dir): - os.makedirs(installed_icons_dir) - - for mime_type in mime_types: - mime_icon_base = os.path.join(install_path, 'activity', - mime_type.replace('/', '-')) - svg_file = mime_icon_base + '.svg' - info_file = mime_icon_base + '.icon' - if os.path.isfile(svg_file): - os.symlink(svg_file, - os.path.join(installed_icons_dir, - os.path.basename(svg_file))) - if os.path.isfile(info_file): - os.symlink(info_file, - os.path.join(installed_icons_dir, - os.path.basename(info_file))) - - if not activity.get_registry().add_bundle(install_path): - raise RegistrationException - - def uninstall(self, force=False): - if self._unpacked: - install_path = self._path - else: - if not self.is_installed(): - raise NotInstalledException - - act = activity.get_registry().get_activity(self._bundle_id) - if not force and act.version != self._activity_version: - logging.warning('Not uninstalling because different bundle present') - return - elif not act.path.startswith(env.get_user_activities_path()): - logging.warning('Not uninstalling system activity') - return - - install_path = os.path.join(env.get_user_activities_path(), - self._zip_root_dir) - - xdg_data_home = os.getenv('XDG_DATA_HOME', os.path.expanduser('~/.local/share')) - - mime_dir = os.path.join(xdg_data_home, 'mime') - installed_mime_path = os.path.join(mime_dir, 'packages', '%s.xml' % self._bundle_id) - if os.path.exists(installed_mime_path): - os.remove(installed_mime_path) - os.spawnlp(os.P_WAIT, 'update-mime-database', - 'update-mime-database', mime_dir) - - mime_types = self.get_mime_types() - if mime_types is not None: - installed_icons_dir = os.path.join(xdg_data_home, - 'icons/sugar/scalable/mimetypes') - for file in os.listdir(installed_icons_dir): - path = os.path.join(installed_icons_dir, file) - if os.path.islink(path) and \ - os.readlink(path).startswith(install_path): - os.remove(path) - - self._uninstall(install_path) - - if not activity.get_registry().remove_bundle(install_path): - raise RegistrationException - - def upgrade(self): - act = activity.get_registry().get_activity(self._bundle_id) - if act is None: - logging.warning('Activity not installed') - elif act.path.startswith(env.get_user_activities_path()): - try: - self.uninstall(force=True) - except Exception, e: - logging.warning('Uninstall failed (%s), still trying to install newer bundle', e) - else: - logging.warning('Unable to uninstall system activity, installing upgraded version in user activities') - - self.install() - diff --git a/lib/sugar/bundle/bundle.py b/lib/sugar/bundle/bundle.py deleted file mode 100644 index f7f18c9..0000000 --- a/lib/sugar/bundle/bundle.py +++ /dev/null @@ -1,146 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -"""Sugar bundle file handler""" - -import os -import StringIO -import zipfile - -class AlreadyInstalledException(Exception): pass -class NotInstalledException(Exception): pass -class InvalidPathException(Exception): pass -class ZipExtractException(Exception): pass -class RegistrationException(Exception): pass -class MalformedBundleException(Exception): pass - -class Bundle: - """A Sugar activity, content module, etc. - - The bundle itself may be either a zip file or a directory - hierarchy, with metadata about the bundle stored various files - inside it. - - This is an abstract base class. See ActivityBundle and - ContentBundle for more details on those bundle types. - """ - def __init__(self, path): - self._path = path - - if os.path.isdir(self._path): - self._unpacked = True - else: - self._unpacked = False - self._check_zip_bundle() - - # manifest = self._get_file(self._infodir + '/contents') - # if manifest is None: - # raise MalformedBundleException('No manifest file') - # - # signature = self._get_file(self._infodir + '/contents.sig') - # if signature is None: - # raise MalformedBundleException('No signature file') - - def _check_zip_bundle(self): - zip_file = zipfile.ZipFile(self._path) - file_names = zip_file.namelist() - if len(file_names) == 0: - raise MalformedBundleException('Empty zip file') - - if file_names[0] == 'mimetype': - del file_names[0] - - self._zip_root_dir = file_names[0].split('/')[0] - if self._unzipped_extension is not None: - (name, ext) = os.path.splitext(self._zip_root_dir) - if ext != self._unzipped_extension: - raise MalformedBundleException( - 'All files in the bundle must be inside a single ' + - 'directory whose name ends with "%s"' % - self._unzipped_extension) - - for file_name in file_names: - if not file_name.startswith(self._zip_root_dir): - raise MalformedBundleException( - 'All files in the bundle must be inside a single ' + - 'top-level directory') - - def _get_file(self, filename): - file = None - - if self._unpacked: - path = os.path.join(self._path, filename) - if os.path.isfile(path): - file = open(path) - else: - zip_file = zipfile.ZipFile(self._path) - path = os.path.join(self._zip_root_dir, filename) - try: - data = zip_file.read(path) - file = StringIO.StringIO(data) - except KeyError: - # == "file not found" - pass - zip_file.close() - - return file - - def get_path(self): - """Get the bundle path.""" - return self._path - - def _unzip(self, install_dir): - if self._unpacked: - raise AlreadyInstalledException - - if not os.path.isdir(install_dir): - os.mkdir(install_dir, 0775) - - # zipfile provides API that in theory would let us do this - # correctly by hand, but handling all the oddities of - # Windows/UNIX mappings, extension attributes, deprecated - # features, etc makes it impractical. - # FIXME: use manifest - if os.spawnlp(os.P_WAIT, 'unzip', 'unzip', '-o', self._path, - '-x', 'mimetype', '-d', install_dir): - raise ZipExtractException - - def _zip(self, bundle_path): - if not self._unpacked: - raise NotInstalledException - - # FIXME: use manifest - zip = zipfile.ZipFile(bundle_path, 'w', zipfile.ZIP_DEFLATED) - for root, dirs, files in os.walk(self._path): - for name in files: - zip.write(filename, os.path.join(base_dir, filename)) - zip.close() - - def _uninstall(self, install_path): - if not os.path.isdir(install_path): - raise InvalidPathException - if self._unzipped_extension is not None: - ext = os.path.splitext(install_path)[1] - if ext != self._unzipped_extension: - raise InvalidPathException - - for root, dirs, files in os.walk(install_path, topdown=False): - for name in files: - os.remove(os.path.join(root, name)) - for name in dirs: - os.rmdir(os.path.join(root, name)) - os.rmdir(install_path) diff --git a/lib/sugar/bundle/contentbundle.py b/lib/sugar/bundle/contentbundle.py deleted file mode 100644 index 9e2d36e..0000000 --- a/lib/sugar/bundle/contentbundle.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -"""Sugar content bundles""" - -from ConfigParser import ConfigParser -import os - -from sugar import env -from sugar.bundle.bundle import Bundle, NotInstalledException, \ - MalformedBundleException - -class ContentBundle(Bundle): - """A Sugar content bundle - - See http://wiki.laptop.org/go/Content_bundles for details - """ - - MIME_TYPE = 'application/vnd.olpc-content' - - _zipped_extension = '.xol' - _unzipped_extension = None - _infodir = 'library' - - def __init__(self, path): - Bundle.__init__(self, path) - - info_file = self._get_file('library/library.info') - if info_file is None: - raise MalformedBundleException('No library.info file') - self._parse_info(info_file) - - if (self._get_file('index.html') is None and - self._get_file('library/library.xml') is None): - raise MalformedBundleException( - 'Content bundle %s has neither index.html nor library.xml' % - self._path) - - def _parse_info(self, info_file): - cp = ConfigParser() - cp.readfp(info_file) - - section = 'Library' - - if cp.has_option(section, 'host_version'): - version = cp.get(section, 'host_version') - try: - if int(version) != 1: - raise MalformedBundleException( - 'Content bundle %s has unknown host_version number %s' % - (self._path, version)) - except ValueError: - raise MalformedBundleException( - 'Content bundle %s has invalid host_version number %s' % - (self._path, version)) - - if cp.has_option(section, 'name'): - self._name = cp.get(section, 'name') - else: - raise MalformedBundleException( - 'Content bundle %s does not specify a name' % self._path) - - if cp.has_option(section, 'library_version'): - version = cp.get(section, 'library_version') - try: - self._library_version = int(version) - except ValueError: - raise MalformedBundleException( - 'Content bundle %s has invalid version number %s' % - (self._path, version)) - - if cp.has_option(section, 'l10n'): - l10n = cp.get(section, 'l10n') - if l10n == 'true': - self._l10n = True - elif l10n == 'false': - self._l10n = False - else: - raise MalformedBundleException( - 'Content bundle %s has invalid l10n key "%s"' % - (self._path, l10n)) - else: - raise MalformedBundleException( - 'Content bundle %s does not specify if it is localized' % - self._path) - - if cp.has_option(section, 'locale'): - self._locale = cp.get(section, 'locale') - else: - raise MalformedBundleException( - 'Content bundle %s does not specify a locale' % self._path) - - if cp.has_option(section, 'category'): - self._category = cp.get(section, 'category') - else: - raise MalformedBundleException( - 'Content bundle %s does not specify a category' % self._path) - - if cp.has_option(section, 'category_icon'): - self._category_icon = cp.get(section, 'category_icon') - else: - self._category_icon = None - - if cp.has_option(section, 'category_class'): - self._category_class = cp.get(section, 'category_class') - else: - self._category_class = None - - if cp.has_option(section, 'subcategory'): - self._subcategory = cp.get(section, 'subcategory') - else: - self._subcategory = None - - if cp.has_option(section, 'bundle_class'): - self._bundle_class = cp.get(section, 'bundle_class') - else: - self._bundle_class = None - - def get_name(self): - return self._name - - def get_library_version(self): - return self._library_version - - def get_l10n(self): - return self._l10n - - def get_locale(self): - return self._locale - - def get_category(self): - return self._category - - def get_category(self): - return self._category - - def get_category_icon(self): - return self._category_icon - - def get_category_class(self): - return self._category_class - - def get_subcategory(self): - return self._subcategory - - def get_bundle_class(self): - return self._bundle_class - - def _run_indexer(self): - os.spawnlp(os.P_WAIT, 'python', - 'python', - env.get_prefix_path('share/library-common/make_index.py')) - - def is_installed(self): - if self._unpacked: - return True - elif os.path.isdir(os.path.join(env.get_user_library_path(), - self._zip_root_dir)): - return True - else: - return False - - def install(self): - self._unzip(env.get_user_library_path()) - self._run_indexer() - - def uninstall(self): - if self._unpacked: - if not self.is_installed(): - raise NotInstalledException - install_dir = self._path - else: - install_dir = os.path.join(env.get_user_library_path(), - self._zip_root_dir) - self._uninstall(install_dir) - self._run_indexer() diff --git a/lib/sugar/clipboard/Makefile.am b/lib/sugar/clipboard/Makefile.am deleted file mode 100644 index 0d61c29..0000000 --- a/lib/sugar/clipboard/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -sugardir = $(pythondir)/sugar/clipboard -sugar_PYTHON = \ - __init__.py \ - clipboardservice.py - diff --git a/lib/sugar/clipboard/__init__.py b/lib/sugar/clipboard/__init__.py deleted file mode 100644 index deee8dd..0000000 --- a/lib/sugar/clipboard/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Client-code's interface to the ClipboardService - -Provides a simplified API for accessing the dbus service -which coordinates clipboard operations within Sugar. -""" -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - diff --git a/lib/sugar/clipboard/clipboardservice.py b/lib/sugar/clipboard/clipboardservice.py deleted file mode 100644 index d975330..0000000 --- a/lib/sugar/clipboard/clipboardservice.py +++ /dev/null @@ -1,229 +0,0 @@ -"""UI class to access system-level clipboard object""" -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -import logging -import dbus -import gobject - -NAME_KEY = 'NAME' -PERCENT_KEY = 'PERCENT' -ICON_KEY = 'ICON' -PREVIEW_KEY = 'PREVIEW' -ACTIVITIES_KEY = 'ACTIVITIES' -FORMATS_KEY = 'FORMATS' - -TYPE_KEY = 'TYPE' -DATA_KEY = 'DATA' -ON_DISK_KEY = 'ON_DISK' - -DBUS_SERVICE = "org.laptop.Clipboard" -DBUS_INTERFACE = "org.laptop.Clipboard" -DBUS_PATH = "/org/laptop/Clipboard" - -class ClipboardService(gobject.GObject): - """GUI interfaces for the system clipboard dbus service - - This object is used to provide convenient access to the clipboard - service (see source/services/clipboard/clipboardservice.py). It - provides utility methods for adding/getting/removing objects from - the clipboard as well as generating events when such events occur. - - Meaning is source/services/clipboard/clipboardobject.py - objects when describing "objects" on the clipboard. - """ - __gsignals__ = { - 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([str, str])), - 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([str])), - 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([str, str, int, str, str, object])), - } - - def __init__(self): - """Initialise the ClipboardService instance - - If the service is not yet active in the background uses - a signal watcher to connect when the service appears. - """ - gobject.GObject.__init__(self) - - self._dbus_service = None - - bus = dbus.SessionBus() - self._nameOwnerChangedHandler = bus.add_signal_receiver( - self._name_owner_changed_cb, - signal_name="NameOwnerChanged", - dbus_interface="org.freedesktop.DBus", - arg0=DBUS_SERVICE) - - self._connected = False - # Try to register to ClipboardService, if we fail, we'll try later. - try: - self._connect_clipboard_signals() - except dbus.DBusException, exception: - logging.debug(exception) - - def _connect_clipboard_signals(self): - """Connect dbus signals to our GObject signal generating callbacks""" - bus = dbus.SessionBus() - if not self._connected: - # NOTE: We need to follow_name_owner_changes here - # because we can not connect to a signal unless - # we follow the changes or we start the service - # before we connect. Starting the service here - # causes a major bottleneck during startup - proxy_obj = bus.get_object(DBUS_SERVICE, - DBUS_PATH, - follow_name_owner_changes=True) - self._dbus_service = dbus.Interface(proxy_obj, DBUS_SERVICE) - self._dbus_service.connect_to_signal('object_added', - self._object_added_cb) - self._dbus_service.connect_to_signal('object_deleted', - self._object_deleted_cb) - self._dbus_service.connect_to_signal('object_state_changed', - self._object_state_changed_cb) - self._connected = True - - bus.remove_signal_receiver(self._nameOwnerChangedHandler) - - def _name_owner_changed_cb(self, name, old, new): - """On backend service creation, connect to the server""" - if not old and new: - # ClipboardService started up - self._connect_clipboard_signals() - - def _object_added_cb(self, object_id, name): - """Emit an object-added GObject event when dbus event arrives""" - self.emit('object-added', str(object_id), name) - - def _object_deleted_cb(self, object_id): - """Emit an object-deleted GObject event when dbus event arrives""" - self.emit('object-deleted', str(object_id)) - - def _object_state_changed_cb(self, object_id, values): - """Emit an object-state-changed GObject event when dbus event arrives - - GObject event has: - - object_id - name - percent - icon - preview - activities - - From the ClipboardObject instance which is being described. - """ - self.emit('object-state-changed', str(object_id), values[NAME_KEY], - values[PERCENT_KEY], values[ICON_KEY], values[PREVIEW_KEY], - values[ACTIVITIES_KEY]) - - def add_object(self, name): - """Add a new object to the path - - returns dbus path-name for the new object's cliboard service, - this is used for all future references to the cliboard object. - - Note: - That service is actually provided by the clipboard - service object, not the ClipboardObject - """ - return str(self._dbus_service.add_object(name)) - - def add_object_format(self, object_id, formatType, data, on_disk): - """Annotate given object on the clipboard with new information - - object_id -- dbus path as returned from add_object - formatType -- XXX what should this be? mime type? - data -- storage format for the clipped object? - on_disk -- whether the data is on-disk (non-volatile) or in - memory (volatile) - - Last three arguments are just passed directly to the - clipboardobject.Format instance on the server side. - - returns None - """ - self._dbus_service.add_object_format(dbus.ObjectPath(object_id), - formatType, - data, - on_disk) - - def delete_object(self, object_id): - """Remove the given object from the clipboard - - object_id -- dbus path as returned from add_object - """ - self._dbus_service.delete_object(dbus.ObjectPath(object_id)) - - def set_object_percent(self, object_id, percent): - """Set the "percentage" for the given clipboard object - - object_id -- dbus path as returned from add_object - percentage -- numeric value from 0 to 100 inclusive - - Object percentages which are set to 100% trigger "file-completed" - operations, see the backend ClipboardService's - _handle_file_completed method for details. - - returns None - """ - self._dbus_service.set_object_percent(dbus.ObjectPath(object_id), percent) - - def get_object(self, object_id): - """Retrieve the clipboard object structure for given object - - object_id -- dbus path as returned from add_object - - Retrieves the metadata description of a given object, but - *not* the data for the object. Use get_object_data passing - one of the values in the FORMATS_KEY value in order to - retrieve the data. - - returns dictionary with - NAME_KEY: str, - PERCENT_KEY: number, - ICON_KEY: str, - PREVIEW_KEY: XXX what is it?, - ACTIVITIES_KEY: activities that can open this object, - FORMATS_KEY: list of XXX what is it? - """ - return self._dbus_service.get_object(dbus.ObjectPath(object_id),) - - def get_object_data(self, object_id, formatType): - """Retrieve object's data in the given formatType - - object_id -- dbus path as returned from add_object - formatType -- format specifier XXX of what description - - returns dictionary with - TYPE_KEY: str, - DATA_KEY: str, - ON_DISK_KEY: bool - """ - return self._dbus_service.get_object_data(dbus.ObjectPath(object_id), - formatType, - byte_arrays=True) - -_clipboard_service = None -def get_instance(): - """Retrieve this process's interface to the clipboard service""" - global _clipboard_service - if not _clipboard_service: - _clipboard_service = ClipboardService() - return _clipboard_service diff --git a/lib/sugar/datastore/Makefile.am b/lib/sugar/datastore/Makefile.am deleted file mode 100644 index a5f16b7..0000000 --- a/lib/sugar/datastore/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -sugardir = $(pythondir)/sugar/datastore -sugar_PYTHON = \ - __init__.py \ - dbus_helpers.py \ - datastore.py diff --git a/lib/sugar/datastore/__init__.py b/lib/sugar/datastore/__init__.py deleted file mode 100644 index bdb658b..0000000 --- a/lib/sugar/datastore/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. diff --git a/lib/sugar/datastore/datastore.py b/lib/sugar/datastore/datastore.py deleted file mode 100644 index 334c866..0000000 --- a/lib/sugar/datastore/datastore.py +++ /dev/null @@ -1,323 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging -import time -from datetime import datetime -import os - -import gobject - -from sugar.datastore import dbus_helpers -from sugar import activity -from sugar.activity.activityhandle import ActivityHandle -from sugar.bundle.contentbundle import ContentBundle -from sugar.bundle.activitybundle import ActivityBundle -from sugar.bundle.contentbundle import ContentBundle -from sugar import mime - -class DSMetadata(gobject.GObject): - __gsignals__ = { - 'updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([])) - } - - def __init__(self, props=None): - gobject.GObject.__init__(self) - if not props: - self._props = {} - else: - self._props = props - - default_keys = ['activity', 'activity_id', - 'mime_type', 'title_set_by_user'] - for key in default_keys: - if not self._props.has_key(key): - self._props[key] = '' - - def __getitem__(self, key): - return self._props[key] - - def __setitem__(self, key, value): - if not self._props.has_key(key) or self._props[key] != value: - self._props[key] = value - self.emit('updated') - - def __delitem__(self, key): - del self._props[key] - - def __contains__(self, key): - return self._props.__contains__(key) - - def has_key(self, key): - return self._props.has_key(key) - - def keys(self): - return self._props.keys() - - def get_dictionary(self): - return self._props - - def copy(self): - return DSMetadata(self._props.copy()) - - def get(self, key, default=None): - if self._props.has_key(key): - return self._props[key] - else: - return default - -class DSObject(object): - def __init__(self, object_id, metadata=None, file_path=None): - self.object_id = object_id - self._metadata = metadata - self._file_path = file_path - self._destroyed = False - self._owns_file = False - - def get_metadata(self): - if self._metadata is None and not self.object_id is None: - metadata = DSMetadata(dbus_helpers.get_properties(self.object_id)) - self._metadata = metadata - return self._metadata - - def set_metadata(self, metadata): - if self._metadata != metadata: - self._metadata = metadata - - metadata = property(get_metadata, set_metadata) - - def get_file_path(self): - if self._file_path is None and not self.object_id is None: - self.set_file_path(dbus_helpers.get_filename(self.object_id)) - self._owns_file = True - return self._file_path - - def set_file_path(self, file_path): - if self._file_path != file_path: - if self._file_path and self._owns_file: - if os.path.isfile(self._file_path): - os.remove(self._file_path) - self._owns_file = False - self._file_path = file_path - - file_path = property(get_file_path, set_file_path) - - def _get_activities_for_mime(self, mime_type): - registry = activity.get_registry() - result = registry.get_activities_for_type(mime_type) - if not result: - for parent_mime in mime.get_mime_parents(mime_type): - result.extend(registry.get_activities_for_type(parent_mime)) - return result - - def get_activities(self): - activities = [] - - bundle_id = self.metadata.get('activity', '') - if bundle_id: - activity_info = activity.get_registry().get_activity(bundle_id) - if activity_info: - activities.append(activity_info) - - mime_type = self.metadata.get('mime_type', '') - if mime_type: - activities_info = self._get_activities_for_mime(mime_type) - for activity_info in activities_info: - if activity_info.bundle_id != bundle_id: - activities.append(activity_info) - - return activities - - def is_activity_bundle(self): - return self.metadata['mime_type'] in \ - [ActivityBundle.MIME_TYPE, ActivityBundle.DEPRECATED_MIME_TYPE] - - def is_content_bundle(self): - return self.metadata['mime_type'] == ContentBundle.MIME_TYPE - - def is_bundle(self): - return self.is_activity_bundle() or self.is_content_bundle() - - def resume(self, bundle_id=None): - from sugar.activity import activityfactory - - if self.is_activity_bundle(): - if bundle_id is not None: - raise ValueError('Object is a bundle, cannot be resumed as an activity.') - - logging.debug('Creating activity bundle') - bundle = ActivityBundle(self.file_path) - if not bundle.is_installed(): - logging.debug('Installing activity bundle') - bundle.install() - elif bundle.need_upgrade(): - logging.debug('Upgrading activity bundle') - bundle.upgrade() - - logging.debug('activityfactory.creating bundle with id %r', bundle.get_bundle_id()) - activityfactory.create(bundle.get_bundle_id()) - else: - if not self.get_activities() and bundle_id is None: - logging.warning('No activity can open this object, %s.' % - self.metadata.get('mime_type', None)) - return - if bundle_id is None: - bundle_id = self.get_activities()[0].bundle_id - - activity_id = self.metadata['activity_id'] - object_id = self.object_id - - if activity_id: - handle = ActivityHandle(object_id=object_id, - activity_id=activity_id) - activityfactory.create(bundle_id, handle) - else: - activityfactory.create_with_object_id(bundle_id, object_id) - - def destroy(self): - if self._destroyed: - logging.warning('This DSObject has already been destroyed!.') - import traceback;traceback.print_stack() - return - self._destroyed = True - if self._file_path and self._owns_file: - if os.path.isfile(self._file_path): - os.remove(self._file_path) - self._owns_file = False - self._file_path = None - - def __del__(self): - if not self._destroyed: - logging.warning('DSObject was deleted without cleaning up first. ' \ - 'Please call DSObject.destroy() before disposing it.') - self.destroy() - - def copy(self): - return DSObject(None, self._metadata.copy(), self._file_path) - -def get(object_id): - logging.debug('datastore.get') - metadata = dbus_helpers.get_properties(object_id) - - ds_object = DSObject(object_id, DSMetadata(metadata), None) - # TODO: register the object for updates - return ds_object - -def create(): - metadata = DSMetadata() - metadata['mtime'] = datetime.now().isoformat() - metadata['timestamp'] = int(time.time()) - return DSObject(object_id=None, metadata=metadata, file_path=None) - -def write(ds_object, update_mtime=True, transfer_ownership=False, reply_handler=None, error_handler=None, timeout=-1): - logging.debug('datastore.write') - - properties = ds_object.metadata.get_dictionary().copy() - - if update_mtime: - properties['mtime'] = datetime.now().isoformat() - properties['timestamp'] = int(time.time()) - - if ds_object._file_path is None: - file_path = '' - else: - file_path = ds_object._file_path - - # FIXME: this func will be sync for creates regardless of the handlers - # supplied. This is very bad API, need to decide what to do here. - if ds_object.object_id: - dbus_helpers.update(ds_object.object_id, - properties, - file_path, - transfer_ownership, - reply_handler=reply_handler, - error_handler=error_handler, - timeout=timeout) - else: - if reply_handler or error_handler: - logging.warning('datastore.write() cannot currently be called async' \ - ' for creates, see https://dev.laptop.org/ticket/3071') - ds_object.object_id = dbus_helpers.create(properties, - file_path, - transfer_ownership) - # TODO: register the object for updates - logging.debug('Written object %s to the datastore.' % ds_object.object_id) - -def delete(object_id): - logging.debug('datastore.delete') - dbus_helpers.delete(object_id) - -def find(query, sorting=None, limit=None, offset=None, properties=[], - reply_handler=None, error_handler=None): - - query = query.copy() - - if sorting: - query['order_by'] = sorting - if limit: - query['limit'] = limit - if offset: - query['offset'] = offset - - props_list, total_count = dbus_helpers.find(query, properties, reply_handler, error_handler) - - objects = [] - for props in props_list: - object_id = props['uid'] - del props['uid'] - - ds_object = DSObject(object_id, DSMetadata(props), None) - objects.append(ds_object) - - return objects, total_count - -def copy(jobject, mount_point): - - new_jobject = jobject.copy() - new_jobject.metadata['mountpoint'] = mount_point - - if jobject.metadata.has_key('title'): - filename = jobject.metadata['title'] - - if jobject.metadata.has_key('mime_type'): - mime_type = jobject.metadata['mime_type'] - extension = mime.get_primary_extension(mime_type) - if extension: - filename += '.' + extension - - new_jobject.metadata['suggested_filename'] = filename - - # this will cause the file be retrieved from the DS - new_jobject.file_path = jobject.file_path - - write(new_jobject) - -def mount(uri, options, timeout=-1): - return dbus_helpers.mount(uri, options, timeout=timeout) - -def unmount(mount_point_id): - dbus_helpers.unmount(mount_point_id) - -def mounts(): - return dbus_helpers.mounts() - -def complete_indexing(): - return dbus_helpers.complete_indexing() - -def get_unique_values(key): - return dbus_helpers.get_unique_values(key) diff --git a/lib/sugar/datastore/dbus_helpers.py b/lib/sugar/datastore/dbus_helpers.py deleted file mode 100644 index a5ce9c8..0000000 --- a/lib/sugar/datastore/dbus_helpers.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging - -import dbus -import dbus.glib -import gobject - -from sugar import util - -DS_DBUS_SERVICE = "org.laptop.sugar.DataStore" -DS_DBUS_INTERFACE = "org.laptop.sugar.DataStore" -DS_DBUS_PATH = "/org/laptop/sugar/DataStore" - -_data_store = None - -def _get_data_store(): - global _data_store - - if not _data_store: - _bus = dbus.SessionBus() - _data_store = dbus.Interface(_bus.get_object(DS_DBUS_SERVICE, - DS_DBUS_PATH), - DS_DBUS_INTERFACE) - return _data_store - -def create(properties, filename, transfer_ownership=False): - object_id = _get_data_store().create(dbus.Dictionary(properties), filename, - transfer_ownership) - logging.debug('dbus_helpers.create: ' + object_id) - return object_id - -def update(uid, properties, filename, transfer_ownership=False, - reply_handler=None, error_handler=None, timeout=-1): - debug_props = properties.copy() - if debug_props.has_key("preview"): - debug_props["preview"] = "" - logging.debug('dbus_helpers.update: %s, %s, %s, %s' % (uid, filename, debug_props, transfer_ownership)) - if reply_handler and error_handler: - _get_data_store().update(uid, dbus.Dictionary(properties), filename, - transfer_ownership, - reply_handler=reply_handler, - error_handler=error_handler, - timeout=timeout) - else: - _get_data_store().update(uid, dbus.Dictionary(properties), filename, transfer_ownership) - -def delete(uid): - logging.debug('dbus_helpers.delete: %r' % uid) - _get_data_store().delete(uid) - -def get_properties(uid): - logging.debug('dbus_helpers.get_properties: %s' % uid) - return _get_data_store().get_properties(uid, byte_arrays=True) - -def get_filename(uid): - filename = _get_data_store().get_filename(uid) - logging.debug('dbus_helpers.get_filename: %s, %s' % (uid, filename)) - return filename - -def find(query, properties, reply_handler, error_handler): - logging.debug('dbus_helpers.find: %r %r' % (query, properties)) - if reply_handler and error_handler: - return _get_data_store().find(query, properties, - reply_handler=reply_handler, error_handler=error_handler) - else: - return _get_data_store().find(query, properties) - -def mount(uri, options, timeout=-1): - return _get_data_store().mount(uri, options, timeout=timeout) - -def unmount(mount_point_id): - _get_data_store().unmount(mount_point_id) - -def mounts(): - return _get_data_store().mounts() - -def get_unique_values(key): - return _get_data_store().get_uniquevaluesfor(key, dbus.Dictionary({}, signature='ss')) - -def complete_indexing(): - return _get_data_store().complete_indexing() - diff --git a/lib/sugar/eggaccelerators.c b/lib/sugar/eggaccelerators.c deleted file mode 100644 index 0a39d51..0000000 --- a/lib/sugar/eggaccelerators.c +++ /dev/null @@ -1,702 +0,0 @@ -/* eggaccelerators.c - * Copyright (C) 2002 Red Hat, Inc.; Copyright 1998, 2001 Tim Janik - * Developed by Havoc Pennington, Tim Janik - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "eggaccelerators.h" - -#include -#include -#include -#include - -enum -{ - EGG_MODMAP_ENTRY_SHIFT = 0, - EGG_MODMAP_ENTRY_LOCK = 1, - EGG_MODMAP_ENTRY_CONTROL = 2, - EGG_MODMAP_ENTRY_MOD1 = 3, - EGG_MODMAP_ENTRY_MOD2 = 4, - EGG_MODMAP_ENTRY_MOD3 = 5, - EGG_MODMAP_ENTRY_MOD4 = 6, - EGG_MODMAP_ENTRY_MOD5 = 7, - EGG_MODMAP_ENTRY_LAST = 8 -}; - -#define MODMAP_ENTRY_TO_MODIFIER(x) (1 << (x)) - -typedef struct -{ - EggVirtualModifierType mapping[EGG_MODMAP_ENTRY_LAST]; - -} EggModmap; - -const EggModmap* egg_keymap_get_modmap (GdkKeymap *keymap); - -static inline gboolean -is_alt (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'a' || string[1] == 'A') && - (string[2] == 'l' || string[2] == 'L') && - (string[3] == 't' || string[3] == 'T') && - (string[4] == '>')); -} - -static inline gboolean -is_ctl (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'c' || string[1] == 'C') && - (string[2] == 't' || string[2] == 'T') && - (string[3] == 'l' || string[3] == 'L') && - (string[4] == '>')); -} - -static inline gboolean -is_modx (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'm' || string[1] == 'M') && - (string[2] == 'o' || string[2] == 'O') && - (string[3] == 'd' || string[3] == 'D') && - (string[4] >= '1' && string[4] <= '5') && - (string[5] == '>')); -} - -static inline gboolean -is_ctrl (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'c' || string[1] == 'C') && - (string[2] == 't' || string[2] == 'T') && - (string[3] == 'r' || string[3] == 'R') && - (string[4] == 'l' || string[4] == 'L') && - (string[5] == '>')); -} - -static inline gboolean -is_shft (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 's' || string[1] == 'S') && - (string[2] == 'h' || string[2] == 'H') && - (string[3] == 'f' || string[3] == 'F') && - (string[4] == 't' || string[4] == 'T') && - (string[5] == '>')); -} - -static inline gboolean -is_shift (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 's' || string[1] == 'S') && - (string[2] == 'h' || string[2] == 'H') && - (string[3] == 'i' || string[3] == 'I') && - (string[4] == 'f' || string[4] == 'F') && - (string[5] == 't' || string[5] == 'T') && - (string[6] == '>')); -} - -static inline gboolean -is_control (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'c' || string[1] == 'C') && - (string[2] == 'o' || string[2] == 'O') && - (string[3] == 'n' || string[3] == 'N') && - (string[4] == 't' || string[4] == 'T') && - (string[5] == 'r' || string[5] == 'R') && - (string[6] == 'o' || string[6] == 'O') && - (string[7] == 'l' || string[7] == 'L') && - (string[8] == '>')); -} - -static inline gboolean -is_release (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'r' || string[1] == 'R') && - (string[2] == 'e' || string[2] == 'E') && - (string[3] == 'l' || string[3] == 'L') && - (string[4] == 'e' || string[4] == 'E') && - (string[5] == 'a' || string[5] == 'A') && - (string[6] == 's' || string[6] == 'S') && - (string[7] == 'e' || string[7] == 'E') && - (string[8] == '>')); -} - -static inline gboolean -is_meta (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'm' || string[1] == 'M') && - (string[2] == 'e' || string[2] == 'E') && - (string[3] == 't' || string[3] == 'T') && - (string[4] == 'a' || string[4] == 'A') && - (string[5] == '>')); -} - -static inline gboolean -is_super (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 's' || string[1] == 'S') && - (string[2] == 'u' || string[2] == 'U') && - (string[3] == 'p' || string[3] == 'P') && - (string[4] == 'e' || string[4] == 'E') && - (string[5] == 'r' || string[5] == 'R') && - (string[6] == '>')); -} - -static inline gboolean -is_hyper (const gchar *string) -{ - return ((string[0] == '<') && - (string[1] == 'h' || string[1] == 'H') && - (string[2] == 'y' || string[2] == 'Y') && - (string[3] == 'p' || string[3] == 'P') && - (string[4] == 'e' || string[4] == 'E') && - (string[5] == 'r' || string[5] == 'R') && - (string[6] == '>')); -} - -static inline gboolean -is_keycode (const gchar *string) -{ - return ((string[0] == '0') && - (string[1] == 'x')); -} - -/** - * egg_accelerator_parse_virtual: - * @accelerator: string representing an accelerator - * @accelerator_key: return location for accelerator keyval - * @accelerator_mods: return location for accelerator modifier mask - * - * Parses a string representing a virtual accelerator. The format - * looks like "<Control>a" or "<Shift><Alt>F1" or - * "<Release>z" (the last one is for key release). The parser - * is fairly liberal and allows lower or upper case, and also - * abbreviations such as "<Ctl>" and "<Ctrl>". - * - * If the parse fails, @accelerator_key and @accelerator_mods will - * be set to 0 (zero) and %FALSE will be returned. If the string contains - * only modifiers, @accelerator_key will be set to 0 but %TRUE will be - * returned. - * - * The virtual vs. concrete accelerator distinction is a relic of - * how the X Window System works; there are modifiers Mod2-Mod5 that - * can represent various keyboard keys (numlock, meta, hyper, etc.), - * the virtual modifier represents the keyboard key, the concrete - * modifier the actual Mod2-Mod5 bits in the key press event. - * - * Returns: %TRUE on success. - */ -gboolean -egg_accelerator_parse_virtual (const gchar *accelerator, - guint *accelerator_key, - guint *keycode, - EggVirtualModifierType *accelerator_mods) -{ - guint keyval; - GdkModifierType mods; - gint len; - gboolean bad_keyval; - - if (accelerator_key) - *accelerator_key = 0; - if (accelerator_mods) - *accelerator_mods = 0; - if (keycode) - *keycode = 0; - - g_return_val_if_fail (accelerator != NULL, FALSE); - - bad_keyval = FALSE; - - keyval = 0; - mods = 0; - len = strlen (accelerator); - while (len) - { - if (*accelerator == '<') - { - if (len >= 9 && is_release (accelerator)) - { - accelerator += 9; - len -= 9; - mods |= EGG_VIRTUAL_RELEASE_MASK; - } - else if (len >= 9 && is_control (accelerator)) - { - accelerator += 9; - len -= 9; - mods |= EGG_VIRTUAL_CONTROL_MASK; - } - else if (len >= 7 && is_shift (accelerator)) - { - accelerator += 7; - len -= 7; - mods |= EGG_VIRTUAL_SHIFT_MASK; - } - else if (len >= 6 && is_shft (accelerator)) - { - accelerator += 6; - len -= 6; - mods |= EGG_VIRTUAL_SHIFT_MASK; - } - else if (len >= 6 && is_ctrl (accelerator)) - { - accelerator += 6; - len -= 6; - mods |= EGG_VIRTUAL_CONTROL_MASK; - } - else if (len >= 6 && is_modx (accelerator)) - { - static const guint mod_vals[] = { - EGG_VIRTUAL_ALT_MASK, EGG_VIRTUAL_MOD2_MASK, EGG_VIRTUAL_MOD3_MASK, - EGG_VIRTUAL_MOD4_MASK, EGG_VIRTUAL_MOD5_MASK - }; - - len -= 6; - accelerator += 4; - mods |= mod_vals[*accelerator - '1']; - accelerator += 2; - } - else if (len >= 5 && is_ctl (accelerator)) - { - accelerator += 5; - len -= 5; - mods |= EGG_VIRTUAL_CONTROL_MASK; - } - else if (len >= 5 && is_alt (accelerator)) - { - accelerator += 5; - len -= 5; - mods |= EGG_VIRTUAL_ALT_MASK; - } - else if (len >= 6 && is_meta (accelerator)) - { - accelerator += 6; - len -= 6; - mods |= EGG_VIRTUAL_META_MASK; - } - else if (len >= 7 && is_hyper (accelerator)) - { - accelerator += 7; - len -= 7; - mods |= EGG_VIRTUAL_HYPER_MASK; - } - else if (len >= 7 && is_super (accelerator)) - { - accelerator += 7; - len -= 7; - mods |= EGG_VIRTUAL_SUPER_MASK; - } - else - { - gchar last_ch; - - last_ch = *accelerator; - while (last_ch && last_ch != '>') - { - last_ch = *accelerator; - accelerator += 1; - len -= 1; - } - } - } - else - { - keyval = gdk_keyval_from_name (accelerator); - - if (keyval == 0) - { - /* If keyval is 0, than maybe it's a keycode. Check for 0x## */ - if (len >= 4 && is_keycode (accelerator)) - { - char keystring[5]; - gchar *endptr; - gint tmp_keycode; - - memcpy (keystring, accelerator, 4); - keystring [4] = '\000'; - - tmp_keycode = strtol (keystring, &endptr, 16); - - if (endptr == NULL || *endptr != '\000') - { - bad_keyval = TRUE; - } - else if (keycode != NULL) - { - *keycode = tmp_keycode; - /* 0x00 is an invalid keycode too. */ - if (*keycode == 0) - bad_keyval = TRUE; - } - } - } else if (keycode != NULL) - *keycode = XKeysymToKeycode (GDK_DISPLAY(), keyval); - - accelerator += len; - len -= len; - } - } - - if (accelerator_key) - *accelerator_key = gdk_keyval_to_lower (keyval); - if (accelerator_mods) - *accelerator_mods = mods; - - return !bad_keyval; -} - - -/** - * egg_virtual_accelerator_name: - * @accelerator_key: accelerator keyval - * @accelerator_mods: accelerator modifier mask - * @returns: a newly-allocated accelerator name - * - * Converts an accelerator keyval and modifier mask - * into a string parseable by egg_accelerator_parse_virtual(). - * For example, if you pass in #GDK_q and #EGG_VIRTUAL_CONTROL_MASK, - * this function returns "<Control>q". - * - * The caller of this function must free the returned string. - */ -gchar* -egg_virtual_accelerator_name (guint accelerator_key, - guint keycode, - EggVirtualModifierType accelerator_mods) -{ - static const gchar text_release[] = ""; - static const gchar text_shift[] = ""; - static const gchar text_control[] = ""; - static const gchar text_mod1[] = ""; - static const gchar text_mod2[] = ""; - static const gchar text_mod3[] = ""; - static const gchar text_mod4[] = ""; - static const gchar text_mod5[] = ""; - static const gchar text_meta[] = ""; - static const gchar text_super[] = ""; - static const gchar text_hyper[] = ""; - guint l; - gchar *keyval_name; - gchar *accelerator; - - accelerator_mods &= EGG_VIRTUAL_MODIFIER_MASK; - - if (!accelerator_key) - { - keyval_name = g_strdup_printf ("0x%02x", keycode); - } - else - { - keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key)); - if (!keyval_name) - keyval_name = ""; - } - - l = 0; - if (accelerator_mods & EGG_VIRTUAL_RELEASE_MASK) - l += sizeof (text_release) - 1; - if (accelerator_mods & EGG_VIRTUAL_SHIFT_MASK) - l += sizeof (text_shift) - 1; - if (accelerator_mods & EGG_VIRTUAL_CONTROL_MASK) - l += sizeof (text_control) - 1; - if (accelerator_mods & EGG_VIRTUAL_ALT_MASK) - l += sizeof (text_mod1) - 1; - if (accelerator_mods & EGG_VIRTUAL_MOD2_MASK) - l += sizeof (text_mod2) - 1; - if (accelerator_mods & EGG_VIRTUAL_MOD3_MASK) - l += sizeof (text_mod3) - 1; - if (accelerator_mods & EGG_VIRTUAL_MOD4_MASK) - l += sizeof (text_mod4) - 1; - if (accelerator_mods & EGG_VIRTUAL_MOD5_MASK) - l += sizeof (text_mod5) - 1; - if (accelerator_mods & EGG_VIRTUAL_META_MASK) - l += sizeof (text_meta) - 1; - if (accelerator_mods & EGG_VIRTUAL_HYPER_MASK) - l += sizeof (text_hyper) - 1; - if (accelerator_mods & EGG_VIRTUAL_SUPER_MASK) - l += sizeof (text_super) - 1; - l += strlen (keyval_name); - - accelerator = g_new (gchar, l + 1); - - l = 0; - accelerator[l] = 0; - if (accelerator_mods & EGG_VIRTUAL_RELEASE_MASK) - { - strcpy (accelerator + l, text_release); - l += sizeof (text_release) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_SHIFT_MASK) - { - strcpy (accelerator + l, text_shift); - l += sizeof (text_shift) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_CONTROL_MASK) - { - strcpy (accelerator + l, text_control); - l += sizeof (text_control) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_ALT_MASK) - { - strcpy (accelerator + l, text_mod1); - l += sizeof (text_mod1) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_MOD2_MASK) - { - strcpy (accelerator + l, text_mod2); - l += sizeof (text_mod2) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_MOD3_MASK) - { - strcpy (accelerator + l, text_mod3); - l += sizeof (text_mod3) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_MOD4_MASK) - { - strcpy (accelerator + l, text_mod4); - l += sizeof (text_mod4) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_MOD5_MASK) - { - strcpy (accelerator + l, text_mod5); - l += sizeof (text_mod5) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_META_MASK) - { - strcpy (accelerator + l, text_meta); - l += sizeof (text_meta) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_HYPER_MASK) - { - strcpy (accelerator + l, text_hyper); - l += sizeof (text_hyper) - 1; - } - if (accelerator_mods & EGG_VIRTUAL_SUPER_MASK) - { - strcpy (accelerator + l, text_super); - l += sizeof (text_super) - 1; - } - - strcpy (accelerator + l, keyval_name); - - return accelerator; -} - -void -egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap, - EggVirtualModifierType virtual_mods, - GdkModifierType *concrete_mods) -{ - GdkModifierType concrete; - int i; - const EggModmap *modmap; - - g_return_if_fail (GDK_IS_KEYMAP (keymap)); - g_return_if_fail (concrete_mods != NULL); - - modmap = egg_keymap_get_modmap (keymap); - - /* Not so sure about this algorithm. */ - - concrete = 0; - i = 0; - while (i < EGG_MODMAP_ENTRY_LAST) - { - if (modmap->mapping[i] & virtual_mods) - concrete |= (1 << i); - - ++i; - } - - *concrete_mods = concrete; -} - -void -egg_keymap_virtualize_modifiers (GdkKeymap *keymap, - GdkModifierType concrete_mods, - EggVirtualModifierType *virtual_mods) -{ - GdkModifierType virtual; - int i; - const EggModmap *modmap; - - g_return_if_fail (GDK_IS_KEYMAP (keymap)); - g_return_if_fail (virtual_mods != NULL); - - modmap = egg_keymap_get_modmap (keymap); - - /* Not so sure about this algorithm. */ - - virtual = 0; - i = 0; - while (i < EGG_MODMAP_ENTRY_LAST) - { - if ((1 << i) & concrete_mods) - { - EggVirtualModifierType cleaned; - - cleaned = modmap->mapping[i] & ~(EGG_VIRTUAL_MOD2_MASK | - EGG_VIRTUAL_MOD3_MASK | - EGG_VIRTUAL_MOD4_MASK | - EGG_VIRTUAL_MOD5_MASK); - - if (cleaned != 0) - { - virtual |= cleaned; - } - else - { - /* Rather than dropping mod2->mod5 if not bound, - * go ahead and use the concrete names - */ - virtual |= modmap->mapping[i]; - } - } - - ++i; - } - - *virtual_mods = virtual; -} - -static void -reload_modmap (GdkKeymap *keymap, - EggModmap *modmap) -{ - XModifierKeymap *xmodmap; - int map_size; - int i; - - /* FIXME multihead */ - xmodmap = XGetModifierMapping (gdk_x11_get_default_xdisplay ()); - - memset (modmap->mapping, 0, sizeof (modmap->mapping)); - - /* there are 8 modifiers, and the first 3 are shift, shift lock, - * and control - */ - map_size = 8 * xmodmap->max_keypermod; - i = 3 * xmodmap->max_keypermod; - while (i < map_size) - { - /* get the key code at this point in the map, - * see if its keysym is one we're interested in - */ - int keycode = xmodmap->modifiermap[i]; - GdkKeymapKey *keys; - guint *keyvals; - int n_entries; - int j; - EggVirtualModifierType mask; - - keys = NULL; - keyvals = NULL; - n_entries = 0; - - gdk_keymap_get_entries_for_keycode (keymap, - keycode, - &keys, &keyvals, &n_entries); - - mask = 0; - j = 0; - while (j < n_entries) - { - if (keyvals[j] == GDK_Num_Lock) - mask |= EGG_VIRTUAL_NUM_LOCK_MASK; - else if (keyvals[j] == GDK_Scroll_Lock) - mask |= EGG_VIRTUAL_SCROLL_LOCK_MASK; - else if (keyvals[j] == GDK_Meta_L || - keyvals[j] == GDK_Meta_R) - mask |= EGG_VIRTUAL_META_MASK; - else if (keyvals[j] == GDK_Hyper_L || - keyvals[j] == GDK_Hyper_R) - mask |= EGG_VIRTUAL_HYPER_MASK; - else if (keyvals[j] == GDK_Super_L || - keyvals[j] == GDK_Super_R) - mask |= EGG_VIRTUAL_SUPER_MASK; - else if (keyvals[j] == GDK_Mode_switch) - mask |= EGG_VIRTUAL_MODE_SWITCH_MASK; - - ++j; - } - - /* Mod1Mask is 1 << 3 for example, i.e. the - * fourth modifier, i / keyspermod is the modifier - * index - */ - modmap->mapping[i/xmodmap->max_keypermod] |= mask; - - g_free (keyvals); - g_free (keys); - - ++i; - } - - /* Add in the not-really-virtual fixed entries */ - modmap->mapping[EGG_MODMAP_ENTRY_SHIFT] |= EGG_VIRTUAL_SHIFT_MASK; - modmap->mapping[EGG_MODMAP_ENTRY_CONTROL] |= EGG_VIRTUAL_CONTROL_MASK; - modmap->mapping[EGG_MODMAP_ENTRY_LOCK] |= EGG_VIRTUAL_LOCK_MASK; - modmap->mapping[EGG_MODMAP_ENTRY_MOD1] |= EGG_VIRTUAL_ALT_MASK; - modmap->mapping[EGG_MODMAP_ENTRY_MOD2] |= EGG_VIRTUAL_MOD2_MASK; - modmap->mapping[EGG_MODMAP_ENTRY_MOD3] |= EGG_VIRTUAL_MOD3_MASK; - modmap->mapping[EGG_MODMAP_ENTRY_MOD4] |= EGG_VIRTUAL_MOD4_MASK; - modmap->mapping[EGG_MODMAP_ENTRY_MOD5] |= EGG_VIRTUAL_MOD5_MASK; - - XFreeModifiermap (xmodmap); -} - -const EggModmap* -egg_keymap_get_modmap (GdkKeymap *keymap) -{ - EggModmap *modmap; - - /* This is all a hack, much simpler when we can just - * modify GDK directly. - */ - - modmap = g_object_get_data (G_OBJECT (keymap), - "egg-modmap"); - - if (modmap == NULL) - { - modmap = g_new0 (EggModmap, 1); - - /* FIXME modify keymap change events with an event filter - * and force a reload if we get one - */ - - reload_modmap (keymap, modmap); - - g_object_set_data_full (G_OBJECT (keymap), - "egg-modmap", - modmap, - g_free); - } - - g_assert (modmap != NULL); - - return modmap; -} diff --git a/lib/sugar/eggaccelerators.h b/lib/sugar/eggaccelerators.h deleted file mode 100644 index d2276d2..0000000 --- a/lib/sugar/eggaccelerators.h +++ /dev/null @@ -1,89 +0,0 @@ -/* eggaccelerators.h - * Copyright (C) 2002 Red Hat, Inc. - * Developed by Havoc Pennington - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __EGG_ACCELERATORS_H__ -#define __EGG_ACCELERATORS_H__ - -#include -#include - -G_BEGIN_DECLS - -/* Where a value is also in GdkModifierType we coincide, - * otherwise we don't overlap. - */ -typedef enum -{ - EGG_VIRTUAL_SHIFT_MASK = 1 << 0, - EGG_VIRTUAL_LOCK_MASK = 1 << 1, - EGG_VIRTUAL_CONTROL_MASK = 1 << 2, - - EGG_VIRTUAL_ALT_MASK = 1 << 3, /* fixed as Mod1 */ - - EGG_VIRTUAL_MOD2_MASK = 1 << 4, - EGG_VIRTUAL_MOD3_MASK = 1 << 5, - EGG_VIRTUAL_MOD4_MASK = 1 << 6, - EGG_VIRTUAL_MOD5_MASK = 1 << 7, - -#if 0 - GDK_BUTTON1_MASK = 1 << 8, - GDK_BUTTON2_MASK = 1 << 9, - GDK_BUTTON3_MASK = 1 << 10, - GDK_BUTTON4_MASK = 1 << 11, - GDK_BUTTON5_MASK = 1 << 12, - /* 13, 14 are used by Xkb for the keyboard group */ -#endif - - EGG_VIRTUAL_META_MASK = 1 << 24, - EGG_VIRTUAL_SUPER_MASK = 1 << 25, - EGG_VIRTUAL_HYPER_MASK = 1 << 26, - EGG_VIRTUAL_MODE_SWITCH_MASK = 1 << 27, - EGG_VIRTUAL_NUM_LOCK_MASK = 1 << 28, - EGG_VIRTUAL_SCROLL_LOCK_MASK = 1 << 29, - - /* Also in GdkModifierType */ - EGG_VIRTUAL_RELEASE_MASK = 1 << 30, - - /* 28-31 24-27 20-23 16-19 12-15 8-11 4-7 0-3 - * 7 f 0 0 0 0 f f - */ - EGG_VIRTUAL_MODIFIER_MASK = 0x7f0000ff - -} EggVirtualModifierType; - -gboolean egg_accelerator_parse_virtual (const gchar *accelerator, - guint *accelerator_key, - guint *keycode, - EggVirtualModifierType *accelerator_mods); -void egg_keymap_resolve_virtual_modifiers (GdkKeymap *keymap, - EggVirtualModifierType virtual_mods, - GdkModifierType *concrete_mods); -void egg_keymap_virtualize_modifiers (GdkKeymap *keymap, - GdkModifierType concrete_mods, - EggVirtualModifierType *virtual_mods); - -gchar* egg_virtual_accelerator_name (guint accelerator_key, - guint keycode, - EggVirtualModifierType accelerator_mods); - -G_END_DECLS - - -#endif /* __EGG_ACCELERATORS_H__ */ diff --git a/lib/sugar/env.py b/lib/sugar/env.py deleted file mode 100644 index e0b6fa9..0000000 --- a/lib/sugar/env.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Calculates file-paths for the Sugar working environment""" -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import os - -def is_emulator(): - if os.environ.has_key('SUGAR_EMULATOR'): - if os.environ['SUGAR_EMULATOR'] == 'yes': - return True - return False - -def get_profile_path(path=None): - if os.environ.has_key('SUGAR_PROFILE'): - profile_id = os.environ['SUGAR_PROFILE'] - else: - profile_id = 'default' - - base = os.path.join(os.path.expanduser('~/.sugar'), profile_id) - if not os.path.isdir(base): - try: - os.makedirs(base, 0770) - except OSError, exc: - print "Could not create user directory." - - if path != None: - return os.path.join(base, path) - else: - return base - -def get_logs_path(path=None): - base = get_profile_path('logs') - if path != None: - return os.path.join(base, path) - else: - return base - -def get_user_activities_path(): - return os.path.expanduser('~/Activities') - -def get_user_library_path(): - return os.path.expanduser('~/Library') diff --git a/lib/sugar/graphics/Makefile.am b/lib/sugar/graphics/Makefile.am deleted file mode 100644 index 0a3a846..0000000 --- a/lib/sugar/graphics/Makefile.am +++ /dev/null @@ -1,25 +0,0 @@ -sugardir = $(pythondir)/sugar/graphics -sugar_PYTHON = \ - __init__.py \ - alert.py \ - animator.py \ - combobox.py \ - entry.py \ - icon.py \ - iconentry.py \ - menuitem.py \ - notebook.py \ - objectchooser.py \ - radiotoolbutton.py \ - palette.py \ - palettegroup.py \ - panel.py \ - roundbox.py \ - style.py \ - toggletoolbutton.py \ - toolbox.py \ - toolbutton.py \ - toolcombobox.py \ - tray.py \ - window.py \ - xocolor.py diff --git a/lib/sugar/graphics/__init__.py b/lib/sugar/graphics/__init__.py deleted file mode 100644 index 1e7e0f9..0000000 --- a/lib/sugar/graphics/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Graphics/controls for use in Sugar""" - -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. diff --git a/lib/sugar/graphics/alert.py b/lib/sugar/graphics/alert.py deleted file mode 100644 index ef649b2..0000000 --- a/lib/sugar/graphics/alert.py +++ /dev/null @@ -1,254 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -from gettext import gettext as _ - -import gtk -import gobject -import hippo -import math - -from sugar.graphics import style -from sugar.graphics.icon import Icon - - -class Alert(gtk.EventBox, gobject.GObject): - """UI interface for Alerts - - Alerts are used inside the activity window instead of being a - separate popup window. They do not hide canvas content. You can - use add_alert(widget) and remove_alert(widget) inside your activity - to add and remove the alert. The position of the alert is below the - toolbox or top in fullscreen mode. - - Properties: - 'title': the title of the alert, - 'message': the message of the alert, - 'icon': the icon that appears at the far left - See __gproperties__ - """ - - __gtype_name__ = 'SugarAlert' - - __gsignals__ = { - 'response': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])) - } - - __gproperties__ = { - 'title' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'msg' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'icon' : (object, None, None, - gobject.PARAM_WRITABLE) - } - - def __init__(self, **kwargs): - gobject.GObject.__init__(self) - - self.set_visible_window(True) - self._hbox = gtk.HBox() - self._hbox.set_border_width(style.DEFAULT_SPACING) - self._hbox.set_spacing(style.DEFAULT_SPACING) - self.add(self._hbox) - - self._title = None - self._msg = None - self._icon = None - self._buttons = {} - - self._msg_box = gtk.VBox() - self._title_label = gtk.Label() - self._title_label.set_alignment(0, 0.5) - self._msg_box.pack_start(self._title_label, False) - self._title_label.show() - - self._msg_label = gtk.Label() - self._msg_label.set_alignment(0, 0.5) - self._msg_box.pack_start(self._msg_label, False) - self._hbox.pack_start(self._msg_box, False) - self._msg_label.show() - - self._buttons_box = gtk.HButtonBox() - self._buttons_box.set_layout(gtk.BUTTONBOX_END) - self._buttons_box.set_spacing(style.DEFAULT_SPACING) - self._hbox.pack_start(self._buttons_box) - self._buttons_box.show() - - self._msg_box.show() - self._hbox.show() - self.show() - - def do_set_property(self, pspec, value): - if pspec.name == 'title': - if self._title != value: - self._title = value - self._title_label.set_markup("" + self._title + "") - elif pspec.name == 'msg': - if self._msg != value: - self._msg = value - self._msg_label.set_markup(self._msg) - elif pspec.name == 'icon': - if self._icon != value: - self._icon = value - self._hbox.pack_start(self._icon, False) - self._hbox.reorder_child(self._icon, 0) - - def do_get_property(self, pspec): - if pspec.name == 'title': - return self._title - elif pspec.name == 'msg': - return self._msg - - def add_button(self, response_id, label, icon=None, position=-1): - """Add a button to the alert - - response_id: will be emitted with the response signal - a response ID should one of the pre-defined - GTK Response Type Constants or a positive number - label: that will occure right to the buttom - icon: this can be a SugarIcon or a gtk.Image - position: the position of the button in the box (optional) - """ - button = gtk.Button() - self._buttons[response_id] = button - if icon is not None: - button.set_image(icon) - button.set_label(label) - self._buttons_box.pack_start(button) - button.show() - button.connect('clicked', self.__button_clicked_cb, response_id) - if position != -1: - self._buttons_box.reorder_child(button, position) - return button - - def remove_button(self, response_id): - """Remove a button from the alert by the given button id""" - self._buttons_box.remove(self._buttons[id]) - - def _response(self, id): - """Emitting response when we have a result - - A result can be that a user has clicked a button or - a timeout has occured, the id identifies the button - that has been clicked and -1 for a timeout - """ - self.emit('response', id) - - def __button_clicked_cb(self, button, response_id): - self._response(response_id) - - -class ConfirmationAlert(Alert): - """This is a ready-made two button (Cancel,Ok) alert""" - - def __init__(self, **kwargs): - Alert.__init__(self, **kwargs) - - icon = Icon(icon_name='dialog-cancel') - cancel_button = self.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), icon) - icon.show() - - icon = Icon(icon_name='dialog-ok') - ok_button = self.add_button(gtk.RESPONSE_OK, _('Ok'), icon) - icon.show() - - -class _TimeoutIcon(hippo.CanvasText, hippo.CanvasItem): - __gtype_name__ = 'AlertTimeoutIcon' - - def __init__(self, **kwargs): - hippo.CanvasText.__init__(self, **kwargs) - - self.props.orientation = hippo.ORIENTATION_HORIZONTAL - self.props.border_left = style.DEFAULT_SPACING - self.props.border_right = style.DEFAULT_SPACING - - def do_paint_background(self, cr, damaged_box): - [width, height] = self.get_allocation() - - x = width * 0.5 - y = height * 0.5 - radius = min(width * 0.5, height * 0.5) - - hippo.cairo_set_source_rgba32(cr, self.props.background_color) - cr.arc(x, y, radius, 0, 2*math.pi) - cr.fill_preserve() - - -class TimeoutAlert(Alert): - """This is a ready-made two button (Cancel,Continue) alert - - It times out with a positive reponse after the given amount of seconds. - """ - - def __init__(self, timeout=5, **kwargs): - Alert.__init__(self, **kwargs) - - self._timeout = timeout - - icon = Icon(icon_name='dialog-cancel') - cancel_button = self.add_button(gtk.RESPONSE_CANCEL, _('Cancel'), icon) - icon.show() - - self._timeout_text = _TimeoutIcon( - text=self._timeout, - color=style.COLOR_BUTTON_GREY.get_int(), - background_color=style.COLOR_WHITE.get_int()) - canvas = hippo.Canvas() - canvas.set_root(self._timeout_text) - canvas.show() - self.add_button(gtk.RESPONSE_OK, _('Continue'), canvas) - - gobject.timeout_add(1000, self.__timeout) - - def __timeout(self): - self._timeout -= 1 - self._timeout_text.props.text = self._timeout - if self._timeout == 0: - self._response(gtk.RESPONSE_OK) - return False - return True - - -class NotifyAlert(Alert): - """Timeout alert with only an "OK" button - just for notifications""" - - def __init__(self, timeout=5, **kwargs): - Alert.__init__(self, **kwargs) - - self._timeout = timeout - - self._timeout_text = _TimeoutIcon( - text=self._timeout, - color=style.COLOR_BUTTON_GREY.get_int(), - background_color=style.COLOR_WHITE.get_int()) - canvas = hippo.Canvas() - canvas.set_root(self._timeout_text) - canvas.show() - self.add_button(gtk.RESPONSE_OK, _('OK'), canvas) - - gobject.timeout_add(1000, self.__timeout) - - def __timeout(self): - self._timeout -= 1 - self._timeout_text.props.text = self._timeout - if self._timeout == 0: - self._response(gtk.RESPONSE_OK) - return False - return True diff --git a/lib/sugar/graphics/animator.py b/lib/sugar/graphics/animator.py deleted file mode 100644 index 459851b..0000000 --- a/lib/sugar/graphics/animator.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import time - -import gobject - -EASE_OUT_EXPO = 0 -EASE_IN_EXPO = 1 - -class Animator(gobject.GObject): - __gsignals__ = { - 'completed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - } - - def __init__(self, time, fps=20, easing=EASE_OUT_EXPO): - gobject.GObject.__init__(self) - self._animations = [] - self._time = time - self._interval = 1.0 / fps - self._easing = easing - self._timeout_sid = 0 - - def add(self, animation): - self._animations.append(animation) - - def remove_all(self): - self.stop() - self._animations = [] - - def start(self): - if self._timeout_sid: - self.stop() - - self._start_time = time.time() - self._timeout_sid = gobject.timeout_add( - int(self._interval * 1000), self._next_frame_cb) - - def stop(self): - if self._timeout_sid: - gobject.source_remove(self._timeout_sid) - self._timeout_sid = 0 - self.emit('completed') - - def _next_frame_cb(self): - current_time = min(self._time, time.time() - self._start_time) - current_time = max(current_time, 0.0) - - for animation in self._animations: - animation.do_frame(current_time, self._time, self._easing) - - if current_time == self._time: - self.stop() - return False - else: - return True - -class Animation(object): - def __init__(self, start, end): - self.start = start - self.end = end - - def do_frame(self, time, duration, easing): - start = self.start - change = self.end - self.start - - if time == duration: - # last frame - frame = self.end - else: - if easing == EASE_OUT_EXPO: - frame = change * (-pow(2, -10 * time/duration) + 1) + start; - elif easing == EASE_IN_EXPO: - frame = change * pow(2, 10 * (time / duration - 1)) + start; - - self.next_frame(frame) - - def next_frame(self, frame): - pass diff --git a/lib/sugar/graphics/combobox.py b/lib/sugar/graphics/combobox.py deleted file mode 100644 index 5584267..0000000 --- a/lib/sugar/graphics/combobox.py +++ /dev/null @@ -1,114 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -import sys -import os -import logging - -import gobject -import gtk - -class ComboBox(gtk.ComboBox): - __gtype_name__ = 'SugarComboBox' - - __gproperties__ = { - 'value' : (object, None, None, - gobject.PARAM_READABLE) - } - def __init__(self): - gtk.ComboBox.__init__(self) - - self._text_renderer = None - self._icon_renderer = None - - self._model = gtk.ListStore(gobject.TYPE_PYOBJECT, - gobject.TYPE_STRING, - gtk.gdk.Pixbuf, - gobject.TYPE_BOOLEAN) - self.set_model(self._model) - - self.set_row_separator_func(self._is_separator) - - def do_get_property(self, pspec): - if pspec.name == 'value': - row = self.get_active_item() - if not row: - return None - return row[0] - else: - return gtk.ComboBox.do_get_property(self, pspec) - - def _get_real_name_from_theme(self, name, size): - icon_theme = gtk.icon_theme_get_default() - width, height = gtk.icon_size_lookup(size) - info = icon_theme.lookup_icon(name, width, 0) - if not info: - raise ValueError("Icon '" + name + "' not found.") - fname = info.get_filename() - del info - return fname - - def append_item(self, action_id, text, icon_name=None, file_name=None): - if not self._icon_renderer and (icon_name or file_name): - self._icon_renderer = gtk.CellRendererPixbuf() - - settings = self.get_settings() - w, h = gtk.icon_size_lookup_for_settings(settings, gtk.ICON_SIZE_MENU) - self._icon_renderer.props.stock_size = w - - self.pack_start(self._icon_renderer, False) - self.add_attribute(self._icon_renderer, 'pixbuf', 2) - - if not self._text_renderer and text: - self._text_renderer = gtk.CellRendererText() - self.pack_end(self._text_renderer, True) - self.add_attribute(self._text_renderer, 'text', 1) - - if icon_name or file_name: - if text: - size = gtk.ICON_SIZE_MENU - else: - size = gtk.ICON_SIZE_LARGE_TOOLBAR - width, height = gtk.icon_size_lookup(size) - - if icon_name: - file_name = self._get_real_name_from_theme(icon_name, size) - - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(file_name, width, height) - else: - pixbuf = None - - self._model.append([action_id, text, pixbuf, False]) - - def append_separator(self): - self._model.append([0, None, None, True]) - - def get_active_item(self): - index = self.get_active() - if index == -1: - index = 0 - - row = self._model.iter_nth_child(None, index) - if not row: - return None - return self._model[row] - - def remove_all(self): - self._model.clear() - - def _is_separator(self, model, row): - action_id, text, icon_name, is_separator = model[row] - return is_separator diff --git a/lib/sugar/graphics/entry.py b/lib/sugar/graphics/entry.py deleted file mode 100644 index 95510e5..0000000 --- a/lib/sugar/graphics/entry.py +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk -import hippo - -class CanvasEntry(hippo.CanvasEntry): - def set_background(self, color_spec): - color = gtk.gdk.color_parse(color_spec) - self.props.widget.modify_bg(gtk.STATE_INSENSITIVE, color) - self.props.widget.modify_base(gtk.STATE_INSENSITIVE, color) diff --git a/lib/sugar/graphics/icon.py b/lib/sugar/graphics/icon.py deleted file mode 100644 index 81a8232..0000000 --- a/lib/sugar/graphics/icon.py +++ /dev/null @@ -1,550 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import os -import re -import math -import time -import logging - -import gobject -import gtk -import hippo -import cairo - -from sugar.graphics.style import Color -from sugar.graphics.xocolor import XoColor -from sugar.graphics import style -from sugar.graphics.palette import Palette, CanvasInvoker -from sugar.util import LRU - -_BADGE_SIZE = 0.45 - -class _SVGLoader(object): - def __init__(self): - self._cache = LRU(50) - - def load(self, file_name, entities, cache): - if file_name in self._cache: - icon = self._cache[file_name] - else: - icon_file = open(file_name, 'r') - icon = icon_file.read() - icon_file.close() - - if cache: - self._cache[file_name] = icon - - for entity, value in entities.items(): - if isinstance(value, basestring): - xml = '' % (entity, value) - icon = re.sub('' % entity, xml, icon) - else: - logging.error( - 'Icon %s, entity %s is invalid.', file_name, entity) - - import rsvg # XXX this is very slow! why? - return rsvg.Handle(data=icon) - -class _IconInfo(object): - def __init__(self): - self.file_name = None - self.attach_x = 0 - self.attach_y = 0 - -class _BadgeInfo(object): - def __init__(self): - self.attach_x = 0 - self.attach_y = 0 - self.size = 0 - self.icon_padding = 0 - -class _IconBuffer(object): - _surface_cache = LRU(50) - _loader = _SVGLoader() - - def __init__(self): - self.icon_name = None - self.file_name = None - self.fill_color = None - self.stroke_color = None - self.badge_name = None - self.width = None - self.height = None - self.cache = False - self.scale = 1.0 - - def _get_cache_key(self, sensitive): - return (self.icon_name, self.file_name, self.fill_color, - self.stroke_color, self.badge_name, self.width, self.height, - sensitive) - - def _load_svg(self, file_name): - entities = {} - if self.fill_color: - entities['fill_color'] = self.fill_color - if self.stroke_color: - entities['stroke_color'] = self.stroke_color - - return self._loader.load(file_name, entities, self.cache) - - def _get_attach_points(self, info, size_request): - attach_points = info.get_attach_points() - - if attach_points: - attach_x = float(attach_points[0][0]) / size_request - attach_y = float(attach_points[0][1]) / size_request - else: - attach_x = attach_y = 0 - - return attach_x, attach_y - - def _get_icon_info(self): - icon_info = _IconInfo() - - if self.file_name: - icon_info.file_name = self.file_name - elif self.icon_name: - theme = gtk.icon_theme_get_default() - - size = 50 - if self.width != None: - size = self.width - - info = theme.lookup_icon(self.icon_name, size, 0) - if info: - attach_x, attach_y = self._get_attach_points(info, size) - - icon_info.file_name = info.get_filename() - icon_info.attach_x = attach_x - icon_info.attach_y = attach_y - - del info - else: - logging.warning('No icon with the name %s ' - 'was found in the theme.' % self.icon_name) - - return icon_info - - def _draw_badge(self, context, size, sensitive, widget): - theme = gtk.icon_theme_get_default() - badge_info = theme.lookup_icon(self.badge_name, size, 0) - if badge_info: - badge_file_name = badge_info.get_filename() - if badge_file_name.endswith('.svg'): - handle = self._loader.load(badge_file_name, {}, self.cache) - pixbuf = handle.get_pixbuf() - else: - pixbuf = gtk.gdk.pixbuf_new_from_file(badge_file_name) - - if not sensitive: - pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) - surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) - context.set_source_surface(surface, 0, 0) - context.paint() - - def _get_size(self, icon_width, icon_height, padding): - if self.width is not None and self.height is not None: - width = self.width + padding - height = self.height + padding - else: - width = icon_width + padding - height = icon_height + padding - - return width, height - - def _get_badge_info(self, icon_info, icon_width, icon_height): - info = _BadgeInfo() - if self.badge_name is None: - return info - - info.size = int(_BADGE_SIZE * icon_width) - info.attach_x = int(icon_info.attach_x * icon_width - info.size / 2) - info.attach_y = int(icon_info.attach_y * icon_height - info.size / 2) - - if info.attach_x < 0 or info.attach_y < 0: - info.icon_padding = max(-info.attach_x, -info.attach_y) - elif info.attach_x + info.size > icon_width or \ - info.attach_y + info.size > icon_height: - x_padding = info.attach_x + info.size - icon_width - y_padding = info.attach_y + info.size - icon_height - info.icon_padding = max(x_padding, y_padding) - - return info - - def _get_xo_color(self): - if self.stroke_color and self.fill_color: - return XoColor('%s,%s' % (self.stroke_color, self.fill_color)) - else: - return None - - def _set_xo_color(self, xo_color): - if xo_color: - self.stroke_color = xo_color.get_stroke_color() - self.fill_color = xo_color.get_fill_color() - else: - self.stroke_color = None - self.fill_color = None - - def _get_insensitive_pixbuf (self, pixbuf, widget): - if not (widget and 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 = widget.style.render_icon(icon_source, widget.get_direction(), - gtk.STATE_INSENSITIVE, -1, widget, - "sugar-icon") - - return pixbuf - - def get_surface(self, sensitive=True, widget=None): - cache_key = self._get_cache_key(sensitive) - if cache_key in self._surface_cache: - return self._surface_cache[cache_key] - - icon_info = self._get_icon_info() - if icon_info.file_name is None: - return None - - is_svg = icon_info.file_name.endswith('.svg') - - if is_svg: - handle = self._load_svg(icon_info.file_name) - dimensions = handle.get_dimension_data() - icon_width = int(dimensions[0]) - icon_height = int(dimensions[1]) - else: - pixbuf = gtk.gdk.pixbuf_new_from_file(icon_info.file_name) - icon_width = pixbuf.get_width() - icon_height = pixbuf.get_height() - - badge_info = self._get_badge_info(icon_info, icon_width, icon_height) - - padding = badge_info.icon_padding - width, height = self._get_size(icon_width, icon_height, padding) - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - - context = cairo.Context(surface) - context.scale(float(width) / (icon_width + padding * 2), - float(height) / (icon_height + padding * 2)) - context.save() - - context.translate(padding, padding) - if is_svg: - if sensitive: - handle.render_cairo(context) - else: - pixbuf = handle.get_pixbuf() - pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) - - pixbuf_surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) - context.set_source_surface(pixbuf_surface, 0, 0) - context.paint() - else: - if not sensitive: - pixbuf = self._get_insensitive_pixbuf(pixbuf, widget) - pixbuf_surface = hippo.cairo_surface_from_gdk_pixbuf(pixbuf) - context.set_source_surface(pixbuf_surface, 0, 0) - context.paint() - - if self.badge_name: - context.restore() - context.translate(badge_info.attach_x, badge_info.attach_y) - self._draw_badge(context, badge_info.size, sensitive, widget) - - self._surface_cache[cache_key] = surface - - return surface - - xo_color = property(_get_xo_color, _set_xo_color) - -class Icon(gtk.Image): - __gtype_name__ = 'SugarIcon' - - __gproperties__ = { - 'xo-color' : (object, None, None, - gobject.PARAM_WRITABLE), - 'fill-color' : (object, None, None, - gobject.PARAM_READWRITE), - 'stroke-color' : (object, None, None, - gobject.PARAM_READWRITE), - 'badge-name' : (str, None, None, None, - gobject.PARAM_READWRITE) - } - - def __init__(self, **kwargs): - self._buffer = _IconBuffer() - - gobject.GObject.__init__(self, **kwargs) - - def _sync_image_properties(self): - if self._buffer.icon_name != self.props.icon_name: - self._buffer.icon_name = self.props.icon_name - - if self._buffer.file_name != self.props.file: - self._buffer.file_name = self.props.file - - width, height = gtk.icon_size_lookup(self.props.icon_size) - if self._buffer.width != width or self._buffer.height != height: - self._buffer.width = width - self._buffer.height = height - - def _icon_size_changed_cb(self, image, pspec): - self._buffer.icon_size = self.props.icon_size - - def _icon_name_changed_cb(self, image, pspec): - self._buffer.icon_name = self.props.icon_name - - def _file_changed_cb(self, image, pspec): - self._buffer.file_name = self.props.file - - def _update_buffer_size(self): - width, height = gtk.icon_size_lookup(self.props.icon_size) - - self._buffer.width = width - self._buffer.height = height - - def do_size_request(self, requisition): - self._sync_image_properties() - surface = self._buffer.get_surface() - if surface: - requisition[0] = surface.get_width() - requisition[1] = surface.get_height() - elif self._buffer.width and self._buffer.height: - requisition[0] = self._buffer.width - requisition[1] = self._buffer.width - else: - requisition[0] = requisition[1] = 0 - - def do_expose_event(self, event): - self._sync_image_properties() - sensitive = (self.state != gtk.STATE_INSENSITIVE) - surface = self._buffer.get_surface(sensitive, self) - if surface is None: - return - - xpad, ypad = self.get_padding() - xalign, yalign = self.get_alignment() - requisition = self.get_child_requisition() - if self.get_direction() != gtk.TEXT_DIR_LTR: - xalign = 1.0 - xalign - - x = math.floor(self.allocation.x + xpad + - (self.allocation.width - requisition[0]) * xalign) - y = math.floor(self.allocation.y + ypad + - (self.allocation.height - requisition[1]) * yalign) - - cr = self.window.cairo_create() - cr.set_source_surface(surface, x, y) - cr.paint() - - def do_set_property(self, pspec, value): - if pspec.name == 'xo-color': - if self._buffer.xo_color != value: - self._buffer.xo_color = value - self.queue_draw() - elif pspec.name == 'fill-color': - if self._buffer.fill_color != value: - self._buffer.fill_color = value - self.queue_draw() - elif pspec.name == 'stroke-color': - if self._buffer.stroke_color != value: - self._buffer.stroke_color = value - self.queue_draw() - elif pspec.name == 'badge-name': - if self._buffer.badge_name != value: - self._buffer.badge_name = value - self.queue_resize() - else: - gtk.Image.do_set_property(self, pspec, value) - - def do_get_property(self, pspec): - if pspec.name == 'fill-color': - return self._buffer.fill_color - elif pspec.name == 'stroke-color': - return self._buffer.stroke_color - elif pspec.name == 'badge-name': - return self._buffer.badge_name - else: - return gtk.Image.do_get_property(self, pspec) - -class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem): - __gtype_name__ = 'CanvasIcon' - - __gproperties__ = { - 'file-name' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'icon-name' : (str, None, None, None, - gobject.PARAM_READWRITE), - 'xo-color' : (object, None, None, - gobject.PARAM_WRITABLE), - 'fill-color' : (object, None, None, - gobject.PARAM_READWRITE), - 'stroke-color' : (object, None, None, - gobject.PARAM_READWRITE), - 'size' : (int, None, None, 0, 1024, 0, - gobject.PARAM_READWRITE), - 'scale' : (float, None, None, -1024.0, 1024.0, 1.0, - gobject.PARAM_READWRITE), - 'cache' : (bool, None, None, False, - gobject.PARAM_READWRITE), - 'badge-name' : (str, None, None, None, - gobject.PARAM_READWRITE) - } - - def __init__(self, **kwargs): - self._buffer = _IconBuffer() - - hippo.CanvasBox.__init__(self, **kwargs) - - self._palette = None - self.connect('destroy', self.__destroy_cb) - - def __destroy_cb(self, icon): - if self._palette is not None: - self._palette.destroy() - - def do_set_property(self, pspec, value): - if pspec.name == 'file-name': - if self._buffer.file_name != value: - self._buffer.file_name = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'icon-name': - if self._buffer.icon_name != value: - self._buffer.icon_name = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'xo-color': - if self._buffer.xo_color != value: - self._buffer.xo_color = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'fill-color': - if self._buffer.fill_color != value: - self._buffer.fill_color = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'stroke-color': - if self._buffer.stroke_color != value: - self._buffer.stroke_color = value - self.emit_paint_needed(0, 0, -1, -1) - elif pspec.name == 'size': - if self._buffer.width != value: - self._buffer.width = value - self._buffer.height = value - self.emit_request_changed() - elif pspec.name == 'scale': - logging.warning('CanvasIcon: the scale parameter is currently unsupported') - if self._buffer.scale != value: - self._buffer.scale = value - self.emit_request_changed() - elif pspec.name == 'cache': - self._buffer.cache = value - elif pspec.name == 'badge-name': - if self._buffer.badge_name != value: - self._buffer.badge_name = value - self.emit_paint_needed(0, 0, -1, -1) - - def do_get_property(self, pspec): - if pspec.name == 'size': - return self._buffer.width - elif pspec.name == 'file-name': - return self._buffer.file_name - elif pspec.name == 'icon-name': - return self._buffer.icon_name - elif pspec.name == 'fill-color': - return self._buffer.fill_color - elif pspec.name == 'stroke-color': - return self._buffer.stroke_color - elif pspec.name == 'cache': - return self._buffer.cache - elif pspec.name == 'badge-name': - return self._buffer.badge_name - elif pspec.name == 'scale': - return self._buffer.scale - - def do_paint_below_children(self, cr, damaged_box): - surface = self._buffer.get_surface() - if surface: - width, height = self.get_allocation() - - x = (width - surface.get_width()) / 2 - y = (height - surface.get_height()) / 2 - - cr.set_source_surface(surface, x, y) - cr.paint() - - def do_get_content_width_request(self): - surface = self._buffer.get_surface() - if surface: - size = surface.get_width() - elif self._buffer.width: - size = self._buffer.width - else: - size = 0 - - return size, size - - def do_get_content_height_request(self, for_width): - surface = self._buffer.get_surface() - if surface: - size = surface.get_height() - elif self._buffer.height: - size = self._buffer.height - else: - size = 0 - - return size, size - - def do_button_press_event(self, event): - self.emit_activated() - return True - - def get_palette(self): - return self._palette - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - if not self._palette.props.invoker: - self._palette.props.invoker = CanvasInvoker(self) - - def set_tooltip(self, text): - self.set_palette(Palette(text)) - - palette = property(get_palette, set_palette) - -def get_icon_state(base_name, perc): - step = 5 - strength = round(perc / step) * step - icon_theme = gtk.icon_theme_get_default() - - while strength <= 100: - icon_name = '%s-%03d' % (base_name, strength) - if icon_theme.has_icon(icon_name): - return icon_name - - strength = strength + step diff --git a/lib/sugar/graphics/iconentry.py b/lib/sugar/graphics/iconentry.py deleted file mode 100644 index a1fed31..0000000 --- a/lib/sugar/graphics/iconentry.py +++ /dev/null @@ -1,108 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk - -from sugar import _sugarext - -from sugar.graphics import style -from sugar.graphics.icon import _SVGLoader -import sugar.profile - -ICON_ENTRY_PRIMARY = _sugarext.ICON_ENTRY_PRIMARY -ICON_ENTRY_SECONDARY = _sugarext.ICON_ENTRY_SECONDARY - -class IconEntry(_sugarext.IconEntry): - - def __init__(self): - _sugarext.IconEntry.__init__(self) - - self._clear_icon = None - self._clear_shown = False - - self.connect('key_press_event', self._keypress_event_cb) - - def set_icon_from_name(self, position, name): - icon_theme = gtk.icon_theme_get_default() - icon_info = icon_theme.lookup_icon(name, - gtk.ICON_SIZE_SMALL_TOOLBAR, - 0) - - if icon_info.get_filename().endswith('.svg'): - loader = _SVGLoader() - color = sugar.profile.get_color() - entities = {'fill_color': style.COLOR_TOOLBAR_GREY.get_svg(), - 'stroke_color': style.COLOR_TOOLBAR_GREY.get_svg()} - handle = loader.load(icon_info.get_filename(), entities, None) - pixbuf = handle.get_pixbuf() - else: - pixbuf = gtk.gdk.pixbuf_new_from_file(icon_info.get_filename()) - del icon_info - - image = gtk.Image() - image.set_from_pixbuf(pixbuf) - image.show() - - self.set_icon(position, image) - - def set_icon(self, position, image): - if image.get_storage_type() not in [gtk.IMAGE_PIXBUF, gtk.IMAGE_STOCK]: - raise ValueError('Image must have a storage type of pixbuf or ' + - 'stock, not %r.' % image.get_storage_type()) - _sugarext.IconEntry.set_icon(self, position, image) - - def remove_icon(self, position): - _sugarext.IconEntry.set_icon(self, position, None) - - def add_clear_button(self): - if self.props.text != "": - self.show_clear_button() - else: - self.hide_clear_button() - - self.connect('icon-pressed', self._icon_pressed_cb) - self.connect('changed', self._changed_cb) - - def show_clear_button(self): - if not self._clear_shown: - self.set_icon_from_name(ICON_ENTRY_SECONDARY, - 'dialog-cancel') - self._clear_shown = True - - def hide_clear_button(self): - if self._clear_shown: - self.remove_icon(ICON_ENTRY_SECONDARY) - self._clear_shown = False - - def _keypress_event_cb(self, widget, event): - keyval = gtk.gdk.keyval_name(event.keyval) - if keyval == 'Escape': - self.props.text = '' - return True - return False - - def _icon_pressed_cb(self, entru, icon_pos, button): - if icon_pos == ICON_ENTRY_SECONDARY: - self.set_text('') - self.hide_clear_button() - - def _changed_cb(self, icon_entry): - if not self.props.text: - self.hide_clear_button() - else: - self.show_clear_button() - diff --git a/lib/sugar/graphics/menuitem.py b/lib/sugar/graphics/menuitem.py deleted file mode 100644 index 908cc1f..0000000 --- a/lib/sugar/graphics/menuitem.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (C) 2007, Eduardo Silva -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk -from sugar.graphics.icon import Icon - -import pango - -class MenuItem(gtk.ImageMenuItem): - def __init__(self, text_label=None, icon_name=None, text_maxlen=0): - gtk.ImageMenuItem.__init__(self, text_label) - if icon_name: - icon = Icon(icon_name=icon_name, icon_size=gtk.ICON_SIZE_MENU) - self.set_image(icon) - icon.show() - - if text_maxlen > 0: - self.child.set_ellipsize(pango.ELLIPSIZE_MIDDLE) - self.child.set_max_width_chars(text_maxlen) diff --git a/lib/sugar/graphics/notebook.py b/lib/sugar/graphics/notebook.py deleted file mode 100644 index 2d49b1f..0000000 --- a/lib/sugar/graphics/notebook.py +++ /dev/null @@ -1,115 +0,0 @@ -"""Notebook class - -This class create a gtk.Notebook() widget supporting -a close button in every tab when the 'can-close-tabs' gproperty -is enabled (True) -""" - -# Copyright (C) 2007, Eduardo Silva (edsiper@gmail.com) -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk -import gobject - -class Notebook(gtk.Notebook): - __gtype_name__ = 'SugarNotebook' - - __gproperties__ = { - 'can-close-tabs': (bool, None, None, False, - gobject.PARAM_READWRITE | gobject.PARAM_CONSTRUCT_ONLY) - } - - def __init__(self, **kwargs): - # Initialise the Widget - # - # Side effects: - # Set the 'can-close-tabs' property using **kwargs - # Set True the scrollable notebook property - - gobject.GObject.__init__(self, **kwargs) - gtk.Notebook.__init__(self) - - self.set_scrollable(True) - self.show() - - def do_set_property(self, pspec, value): - if pspec.name == 'can-close-tabs': - self._can_close_tabs = value - else: - raise AssertionError - - def _add_icon_to_button(self, button): - icon_box = gtk.HBox() - image = gtk.Image() - image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU) - gtk.Button.set_relief(button, gtk.RELIEF_NONE) - - settings = gtk.Widget.get_settings(button) - (w,h) = gtk.icon_size_lookup_for_settings(settings, gtk.ICON_SIZE_MENU) - gtk.Widget.set_size_request(button, w + 4, h + 4) - image.show() - icon_box.pack_start(image, True, False, 0) - button.add(icon_box) - icon_box.show() - - def _create_custom_tab(self, text, child): - event_box = gtk.EventBox() - - tab_box = gtk.HBox(False, 2) - tab_label = gtk.Label(text) - - tab_button = gtk.Button() - tab_button.connect('clicked', self._close_page, child) - - # Add a picture on a button - self._add_icon_to_button(tab_button) - icon_box = gtk.HBox(False, 0) - - event_box.show() - tab_button.show() - tab_label.show() - - tab_box.pack_start(tab_label, True) - tab_box.pack_start(tab_button, True) - - tab_box.show_all() - event_box.add(tab_box) - - return event_box - - def add_page(self, text_label, widget): - # Add a new page to the notebook - if self._can_close_tabs: - eventbox = self._create_custom_tab(text_label, widget) - self.append_page(widget, eventbox) - else: - self.append_page(widget, gtk.Label(text_label)) - - pages = self.get_n_pages() - - # Set the new page - self.set_current_page(pages - 1) - self.show_all() - - return True - - def _close_page(self, button, child): - # Remove a page from the notebook - page = self.page_num(child) - - if page != -1: - self.remove_page(page) diff --git a/lib/sugar/graphics/objectchooser.py b/lib/sugar/graphics/objectchooser.py deleted file mode 100644 index 59f1a8a..0000000 --- a/lib/sugar/graphics/objectchooser.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging -import time - -import gobject -import gtk -import dbus - -from sugar.datastore import datastore - -J_DBUS_SERVICE = 'org.laptop.Journal' -J_DBUS_INTERFACE = 'org.laptop.Journal' -J_DBUS_PATH = '/org/laptop/Journal' - -class ObjectChooser(object): - def __init__(self, title=None, parent=None, flags=None, buttons=None): - # For backwards compatibility: - # - We ignore title, flags and buttons. - # - 'parent' can be a xid or a gtk.gdk.Window - - if title is not None or flags is not None or buttons is not None: - logging.warning('Invocation of ObjectChooser() has deprecated ' - 'parameters.') - - if parent is None: - parent_xid = 0 - elif hasattr(parent, 'window') and hasattr(parent.window, 'xid'): - parent_xid = parent.window.xid - else: - parent_xid = parent - - self._parent_xid = parent_xid - self._main_loop = None - self._object_id = None - self._bus = None - self._chooser_id = None - self._response_code = gtk.RESPONSE_NONE - - def run(self): - self._object_id = None - - self._main_loop = gobject.MainLoop() - - self._bus = dbus.SessionBus(mainloop=self._main_loop) - self._bus.add_signal_receiver( - self.__name_owner_changed_cb, - signal_name="NameOwnerChanged", - dbus_interface="org.freedesktop.DBus", - arg0=J_DBUS_SERVICE) - - obj = self._bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH) - journal = dbus.Interface(obj, J_DBUS_INTERFACE) - journal.connect_to_signal('ObjectChooserResponse', - self.__chooser_response_cb) - journal.connect_to_signal('ObjectChooserCancelled', - self.__chooser_cancelled_cb) - self._chooser_id = journal.ChooseObject(self._parent_xid) - - gtk.gdk.threads_leave() - try: - self._main_loop.run() - finally: - gtk.gdk.threads_enter() - self._main_loop = None - - return self._response_code - - def get_selected_object(self): - if self._object_id is None: - return None - else: - return datastore.get(self._object_id) - - def destroy(self): - self._cleanup() - - def _cleanup(self): - if self._main_loop is not None: - self._main_loop.quit() - self._main_loop = None - self._bus = None - - def __chooser_response_cb(self, chooser_id, object_id): - if chooser_id != self._chooser_id: - return - logging.debug('ObjectChooser.__chooser_response_cb: %r' % object_id) - self._response_code = gtk.RESPONSE_ACCEPT - self._object_id = object_id - self._cleanup() - - def __chooser_cancelled_cb(self, chooser_id): - if chooser_id != self._chooser_id: - return - logging.debug('ObjectChooser.__chooser_cancelled_cb: %r' % chooser_id) - self._response_code = gtk.RESPONSE_CANCEL - self._cleanup() - - def __name_owner_changed_cb(self, name, old, new): - logging.debug('ObjectChooser.__name_owner_changed_cb') - # Journal service disappeared from the bus - self._response_code = gtk.RESPONSE_CANCEL - self._cleanup() - diff --git a/lib/sugar/graphics/palette.py b/lib/sugar/graphics/palette.py deleted file mode 100644 index 85e60ac..0000000 --- a/lib/sugar/graphics/palette.py +++ /dev/null @@ -1,877 +0,0 @@ -# Copyright (C) 2007, Eduardo Silva -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging - -import gtk -import gobject -import time -import hippo -import pango - -from sugar.graphics import palettegroup -from sugar.graphics import animator -from sugar.graphics import style -from sugar import _sugarext - -# Helper function to find the gap position and size of widget a -def _calculate_gap(a, b): - # Test for each side if the palette and invoker are - # adjacent to each other. - gap = True - - if a.y + a.height == b.y: - gap_side = gtk.POS_BOTTOM - elif a.x + a.width == b.x: - gap_side = gtk.POS_RIGHT - elif a.x == b.x + b.width: - gap_side = gtk.POS_LEFT - elif a.y == b.y + b.height: - gap_side = gtk.POS_TOP - else: - gap = False - - if gap: - if gap_side == gtk.POS_BOTTOM or gap_side == gtk.POS_TOP: - gap_start = min(a.width, max(0, b.x - a.x)) - gap_size = max(0, min(a.width, - (b.x + b.width) - a.x) - gap_start) - elif gap_side == gtk.POS_RIGHT or gap_side == gtk.POS_LEFT: - gap_start = min(a.height, max(0, b.y - a.y)) - gap_size = max(0, min(a.height, - (b.y + b.height) - a.y) - gap_start) - - if gap and gap_size > 0: - return (gap_side, gap_start, gap_size) - else: - return False - -class MouseSpeedDetector(gobject.GObject): - - __gsignals__ = { - 'motion-slow': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - 'motion-fast': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - } - - _MOTION_SLOW = 1 - _MOTION_FAST = 2 - - def __init__(self, parent, delay, thresh): - """Create MouseSpeedDetector object, - delay in msec - threshold in pixels (per tick of 'delay' msec)""" - - gobject.GObject.__init__(self) - - self._threshold = thresh - self._parent = parent - self._delay = delay - - self._state = None - - self._timeout_hid = None - - def start(self): - self._state = None - self._mouse_pos = self._get_mouse_position() - - self._timeout_hid = gobject.timeout_add(self._delay, self._timer_cb) - - def stop(self): - if self._timeout_hid is not None: - gobject.source_remove(self._timeout_hid) - self._state = None - - def _get_mouse_position(self): - display = gtk.gdk.display_get_default() - screen, x, y, mask = display.get_pointer() - return (x, y) - - def _detect_motion(self): - oldx, oldy = self._mouse_pos - (x, y) = self._get_mouse_position() - self._mouse_pos = (x, y) - - dist2 = (oldx - x)**2 + (oldy - y)**2 - if dist2 > self._threshold**2: - return True - else: - return False - - def _timer_cb(self): - motion = self._detect_motion() - if motion and self._state != self._MOTION_FAST: - self.emit('motion-fast') - self._state = self._MOTION_FAST - elif not motion and self._state != self._MOTION_SLOW: - self.emit('motion-slow') - self._state = self._MOTION_SLOW - - return True - -class Palette(gtk.Window): - PRIMARY = 0 - SECONDARY = 1 - - __gtype_name__ = 'SugarPalette' - - __gproperties__ = { - 'invoker' : (object, None, None, - gobject.PARAM_READWRITE) - } - - __gsignals__ = { - 'popup' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - 'popdown' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])) - } - - def __init__(self, label, accel_path=None, menu_after_content=False, - text_maxlen=0): - gtk.Window.__init__(self) - - self.set_decorated(False) - self.set_resizable(False) - # Just assume xthickness and ythickness are the same - self.set_border_width(self.style.xthickness) - self.connect('realize', self._realize_cb) - self.connect('destroy', self.__destroy_cb) - - self.palette_state = self.PRIMARY - - self._alignment = None - self._old_alloc = None - self._full_request = [0, 0] - self._cursor_x = 0 - self._cursor_y = 0 - self._invoker = None - self._group_id = None - self._up = False - self._palette_popup_sid = None - - self._popup_anim = animator.Animator(0.3, 10) - self._popup_anim.add(_PopupAnimation(self)) - - self._secondary_anim = animator.Animator(1.0, 10) - self._secondary_anim.add(_SecondaryAnimation(self)) - - self._popdown_anim = animator.Animator(0.6, 10) - self._popdown_anim.add(_PopdownAnimation(self)) - - vbox = gtk.VBox() - - self._label = gtk.Label() - self._label.set_size_request(-1, style.zoom(style.GRID_CELL_SIZE) - - 2*self.get_border_width()) - self._label.set_alignment(0, 0.5) - self._label.set_padding(style.DEFAULT_SPACING, 0) - - if text_maxlen > 0: - self._label.set_max_width_chars(text_maxlen) - self._label.set_ellipsize(pango.ELLIPSIZE_MIDDLE) - - vbox.pack_start(self._label, False) - - self._secondary_box = gtk.VBox() - vbox.pack_start(self._secondary_box) - - self._separator = gtk.HSeparator() - self._secondary_box.pack_start(self._separator) - - self._menu_content_separator = gtk.HSeparator() - - if menu_after_content: - self._add_content() - self._secondary_box.pack_start(self._menu_content_separator) - self._add_menu() - else: - self._add_menu() - self._secondary_box.pack_start(self._menu_content_separator) - self._add_content() - - self.action_bar = PaletteActionBar() - self._secondary_box.pack_start(self.action_bar) - self.action_bar.show() - - self.add(vbox) - vbox.show() - - # The menu is not shown here until an item is added - self.menu = _Menu(self) - - self.connect('enter-notify-event', - self._enter_notify_event_cb) - self.connect('leave-notify-event', - self._leave_notify_event_cb) - - self.set_primary_text(label, accel_path) - self.set_group_id('default') - - self._mouse_detector = MouseSpeedDetector(self, 200, 5) - self._mouse_detector.connect('motion-slow', self._mouse_slow_cb) - - def __destroy_cb(self, palette): - self.set_group_id(None) - - if self._palette_popup_sid is not None: - _palette_observer.disconnect(self._palette_popup_sid) - - def _add_menu(self): - self._menu_box = gtk.VBox() - self._secondary_box.pack_start(self._menu_box) - self._menu_box.show() - - def _add_content(self): - # The content is not shown until a widget is added - self._content = gtk.VBox() - self._content.set_border_width(style.DEFAULT_SPACING) - self._secondary_box.pack_start(self._content) - - def do_style_set(self, previous_style): - # Prevent a warning from pygtk - if previous_style is not None: - gtk.Window.do_style_set(self, previous_style) - self.set_border_width(self.style.xthickness) - - def is_up(self): - return self._up - - def get_rect(self): - win_x, win_y = self.window.get_origin() - rectangle = self.get_allocation() - - x = win_x + rectangle.x - y = win_y + rectangle.y - width = rectangle.width - height = rectangle.height - - return gtk.gdk.Rectangle(x, y, width, height) - - def set_primary_text(self, label, accel_path=None): - if label is not None: - self._label.set_markup(""+label+"") - self._label.show() - - def set_content(self, widget): - if len(self._content.get_children()) > 0: - self._content.remove(self._content.get_children()[0]) - - if widget is not None: - self._content.add(widget) - self._content.show() - else: - self._content.hide() - - self._update_accept_focus() - self._update_separators() - - def set_group_id(self, group_id): - if self._group_id: - group = palettegroup.get_group(self._group_id) - group.remove(self) - if group_id: - self._group_id = group_id - group = palettegroup.get_group(group_id) - group.add(self) - - def do_set_property(self, pspec, value): - if pspec.name == 'invoker': - if self._invoker is not None: - self._invoker.disconnect(self._enter_invoker_hid) - self._invoker.disconnect(self._leave_invoker_hid) - - self._invoker = value - if value is not None: - self._enter_invoker_hid = self._invoker.connect( - 'mouse-enter', self._invoker_mouse_enter_cb) - self._leave_invoker_hid = self._invoker.connect( - 'mouse-leave', self._invoker_mouse_leave_cb) - else: - raise AssertionError - - def do_get_property(self, pspec): - if pspec.name == 'invoker': - return self._invoker - else: - raise AssertionError - - def do_size_request(self, requisition): - gtk.Window.do_size_request(self, requisition) - - requisition.width = max(requisition.width, self._full_request[0]) - - # Minimum width - requisition.width = max(requisition.width, - style.zoom(style.GRID_CELL_SIZE*2)) - - def do_size_allocate(self, allocation): - gtk.Window.do_size_allocate(self, allocation) - - if self._old_alloc is None or \ - self._old_alloc.x != allocation.x or \ - self._old_alloc.y != allocation.y or \ - self._old_alloc.width != allocation.width or \ - self._old_alloc.height != allocation.height: - self.queue_draw() - - # We need to store old allocation because when size_allocate - # is called widget.allocation is already updated. - # gtk.Window resizing is different from normal containers: - # the X window is resized, widget.allocation is updated from - # the configure request handler and finally size_allocate is called. - self._old_alloc = allocation - - def do_expose_event(self, event): - # We want to draw a border with a beautiful gap - if self._invoker is not None and self._invoker.has_rectangle_gap(): - invoker = self._invoker.get_rect() - palette = self.get_rect() - - gap = _calculate_gap(palette, invoker) - else: - gap = False - - if gap: - self.style.paint_box_gap(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self, "palette", - 0, 0, - self.allocation.width, - self.allocation.height, - gap[0], gap[1], gap[2]) - else: - self.style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self, "palette", - 0, 0, - self.allocation.width, - self.allocation.height) - - # Fall trough to the container expose handler. - # (Leaving out the window expose handler which redraws everything) - gtk.Bin.do_expose_event(self, event) - - def _update_separators(self): - visible = len(self.menu.get_children()) > 0 or \ - len(self._content.get_children()) > 0 - self._separator.props.visible = visible - - visible = len(self.menu.get_children()) > 0 and \ - len(self._content.get_children()) > 0 - self._menu_content_separator.props.visible = visible - - def _update_accept_focus(self): - accept_focus = len(self._content.get_children()) - if self.window: - self.window.set_accept_focus(accept_focus) - - def _realize_cb(self, widget): - self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - self._update_accept_focus() - - def _update_full_request(self): - state = self.palette_state - - self._set_state(self.SECONDARY) - self._full_request = self.size_request() - - self._set_state(state) - - def _update_position(self): - invoker = self._invoker - if invoker is None or self._alignment is None: - logging.error('Cannot update the palette position.') - return - - rect = self.size_request() - position = invoker.get_position_for_alignment(self._alignment, rect) - if position is None: - position = invoker.get_position(rect) - - self.move(position.x, position.y) - - def _show(self): - if self._up: - return - - self._palette_popup_sid = _palette_observer.connect( - 'popup', self._palette_observer_popup_cb) - - if self._invoker is not None: - self._update_full_request() - self._alignment = self._invoker.get_alignment(self._full_request) - self._update_position() - - self.menu.set_active(True) - self.show() - - self._invoker.notify_popup() - - self._up = True - _palette_observer.emit('popup', self) - self.emit('popup') - - def _hide(self): - self._secondary_anim.stop() - - if not self._palette_popup_sid is None: - _palette_observer.disconnect(self._palette_popup_sid) - self._palette_popup_sid = None - - self.menu.set_active(False) - self.hide() - - if self._invoker: - self._invoker.notify_popdown() - - self._up = False - self.emit('popdown') - - def popup(self, immediate=False): - self._popdown_anim.stop() - - if not immediate: - self._popup_anim.start() - else: - self._show() - - self._secondary_anim.start() - - def popdown(self, immediate=False): - self._popup_anim.stop() - - self._mouse_detector.stop() - - if not immediate: - self._popdown_anim.start() - else: - self._hide() - - def _set_state(self, state): - if self.palette_state == state: - return - - if state == self.PRIMARY: - self.menu.unembed() - self._secondary_box.hide() - elif state == self.SECONDARY: - self.menu.embed(self._menu_box) - self._secondary_box.show() - - self.palette_state = state - - def _invoker_mouse_enter_cb(self, invoker): - self._mouse_detector.start() - - def _mouse_slow_cb(self, widget): - self._mouse_detector.stop() - self._palette_do_popup() - - def _palette_do_popup(self): - immediate = False - - if self.is_up(): - self._popdown_anim.stop() - return - - if self._group_id: - group = palettegroup.get_group(self._group_id) - if group and group.is_up(): - self._set_state(self.PRIMARY) - - immediate = True - group.popdown() - - self.popup(immediate=immediate) - - def _invoker_mouse_leave_cb(self, invoker): - self._mouse_detector.stop() - self.popdown() - - def _enter_notify_event_cb(self, widget, event): - if event.detail != gtk.gdk.NOTIFY_INFERIOR: - self._popdown_anim.stop() - self._secondary_anim.start() - - def _leave_notify_event_cb(self, widget, event): - if event.detail != gtk.gdk.NOTIFY_INFERIOR: - self.popdown() - - def _palette_observer_popup_cb(self, observer, palette): - if self != palette: - self._hide() - -class PaletteActionBar(gtk.HButtonBox): - def add_action(label, icon_name=None): - button = Button(label) - - if icon_name: - icon = Icon(icon_name) - button.set_image(icon) - icon.show() - - self.pack_start(button) - button.show() - -class _Menu(_sugarext.Menu): - __gtype_name__ = 'SugarPaletteMenu' - - def __init__(self, palette): - _sugarext.Menu.__init__(self) - self._palette = palette - - def do_insert(self, item, position): - _sugarext.Menu.do_insert(self, item, position) - self._palette._update_separators() - self.show() - - def do_expose_event(self, event): - # Ignore the Menu expose, just do the MenuShell expose to prevent any - # border from being drawn here. A border is drawn by the palette object - # around everything. - gtk.MenuShell.do_expose_event(self, event) - - def do_grab_notify(self, was_grabbed): - # Ignore grab_notify as the menu would close otherwise - pass - - def do_deactivate(self): - self._palette._hide() - -class _PopupAnimation(animator.Animation): - def __init__(self, palette): - animator.Animation.__init__(self, 0.0, 1.0) - self._palette = palette - - def next_frame(self, current): - if current == 1.0: - self._palette._set_state(Palette.PRIMARY) - self._palette._show() - -class _SecondaryAnimation(animator.Animation): - def __init__(self, palette): - animator.Animation.__init__(self, 0.0, 1.0) - self._palette = palette - - def next_frame(self, current): - if current == 1.0: - self._palette._set_state(Palette.SECONDARY) - self._palette._update_position() - -class _PopdownAnimation(animator.Animation): - def __init__(self, palette): - animator.Animation.__init__(self, 0.0, 1.0) - self._palette = palette - - def next_frame(self, current): - if current == 1.0: - self._palette._hide() - -class Invoker(gobject.GObject): - __gtype_name__ = 'SugarPaletteInvoker' - - __gsignals__ = { - 'mouse-enter': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - 'mouse-leave': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), - 'focus-out': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) - } - - ANCHORED = 0 - AT_CURSOR = 1 - - BOTTOM = [(0.0, 0.0, 0.0, 1.0), - (-1.0, 0.0, 1.0, 1.0)] - RIGHT = [(0.0, 0.0, 1.0, 0.0), - (0.0, -1.0, 1.0, 1.0)] - TOP = [(0.0, -1.0, 0.0, 0.0), - (-1.0, -1.0, 1.0, 0.0)] - LEFT = [(-1.0, 0.0, 0.0, 0.0), - (-1.0, -1.0, 0.0, 1.0)] - - def __init__(self): - gobject.GObject.__init__(self) - - self._screen_area = gtk.gdk.Rectangle(0, 0, gtk.gdk.screen_width(), - gtk.gdk.screen_height()) - self._position_hint = self.ANCHORED - self._cursor_x = -1 - self._cursor_y = -1 - - def _get_position_for_alignment(self, alignment, palette_dim): - palette_halign = alignment[0] - palette_valign = alignment[1] - invoker_halign = alignment[2] - invoker_valign = alignment[3] - - if self._cursor_x == -1 or self._cursor_y == -1: - display = gtk.gdk.display_get_default() - screen, x, y, mask = display.get_pointer() - self._cursor_x = x - self._cursor_y = y - - if self._position_hint is self.ANCHORED: - rect = self.get_rect() - else: - dist = style.PALETTE_CURSOR_DISTANCE - rect = gtk.gdk.Rectangle(self._cursor_x - dist, - self._cursor_y - dist, - dist * 2, dist * 2) - - palette_width, palette_height = palette_dim - - x = rect.x + rect.width * invoker_halign + \ - palette_width * palette_halign - - y = rect.y + rect.height * invoker_valign + \ - palette_height * palette_valign - - return gtk.gdk.Rectangle(int(x), int(y), - palette_width, palette_height) - - def _in_screen(self, rect): - return rect.x >= self._screen_area.x and \ - rect.y >= self._screen_area.y and \ - rect.x + rect.width <= self._screen_area.width and \ - rect.y + rect.height <= self._screen_area.height - - def _get_area_in_screen(self, rect): - """Return area of rectangle visible in the screen""" - - x1 = max(rect.x, self._screen_area.x) - y1 = max(rect.y, self._screen_area.y) - x2 = min(rect.x + rect.width, - self._screen_area.x + self._screen_area.width) - y2 = min(rect.y + rect.height, - self._screen_area.y + self._screen_area.height) - - return (x2 - x1) * (y2 - y1) - - def _get_alignments(self): - if self._position_hint is self.AT_CURSOR: - return [(0.0, 0.0, 1.0, 1.0), - (0.0, -1.0, 1.0, 0.0), - (-1.0, -1.0, 0.0, 0.0), - (-1.0, 0.0, 0.0, 1.0)] - else: - return self.BOTTOM + self.RIGHT + self.TOP + self.LEFT - - def get_position_for_alignment(self, alignment, palette_dim): - rect = self._get_position_for_alignment(alignment, palette_dim) - if self._in_screen(rect): - return rect - else: - return None - - def get_position(self, palette_dim): - alignment = self.get_alignment(palette_dim) - return self._get_position_for_alignment(alignment, palette_dim) - - def get_alignment(self, palette_dim): - best_alignment = None - best_area = -1 - for alignment in self._get_alignments(): - pos = self._get_position_for_alignment(alignment, palette_dim) - if self._in_screen(pos): - return alignment - - area = self._get_area_in_screen(pos) - if area > best_area: - best_alignment = alignment - best_area = area - - # Palette horiz/vert alignment - ph = best_alignment[0] - pv = best_alignment[1] - - # Invoker horiz/vert alignment - ih = best_alignment[2] - iv = best_alignment[3] - - rect = self.get_rect() - screen_area = self._screen_area - - if best_alignment in self.LEFT or best_alignment in self.RIGHT: - dtop = rect.y - screen_area.y - dbottom = screen_area.y + screen_area.height - rect.y - rect.width - - iv = 0 - - # Set palette_valign to align to screen on the top - if dtop > dbottom: - pv = -float(dtop) / palette_dim[1] - - # Set palette_valign to align to screen on the bottom - else: - pv = -float(palette_dim[1] - dbottom - rect.height) \ - / palette_dim[1] - - else: - dleft = rect.x - screen_area.x - dright = screen_area.x + screen_area.width - rect.x - rect.width - - ih = 0 - - # Set palette_halign to align to screen on left - if dleft > dright: - ph = -float(dleft) / palette_dim[0] - - # Set palette_halign to align to screen on right - else: - ph = -float(palette_dim[0] - dright - rect.width) \ - / palette_dim[0] - - return (ph, pv, ih, iv) - - def has_rectangle_gap(self): - return False - - def draw_rectangle(self, event, palette): - pass - - def notify_popup(self): - pass - - def notify_popdown(self): - self._cursor_x = -1 - self._cursor_y = -1 - -class WidgetInvoker(Invoker): - def __init__(self, widget): - Invoker.__init__(self) - self._widget = widget - - widget.connect('enter-notify-event', self._enter_notify_event_cb) - widget.connect('leave-notify-event', self._leave_notify_event_cb) - - def get_rect(self): - allocation = self._widget.get_allocation() - if self._widget.window is not None: - x, y = self._widget.window.get_origin() - else: - logging.warning( - "Trying to position palette with invoker that's not realized.") - x = 0 - y = 0 - - if self._widget.flags() & gtk.NO_WINDOW: - x += allocation.x - y += allocation.y - - width = allocation.width - height = allocation.height - - return gtk.gdk.Rectangle(x, y, width, height) - - def has_rectangle_gap(self): - return True - - def draw_rectangle(self, event, palette): - style = self._widget.style - gap = _calculate_gap(self.get_rect(), palette.get_rect()) - if gap: - style.paint_box_gap(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self._widget, - "palette-invoker", - self._widget.allocation.x, - self._widget.allocation.y, - self._widget.allocation.width, - self._widget.allocation.height, - gap[0], gap[1], gap[2]) - else: - style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_IN, event.area, self._widget, - "palette-invoker", - self._widget.allocation.x, - self._widget.allocation.y, - self._widget.allocation.width, - self._widget.allocation.height) - - def _enter_notify_event_cb(self, widget, event): - self.emit('mouse-enter') - - def _leave_notify_event_cb(self, widget, event): - self.emit('mouse-leave') - - def get_toplevel(self): - return self._widget.get_toplevel() - - def notify_popup(self): - Invoker.notify_popup(self) - self._widget.queue_draw() - - def notify_popdown(self): - Invoker.notify_popdown(self) - self._widget.queue_draw() - -class CanvasInvoker(Invoker): - def __init__(self, item): - Invoker.__init__(self) - - self._item = item - self._position_hint = self.AT_CURSOR - - item.connect('motion-notify-event', - self._motion_notify_event_cb) - - def get_default_position(self): - return self.AT_CURSOR - - def get_rect(self): - context = self._item.get_context() - if context: - x, y = context.translate_to_screen(self._item) - width, height = self._item.get_allocation() - return gtk.gdk.Rectangle(x, y, width, height) - else: - return gtk.gdk.Rectangle() - - def _motion_notify_event_cb(self, button, event): - if event.detail == hippo.MOTION_DETAIL_ENTER: - context = self._item.get_context() - self.emit('mouse-enter') - elif event.detail == hippo.MOTION_DETAIL_LEAVE: - self.emit('mouse-leave') - - return False - - def get_toplevel(self): - return hippo.get_canvas_for_item(self._item).get_toplevel() - -class ToolInvoker(WidgetInvoker): - def __init__(self, widget): - WidgetInvoker.__init__(self, widget.child) - - def _get_alignments(self): - parent = self._widget.get_parent() - if parent is None: - return WidgetInvoker.get_alignments() - - if parent.get_orientation() is gtk.ORIENTATION_HORIZONTAL: - return self.BOTTOM + self.TOP - else: - return self.LEFT + self.RIGHT - -class _PaletteObserver(gobject.GObject): - __gtype_name__ = 'SugarPaletteObserver' - - __gsignals__ = { - 'popup': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])) - } - - def __init__(self): - gobject.GObject.__init__(self) - -_palette_observer = _PaletteObserver() diff --git a/lib/sugar/graphics/palettegroup.py b/lib/sugar/graphics/palettegroup.py deleted file mode 100644 index bdae76b..0000000 --- a/lib/sugar/graphics/palettegroup.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) 2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gobject - -_groups = {} - -def get_group(group_id): - if _groups.has_key(group_id): - group = _groups[group_id] - else: - group = Group() - _groups[group_id] = group - - return group - -class Group(gobject.GObject): - __gsignals__ = { - 'popup' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - 'popdown' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])) - } - def __init__(self): - gobject.GObject.__init__(self) - self._up = False - self._palettes = [] - self._sig_ids = {} - - def is_up(self): - return self._up - - def get_state(self): - for palette in self._palettes: - if palette.is_up(): - return palette.palette_state - - return None - - def add(self, palette): - self._palettes.append(palette) - - self._sig_ids[palette] = [] - - sid = palette.connect('popup', self._palette_popup_cb) - self._sig_ids[palette].append(sid) - - sid = palette.connect('popdown', self._palette_popdown_cb) - self._sig_ids[palette].append(sid) - - def remove(self, palette): - sig_ids = self._sig_ids[palette] - for sid in sig_ids: - palette.disconnect(sid) - - self._palettes.remove(palette) - del self._sig_ids[palette] - - def popdown(self): - for palette in self._palettes: - if palette.is_up(): - palette.popdown(immediate=True) - - def _palette_popup_cb(self, palette): - if not self._up: - self.emit('popup') - self._up = True - - def _palette_popdown_cb(self, palette): - down = True - for palette in self._palettes: - if palette.is_up(): - down = False - - if down: - self._up = False - self.emit('popdown') diff --git a/lib/sugar/graphics/panel.py b/lib/sugar/graphics/panel.py deleted file mode 100644 index bf3ed24..0000000 --- a/lib/sugar/graphics/panel.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk - -class Panel(gtk.VBox): - __gtype_name__ = 'SugarPanel' - def __init__(self): - gtk.VBox.__init__(self) diff --git a/lib/sugar/graphics/radiotoolbutton.py b/lib/sugar/graphics/radiotoolbutton.py deleted file mode 100644 index cb4ae25..0000000 --- a/lib/sugar/graphics/radiotoolbutton.py +++ /dev/null @@ -1,67 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk - -from sugar.graphics.icon import Icon -from sugar.graphics.palette import Palette, ToolInvoker - -class RadioToolButton(gtk.RadioToolButton): - __gtype_name__ = "SugarRadioToolButton" - - def __init__(self, named_icon=None, group=None, xo_color=None): - gtk.RadioToolButton.__init__(self, group=group) - self._palette = None - self._xo_color = xo_color - self.set_named_icon(named_icon) - - def set_named_icon(self, named_icon): - icon = Icon(icon_name=named_icon, - xo_color=self._xo_color, - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) - self.set_icon_widget(icon) - icon.show() - - def get_palette(self): - return self._palette - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - self._palette.props.invoker = ToolInvoker(self) - - def set_tooltip(self, text): - self.set_palette(Palette(text)) - - def do_expose_event(self, event): - if self._palette and self._palette.is_up(): - invoker = self._palette.props.invoker - invoker.draw_rectangle(event, self._palette) - elif self.child.state == gtk.STATE_PRELIGHT: - self.child.style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_NONE, event.area, - self.child, "toolbutton-prelight", - self.allocation.x, - self.allocation.y, - self.allocation.width, - self.allocation.height) - - gtk.RadioToolButton.do_expose_event(self, event) - - palette = property(get_palette, set_palette) diff --git a/lib/sugar/graphics/roundbox.py b/lib/sugar/graphics/roundbox.py deleted file mode 100644 index 51b9e7d..0000000 --- a/lib/sugar/graphics/roundbox.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import math - -import hippo - -from sugar.graphics import style - -class CanvasRoundBox(hippo.CanvasBox, hippo.CanvasItem): - __gtype_name__ = 'SugarRoundBox' - - _BORDER_DEFAULT = style.LINE_WIDTH - - def __init__(self, **kwargs): - hippo.CanvasBox.__init__(self, **kwargs) - - # TODO: we should calculate this value depending on the height of the box. - self._radius = style.zoom(10) - - self.props.orientation = hippo.ORIENTATION_HORIZONTAL - self.props.border = self._BORDER_DEFAULT - self.props.border_left = self._radius - self.props.border_right = self._radius - self.props.border_color = style.COLOR_BLACK.get_int() - - def do_paint_background(self, cr, damaged_box): - [width, height] = self.get_allocation() - - x = self._BORDER_DEFAULT / 2 - y = self._BORDER_DEFAULT / 2 - width -= self._BORDER_DEFAULT - height -= self._BORDER_DEFAULT - - cr.move_to(x + self._radius, y); - cr.arc(x + width - self._radius, y + self._radius, - self._radius, math.pi * 1.5, math.pi * 2); - cr.arc(x + width - self._radius, x + height - self._radius, - self._radius, 0, math.pi * 0.5); - cr.arc(x + self._radius, y + height - self._radius, - self._radius, math.pi * 0.5, math.pi); - cr.arc(x + self._radius, y + self._radius, self._radius, - math.pi, math.pi * 1.5); - - hippo.cairo_set_source_rgba32(cr, self.props.background_color) - cr.fill_preserve(); - - # TODO: we should be more consistent here with the border properties. - if self.props.border_color: - hippo.cairo_set_source_rgba32(cr, self.props.border_color) - cr.set_line_width(self.props.border_top) - cr.stroke() diff --git a/lib/sugar/graphics/style.py b/lib/sugar/graphics/style.py deleted file mode 100644 index 1f97adc..0000000 --- a/lib/sugar/graphics/style.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -All the constants are expressed in pixels. They are defined for the XO screen -and are usually adapted to different resolution by applying a zoom factor. The -factor for traditional 96 dpi screen is currently 0.72 which is the inverse -of the one we are using to adapt web pages to the XO screen. It should be -considered a reference value rather then a scale constant which has to be -automatically applied and always respected. -""" - -import os - -import gtk -import pango - -_XO_DPI = 200.0 - -_FOCUS_LINE_WIDTH = 2 -_TAB_CURVATURE = 1 - -def _get_screen_dpi(): - xft_dpi = gtk.settings_get_default().get_property('gtk-xft-dpi') - return float(xft_dpi / 1024) - -def _compute_zoom_factor(): - if _get_screen_dpi() == 96.0: - if not os.environ.has_key('SUGAR_XO_STYLE') or \ - not os.environ['SUGAR_XO_STYLE'] == 'yes': - return 0.72 - - return 1.0 - -def _compute_font_height(font): - widget = gtk.Label('') - - context = widget.get_pango_context() - pango_font = context.load_font(font.get_pango_desc()) - metrics = pango_font.get_metrics() - - return pango.PIXELS(metrics.get_ascent() + metrics.get_descent()) - -class Font(object): - def __init__(self, desc): - self._desc = desc - - def __str__(self): - return self._desc - - def get_pango_desc(self): - return pango.FontDescription(self._desc) - -class Color(object): - def __init__(self, color, alpha=1.0): - self._r, self._g, self._b = self._html_to_rgb(color) - self._a = alpha - - def get_rgba(self): - return (self._r, self._g, self._b, self._a) - - def get_int(self): - return int(self._a * 255) + (int(self._b * 255) << 8) + \ - (int(self._g * 255) << 16) + (int(self._r * 255) << 24) - - def get_gdk_color(self): - return gtk.gdk.Color(int(self._r * 65535), int(self._g * 65535), - int(self._b * 65535)) - - def get_html(self): - return '#%02x%02x%02x' % (self._r * 255, self._g * 255, self._b * 255) - - def _html_to_rgb(self, html_color): - """ #RRGGBB -> (r, g, b) tuple (in float format) """ - - html_color = html_color.strip() - if html_color[0] == '#': - html_color = html_color[1:] - if len(html_color) != 6: - raise ValueError, "input #%s is not in #RRGGBB format" % html_color - - r, g, b = html_color[:2], html_color[2:4], html_color[4:] - r, g, b = [int(n, 16) for n in (r, g, b)] - r, g, b = (r / 255.0, g / 255.0, b / 255.0) - - return (r, g, b) - - def get_svg(self): - if self._a == 0.0: - return 'none' - else: - return self.get_html() - -def zoom(units): - return int(ZOOM_FACTOR * units) - -ZOOM_FACTOR = _compute_zoom_factor() - -DEFAULT_SPACING = zoom(15) -DEFAULT_PADDING = zoom(6) -GRID_CELL_SIZE = zoom(75) -LINE_WIDTH = zoom(2) - -STANDARD_ICON_SIZE = zoom(55) -SMALL_ICON_SIZE = zoom(55 * 0.5) -MEDIUM_ICON_SIZE = zoom(55 * 1.5) -LARGE_ICON_SIZE = zoom(55 * 2.0) -XLARGE_ICON_SIZE = zoom(55 * 2.75) - -FONT_SIZE = zoom(7 * _XO_DPI / _get_screen_dpi()) -FONT_NORMAL = Font('Bitstream Vera Sans %d' % FONT_SIZE) -FONT_BOLD = Font('Bitstream Vera Sans bold %d' % FONT_SIZE) -FONT_NORMAL_H = _compute_font_height(FONT_NORMAL) -FONT_BOLD_H = _compute_font_height(FONT_BOLD) - -TOOLBOX_SEPARATOR_HEIGHT = zoom(9) -TOOLBOX_HORIZONTAL_PADDING = zoom(75) -TOOLBOX_TAB_VBORDER = int((zoom(36) - FONT_NORMAL_H - _FOCUS_LINE_WIDTH) / 2) -TOOLBOX_TAB_HBORDER = zoom(15) - _FOCUS_LINE_WIDTH - _TAB_CURVATURE -TOOLBOX_TAB_LABEL_WIDTH = zoom(150 - 15 * 2) - -COLOR_BLACK = Color('#000000') -COLOR_WHITE = Color('#FFFFFF') -COLOR_TRANSPARENT = Color('#FFFFFF', alpha=0.0) -COLOR_PANEL_GREY = Color('#C0C0C0') -COLOR_SELECTION_GREY = Color('#A6A6A6') -COLOR_TOOLBAR_GREY = Color('#404040') -COLOR_BUTTON_GREY = Color('#808080') -COLOR_INACTIVE_FILL = Color('#9D9FA1') -COLOR_INACTIVE_STROKE = Color('#757575') -COLOR_TEXT_FIELD_GREY = Color('#E5E5E5') - -PALETTE_CURSOR_DISTANCE = zoom(10) diff --git a/lib/sugar/graphics/toggletoolbutton.py b/lib/sugar/graphics/toggletoolbutton.py deleted file mode 100644 index 3d05cc0..0000000 --- a/lib/sugar/graphics/toggletoolbutton.py +++ /dev/null @@ -1,63 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk - -from sugar.graphics.icon import Icon -from sugar.graphics.palette import Palette, ToolInvoker - -class ToggleToolButton(gtk.ToggleToolButton): - __gtype_name__ = "SugarToggleToolButton" - - def __init__(self, named_icon=None): - gtk.ToggleToolButton.__init__(self) - self._palette = None - self.set_named_icon(named_icon) - - def set_named_icon(self, named_icon): - icon = Icon(icon_name=named_icon) - self.set_icon_widget(icon) - icon.show() - - def get_palette(self): - return self._palette - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - self._palette.props.invoker = ToolInvoker(self) - - def set_tooltip(self, text): - self.set_palette(Palette(text)) - - def do_expose_event(self, event): - if self._palette and self._palette.is_up(): - invoker = self._palette.props.invoker - invoker.draw_rectangle(event, self._palette) - elif self.child.state == gtk.STATE_PRELIGHT: - self.child.style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_NONE, event.area, - self.child, "toolbutton-prelight", - self.allocation.x, - self.allocation.y, - self.allocation.width, - self.allocation.height) - - gtk.ToggleToolButton.do_expose_event(self, event) - - palette = property(get_palette, set_palette) diff --git a/lib/sugar/graphics/toolbox.py b/lib/sugar/graphics/toolbox.py deleted file mode 100644 index 4171d00..0000000 --- a/lib/sugar/graphics/toolbox.py +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk -import gobject -import hippo - -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics import style - -class Toolbox(gtk.VBox): - __gtype_name__ = 'SugarToolbox' - - __gsignals__ = { - 'current-toolbar-changed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([int])) - } - - def __init__(self): - gtk.VBox.__init__(self) - - self._notebook = gtk.Notebook() - self._notebook.set_tab_pos(gtk.POS_BOTTOM) - self._notebook.set_show_border(False) - self._notebook.set_show_tabs(False) - self._notebook.props.tab_vborder = style.TOOLBOX_TAB_VBORDER - self._notebook.props.tab_hborder = style.TOOLBOX_TAB_HBORDER - self.pack_start(self._notebook) - self._notebook.show() - - # FIXME improve gtk.Notebook and do this in the theme - self._separator = hippo.Canvas() - box = hippo.CanvasBox( - border_color=style.COLOR_BUTTON_GREY.get_int(), - background_color=style.COLOR_PANEL_GREY.get_int(), - box_height=style.TOOLBOX_SEPARATOR_HEIGHT, - border_bottom=style.LINE_WIDTH) - self._separator.set_root(box) - self.pack_start(self._separator, False) - - self._notebook.connect('notify::page', self._notify_page_cb) - - def _notify_page_cb(self, notebook, pspec): - self.emit('current-toolbar-changed', notebook.props.page) - - def add_toolbar(self, name, toolbar): - label = gtk.Label(name) - label.set_size_request(style.TOOLBOX_TAB_LABEL_WIDTH, -1) - label.set_alignment(0.0, 0.5) - - event_box = gtk.EventBox() - - alignment = gtk.Alignment(0.0, 0.0, 1.0, 1.0) - alignment.set_padding(0, 0, style.TOOLBOX_HORIZONTAL_PADDING, - style.TOOLBOX_HORIZONTAL_PADDING) - - alignment.add(toolbar) - event_box.add(alignment) - alignment.show() - event_box.show() - - self._notebook.append_page(event_box, label) - - if self._notebook.get_n_pages() > 1: - self._notebook.set_show_tabs(True) - self._separator.show() - - def remove_toolbar(self, index): - self._notebook.remove_page(index) - - if self._notebook.get_n_pages() < 2: - self._notebook.set_show_tabs(False) - self._separator.hide() - - def set_current_toolbar(self, index): - self._notebook.set_current_page(index) - - def get_current_toolbar(self): - return self._notebook.get_current_page() - - current_toolbar = property(get_current_toolbar, set_current_toolbar) - diff --git a/lib/sugar/graphics/toolbutton.py b/lib/sugar/graphics/toolbutton.py deleted file mode 100644 index 26acc83..0000000 --- a/lib/sugar/graphics/toolbutton.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk -import gobject -import time - -from sugar.graphics.icon import Icon -from sugar.graphics.palette import Palette, ToolInvoker - -class ToolButton(gtk.ToolButton): - __gtype_name__ = "SugarToolButton" - - def __init__(self, icon_name=None): - gtk.ToolButton.__init__(self) - self._palette = None - if icon_name: - self.set_icon(icon_name) - self.connect('clicked', self._button_clicked_cb) - - def set_icon(self, icon_name): - icon = Icon(icon_name=icon_name) - self.set_icon_widget(icon) - icon.show() - - def get_palette(self): - return self._palette - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - self._palette.props.invoker = ToolInvoker(self) - - def set_tooltip(self, text): - self.set_palette(Palette(text)) - - # Set label, shows up when toolbar overflows - self.set_label(text) - - def do_expose_event(self, event): - if self._palette and self._palette.is_up(): - invoker = self._palette.props.invoker - invoker.draw_rectangle(event, self._palette) - elif self.child.state == gtk.STATE_PRELIGHT: - self.child.style.paint_box(event.window, gtk.STATE_PRELIGHT, - gtk.SHADOW_NONE, event.area, - self.child, "toolbutton-prelight", - self.allocation.x, - self.allocation.y, - self.allocation.width, - self.allocation.height) - - gtk.ToolButton.do_expose_event(self, event) - - def _button_clicked_cb(self, widget): - if self._palette: - self._palette.popdown(True) - - palette = property(get_palette, set_palette) diff --git a/lib/sugar/graphics/toolcombobox.py b/lib/sugar/graphics/toolcombobox.py deleted file mode 100644 index 460dcee..0000000 --- a/lib/sugar/graphics/toolcombobox.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk -import gobject - -from sugar.graphics.combobox import ComboBox -from sugar.graphics import style - -class ToolComboBox(gtk.ToolItem): - __gproperties__ = { - 'label-text' : (str, None, None, None, - gobject.PARAM_WRITABLE), - } - - def __init__(self, combo=None, **kwargs): - self.label = None - self._label_text = '' - - gobject.GObject.__init__(self, **kwargs) - - self.set_border_width(style.DEFAULT_PADDING) - - hbox = gtk.HBox(False, style.DEFAULT_SPACING) - - self.label = gtk.Label(self._label_text) - hbox.pack_start(self.label, False) - self.label.show() - - if combo: - self.combo = combo - else: - self.combo = ComboBox() - - hbox.pack_start(self.combo) - self.combo.show() - - self.add(hbox) - hbox.show() - - def do_set_property(self, pspec, value): - if pspec.name == 'label-text': - self._label_text = value - if self.label: - self.label.set_text(self._label_text) diff --git a/lib/sugar/graphics/tray.py b/lib/sugar/graphics/tray.py deleted file mode 100644 index da40501..0000000 --- a/lib/sugar/graphics/tray.py +++ /dev/null @@ -1,299 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gobject -import gtk - -from sugar.graphics import style -from sugar.graphics.palette import Palette, ToolInvoker -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.icon import Icon - -_PREVIOUS_PAGE = 0 -_NEXT_PAGE = 1 - -class _TrayViewport(gtk.Viewport): - __gproperties__ = { - 'scrollable' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'can-scroll-prev' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'can-scroll-next' : (bool, None, None, False, - gobject.PARAM_READABLE), - } - - def __init__(self, orientation): - self.orientation = orientation - self._scrollable = False - self._can_scroll_next = False - self._can_scroll_prev = False - - gobject.GObject.__init__(self) - - self.set_shadow_type(gtk.SHADOW_NONE) - - self.traybar = gtk.Toolbar() - self.traybar.set_orientation(orientation) - self.traybar.set_show_arrow(False) - self.add(self.traybar) - self.traybar.show() - - self.connect('size_allocate', self._size_allocate_cb) - - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - adj = self.get_hadjustment() - else: - adj = self.get_vadjustment() - adj.connect('changed', self._adjustment_changed_cb) - adj.connect('value-changed', self._adjustment_changed_cb) - - def scroll(self, direction): - if direction == _PREVIOUS_PAGE: - self._scroll_previous() - elif direction == _NEXT_PAGE: - self._scroll_next() - - def _scroll_next(self): - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - adj = self.get_hadjustment() - new_value = adj.value + self.allocation.width - adj.value = min(new_value, adj.upper - self.allocation.width) - else: - adj = self.get_vadjustment() - new_value = adj.value + self.allocation.height - adj.value = min(new_value, adj.upper - self.allocation.height) - - def _scroll_previous(self): - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - adj = self.get_hadjustment() - new_value = adj.value - self.allocation.width - adj.value = max(adj.lower, new_value) - else: - adj = self.get_vadjustment() - new_value = adj.value - self.allocation.height - adj.value = max(adj.lower, new_value) - - def do_size_request(self, requisition): - child_requisition = self.child.size_request() - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - requisition[0] = 0 - requisition[1] = child_requisition[1] - else: - requisition[0] = child_requisition[0] - requisition[1] = 0 - - def do_get_property(self, pspec): - if pspec.name == 'scrollable': - return self._scrollable - elif pspec.name == 'can-scroll-next': - return self._can_scroll_next - elif pspec.name == 'can-scroll-prev': - return self._can_scroll_prev - - def _size_allocate_cb(self, viewport, allocation): - bar_requisition = self.traybar.get_child_requisition() - if self.orientation == gtk.ORIENTATION_HORIZONTAL: - scrollable = bar_requisition[0] > allocation.width - else: - scrollable = bar_requisition[1] > allocation.height - - if scrollable != self._scrollable: - self._scrollable = scrollable - self.notify('scrollable') - - def _adjustment_changed_cb(self, adjustment): - if adjustment.value <= adjustment.lower: - can_scroll_prev = False - else: - can_scroll_prev = True - - if adjustment.value + adjustment.page_size >= adjustment.upper: - can_scroll_next = False - else: - can_scroll_next = True - - if can_scroll_prev != self._can_scroll_prev: - self._can_scroll_prev = can_scroll_prev - self.notify('can-scroll-prev') - - if can_scroll_next != self._can_scroll_next: - self._can_scroll_next = can_scroll_next - self.notify('can-scroll-next') - - -class _TrayScrollButton(ToolButton): - def __init__(self, icon_name, scroll_direction): - ToolButton.__init__(self) - self._viewport = None - - self._scroll_direction = scroll_direction - - self.set_size_request(style.GRID_CELL_SIZE, style.GRID_CELL_SIZE) - - 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(self.icon) - self.set_icon_widget(alignment) - alignment.show_all() - - self.connect('clicked', self._clicked_cb) - - def set_viewport(self, viewport): - self._viewport = viewport - self._viewport.connect('notify::scrollable', - self._viewport_scrollable_changed_cb) - - if self._scroll_direction == _PREVIOUS_PAGE: - self._viewport.connect('notify::can-scroll-prev', - self._viewport_can_scroll_dir_changed_cb) - self.set_sensitive(self._viewport.props.can_scroll_prev) - else: - self._viewport.connect('notify::can-scroll-next', - self._viewport_can_scroll_dir_changed_cb) - self.set_sensitive(self._viewport.props.can_scroll_next) - - - def _viewport_scrollable_changed_cb(self, viewport, pspec): - self.props.visible = self._viewport.props.scrollable - - def _viewport_can_scroll_dir_changed_cb(self, viewport, pspec): - if self._scroll_direction == _PREVIOUS_PAGE: - sensitive = self._viewport.props.can_scroll_prev - else: - sensitive = self._viewport.props.can_scroll_next - - self.set_sensitive(sensitive) - - def _clicked_cb(self, button): - self._viewport.scroll(self._scroll_direction) - - viewport = property(fset=set_viewport) - -class HTray(gtk.HBox): - def __init__(self, **kwargs): - gobject.GObject.__init__(self, **kwargs) - self.set_direction(gtk.TEXT_DIR_LTR) - - scroll_left = _TrayScrollButton('go-left', _PREVIOUS_PAGE) - self.pack_start(scroll_left, False) - - self._viewport = _TrayViewport(gtk.ORIENTATION_HORIZONTAL) - self.pack_start(self._viewport) - self._viewport.show() - - scroll_right = _TrayScrollButton('go-right', _NEXT_PAGE) - self.pack_start(scroll_right, False) - - scroll_left.viewport = self._viewport - scroll_right.viewport = self._viewport - - def get_children(self): - return self._viewport.traybar.get_children() - - def add_item(self, item, index=-1): - self._viewport.traybar.insert(item, index) - - def remove_item(self, item): - self._viewport.traybar.remove(item) - - def get_item_index(self, item): - return self._viewport.traybar.get_item_index(item) - -class VTray(gtk.VBox): - def __init__(self, **kwargs): - gobject.GObject.__init__(self, **kwargs) - - # FIXME we need a go-up icon - scroll_left = _TrayScrollButton('go-left', _PREVIOUS_PAGE) - self.pack_start(scroll_left, False) - - self._viewport = _TrayViewport(gtk.ORIENTATION_VERTICAL) - self.pack_start(self._viewport) - self._viewport.show() - - # FIXME we need a go-down icon - scroll_right = _TrayScrollButton('go-right', _NEXT_PAGE) - self.pack_start(scroll_right, False) - - scroll_left.viewport = self._viewport - scroll_right.viewport = self._viewport - - def get_children(self): - return self._viewport.traybar.get_children() - - def add_item(self, item, index=-1): - self._viewport.traybar.insert(item, index) - - def remove_item(self, item): - self._viewport.traybar.remove(item) - - def get_item_index(self, item): - return self._viewport.traybar.get_item_index(item) - -class TrayButton(ToolButton): - def __init__(self, **kwargs): - ToolButton.__init__(self, **kwargs) - -class _IconWidget(gtk.EventBox): - __gtype_name__ = "SugarTrayIconWidget" - - def __init__(self, icon_name=None, xo_color=None): - gtk.EventBox.__init__(self) - - self._palette = None - - self.set_app_paintable(True) - - icon = Icon(icon_name=icon_name, xo_color=xo_color, - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) - self.add(icon) - icon.show() - - def do_expose_event(self, event): - if self._palette and self._palette.is_up(): - invoker = self._palette.props.invoker - invoker.draw_rectangle(event, self._palette) - - gtk.EventBox.do_expose_event(self, event) - - def set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - self._palette.props.invoker = ToolInvoker(self) - -class TrayIcon(gtk.ToolItem): - __gtype_name__ = "SugarTrayIcon" - - def __init__(self, icon_name=None, xo_color=None): - gtk.ToolItem.__init__(self) - - self._icon_widget = _IconWidget(icon_name, xo_color) - self.add(self._icon_widget) - self._icon_widget.show() - - self.set_size_request(style.GRID_CELL_SIZE, style.GRID_CELL_SIZE) - - def set_palette(self, palette): - self._icon_widget.set_palette(palette) - - def set_tooltip(self, text): - self.set_palette(Palette(text)) - diff --git a/lib/sugar/graphics/window.py b/lib/sugar/graphics/window.py deleted file mode 100644 index 3189400..0000000 --- a/lib/sugar/graphics/window.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gobject -import gtk -import logging - -from sugar.graphics.icon import Icon - -class UnfullscreenButton(gtk.Window): - - def __init__(self): - gtk.Window.__init__(self) - - self.set_decorated(False) - self.set_resizable(False) - self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - - self.set_border_width(0) - - self.props.accept_focus = False - - #Setup estimate of width, height - w, h = gtk.icon_size_lookup(gtk.ICON_SIZE_LARGE_TOOLBAR) - self._width = w - self._height = h - - self.connect('size-request', self._size_request_cb) - - screen = self.get_screen() - screen.connect('size-changed', self._screen_size_changed_cb) - - self._button = gtk.Button() - self._button.set_relief(gtk.RELIEF_NONE) - - self._icon = Icon(icon_name='view-return', - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) - self._icon.show() - self._button.add(self._icon) - - self._button.show() - self.add(self._button) - - def connect_button_press(self, cb): - self._button.connect('button-press-event', cb) - - def _reposition(self): - x = gtk.gdk.screen_width() - self._width - self.move(x, 0) - - def _size_request_cb(self, widget, req): - self._width = req.width - self._height = req.height - self._reposition() - - def _screen_size_changed_cb(self, screen): - self._reposition() - -class Window(gtk.Window): - - __gproperties__ = { - 'enable-fullscreen-mode': (bool, None, None, True, - gobject.PARAM_READWRITE), - } - - def __init__(self, **args): - self._enable_fullscreen_mode = True - - gtk.Window.__init__(self, **args) - - self.connect('realize', self.__window_realize_cb) - self.connect('window-state-event', self.__window_state_event_cb) - self.connect('key-press-event', self.__key_press_cb) - - self.toolbox = None - self._alerts = [] - self.canvas = None - self.tray = None - - self._vbox = gtk.VBox() - self._hbox = gtk.HBox() - self._vbox.pack_start(self._hbox) - self._hbox.show() - - self._event_box = gtk.EventBox() - self._hbox.pack_start(self._event_box) - self._event_box.show() - - self.add(self._vbox) - self._vbox.show() - - self._is_fullscreen = False - self._unfullscreen_button = UnfullscreenButton() - self._unfullscreen_button.set_transient_for(self) - self._unfullscreen_button.connect_button_press( - self.__unfullscreen_button_pressed) - - def do_get_property(self, prop): - if prop.name == 'enable-fullscreen-mode': - return self._enable_fullscreen_mode - else: - return gtk.Window.do_get_property(self, prop) - - def do_set_property(self, prop, val): - if prop.name == 'enable-fullscreen-mode': - self._enable_fullscreen_mode = val - else: - gtk.Window.do_set_property(self, prop, val) - - def set_canvas(self, canvas): - if self.canvas: - self._event_box.remove(self.canvas) - - if canvas: - self._event_box.add(canvas) - - self.canvas = canvas - - def set_toolbox(self, toolbox): - if self.toolbox: - self._vbox.remove(self.toolbox) - - self._vbox.pack_start(toolbox, False) - self._vbox.reorder_child(toolbox, 0) - - self.toolbox = toolbox - - def set_tray(self, tray, position): - if self.tray: - box = self.tray.get_parent() - box.remove(self.tray) - - if position == gtk.POS_LEFT: - self._hbox.pack_start(tray, False) - elif position == gtk.POS_RIGHT: - self._hbox.pack_end(tray, False) - elif position == gtk.POS_BOTTOM: - self._vbox.pack_end(tray, False) - - self.tray = tray - - def add_alert(self, alert): - self._alerts.append(alert) - if len(self._alerts) == 1: - self._vbox.pack_start(alert, False) - if self.toolbox is not None: - self._vbox.reorder_child(alert, 1) - else: - self._vbox.reorder_child(alert, 0) - - def remove_alert(self, alert): - if alert in self._alerts: - self._alerts.remove(alert) - # if the alert is the visible one on top of the queue - if alert.get_parent() is not None: - self._vbox.remove(alert) - if len(self._alerts) >= 1: - self._vbox.pack_start(self._alerts[0], False) - if self.toolbox is not None: - self._vbox.reorder_child(self._alerts[0], 1) - else: - self._vbox.reorder_child(self._alert[0], 0) - - def __window_realize_cb(self, window): - group = gtk.Window() - group.realize() - window.window.set_group(group.window) - - def __window_state_event_cb(self, window, event): - if not (event.changed_mask & gtk.gdk.WINDOW_STATE_FULLSCREEN): - return False - - if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: - if self.toolbox is not None: - self.toolbox.hide() - if self.tray is not None: - self.tray.hide() - - self._is_fullscreen = True - if self.props.enable_fullscreen_mode: - self._unfullscreen_button.show() - - else: - if self.toolbox is not None: - self.toolbox.show() - if self.tray is not None: - self.tray.show() - - self._is_fullscreen = False - if self.props.enable_fullscreen_mode: - self._unfullscreen_button.hide() - - def __key_press_cb(self, widget, event): - key = gtk.gdk.keyval_name(event.keyval) - if event.state & gtk.gdk.MOD1_MASK: - if key == 'space': - self.tray.props.visible = not self.tray.props.visible - return True - elif key == 'Escape' and self._is_fullscreen and \ - self.props.enable_fullscreen_mode: - self.unfullscreen() - return True - return False - - def __unfullscreen_button_pressed(self, widget, event): - self.unfullscreen() diff --git a/lib/sugar/graphics/xocolor.py b/lib/sugar/graphics/xocolor.py deleted file mode 100644 index d37eab1..0000000 --- a/lib/sugar/graphics/xocolor.py +++ /dev/null @@ -1,255 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import random - -_colors = [ -['#B20008', '#FF2B34'], \ -['#FF2B34', '#B20008'], \ -['#E6000A', '#FF2B34'], \ -['#FF2B34', '#E6000A'], \ -['#FFADCE', '#FF2B34'], \ -['#9A5200', '#FF2B34'], \ -['#FF2B34', '#9A5200'], \ -['#FF8F00', '#FF2B34'], \ -['#FF2B34', '#FF8F00'], \ -['#FFC169', '#FF2B34'], \ -['#807500', '#FF2B34'], \ -['#FF2B34', '#807500'], \ -['#BE9E00', '#FF2B34'], \ -['#FF2B34', '#BE9E00'], \ -['#F8E800', '#FF2B34'], \ -['#008009', '#FF2B34'], \ -['#FF2B34', '#008009'], \ -['#00B20D', '#FF2B34'], \ -['#FF2B34', '#00B20D'], \ -['#8BFF7A', '#FF2B34'], \ -['#00588C', '#FF2B34'], \ -['#FF2B34', '#00588C'], \ -['#005FE4', '#FF2B34'], \ -['#FF2B34', '#005FE4'], \ -['#BCCDFF', '#FF2B34'], \ -['#5E008C', '#FF2B34'], \ -['#FF2B34', '#5E008C'], \ -['#7F00BF', '#FF2B34'], \ -['#FF2B34', '#7F00BF'], \ -['#D1A3FF', '#FF2B34'], \ -['#9A5200', '#FF8F00'], \ -['#FF8F00', '#9A5200'], \ -['#C97E00', '#FF8F00'], \ -['#FF8F00', '#C97E00'], \ -['#FFC169', '#FF8F00'], \ -['#807500', '#FF8F00'], \ -['#FF8F00', '#807500'], \ -['#BE9E00', '#FF8F00'], \ -['#FF8F00', '#BE9E00'], \ -['#F8E800', '#FF8F00'], \ -['#008009', '#FF8F00'], \ -['#FF8F00', '#008009'], \ -['#00B20D', '#FF8F00'], \ -['#FF8F00', '#00B20D'], \ -['#8BFF7A', '#FF8F00'], \ -['#00588C', '#FF8F00'], \ -['#FF8F00', '#00588C'], \ -['#005FE4', '#FF8F00'], \ -['#FF8F00', '#005FE4'], \ -['#BCCDFF', '#FF8F00'], \ -['#5E008C', '#FF8F00'], \ -['#FF8F00', '#5E008C'], \ -['#A700FF', '#FF8F00'], \ -['#FF8F00', '#A700FF'], \ -['#D1A3FF', '#FF8F00'], \ -['#B20008', '#FF8F00'], \ -['#FF8F00', '#B20008'], \ -['#FF2B34', '#FF8F00'], \ -['#FF8F00', '#FF2B34'], \ -['#FFADCE', '#FF8F00'], \ -['#807500', '#F8E800'], \ -['#F8E800', '#807500'], \ -['#BE9E00', '#F8E800'], \ -['#F8E800', '#BE9E00'], \ -['#FFFA00', '#EDDE00'], \ -['#008009', '#F8E800'], \ -['#F8E800', '#008009'], \ -['#00EA11', '#F8E800'], \ -['#F8E800', '#00EA11'], \ -['#8BFF7A', '#F8E800'], \ -['#00588C', '#F8E800'], \ -['#F8E800', '#00588C'], \ -['#00A0FF', '#F8E800'], \ -['#F8E800', '#00A0FF'], \ -['#BCCEFF', '#F8E800'], \ -['#5E008C', '#F8E800'], \ -['#F8E800', '#5E008C'], \ -['#AC32FF', '#F8E800'], \ -['#F8E800', '#AC32FF'], \ -['#D1A3FF', '#F8E800'], \ -['#B20008', '#F8E800'], \ -['#F8E800', '#B20008'], \ -['#FF2B34', '#F8E800'], \ -['#F8E800', '#FF2B34'], \ -['#FFADCE', '#F8E800'], \ -['#9A5200', '#F8E800'], \ -['#F8E800', '#9A5200'], \ -['#FF8F00', '#F8E800'], \ -['#F8E800', '#FF8F00'], \ -['#FFC169', '#F8E800'], \ -['#008009', '#00EA11'], \ -['#00EA11', '#008009'], \ -['#00B20D', '#00EA11'], \ -['#00EA11', '#00B20D'], \ -['#8BFF7A', '#00EA11'], \ -['#00588C', '#00EA11'], \ -['#00EA11', '#00588C'], \ -['#005FE4', '#00EA11'], \ -['#00EA11', '#005FE4'], \ -['#BCCDFF', '#00EA11'], \ -['#5E008C', '#00EA11'], \ -['#00EA11', '#5E008C'], \ -['#7F00BF', '#00EA11'], \ -['#00EA11', '#7F00BF'], \ -['#D1A3FF', '#00EA11'], \ -['#B20008', '#00EA11'], \ -['#00EA11', '#B20008'], \ -['#FF2B34', '#00EA11'], \ -['#00EA11', '#FF2B34'], \ -['#FFADCE', '#00EA11'], \ -['#9A5200', '#00EA11'], \ -['#00EA11', '#9A5200'], \ -['#FF8F00', '#00EA11'], \ -['#00EA11', '#FF8F00'], \ -['#FFC169', '#00EA11'], \ -['#807500', '#00EA11'], \ -['#00EA11', '#807500'], \ -['#BE9E00', '#00EA11'], \ -['#00EA11', '#BE9E00'], \ -['#F8E800', '#00EA11'], \ -['#00588C', '#00A0FF'], \ -['#00A0FF', '#00588C'], \ -['#005FE4', '#00A0FF'], \ -['#00A0FF', '#005FE4'], \ -['#BCCDFF', '#00A0FF'], \ -['#5E008C', '#00A0FF'], \ -['#00A0FF', '#5E008C'], \ -['#9900E6', '#00A0FF'], \ -['#00A0FF', '#9900E6'], \ -['#D1A3FF', '#00A0FF'], \ -['#B20008', '#00A0FF'], \ -['#00A0FF', '#B20008'], \ -['#FF2B34', '#00A0FF'], \ -['#00A0FF', '#FF2B34'], \ -['#FFADCE', '#00A0FF'], \ -['#9A5200', '#00A0FF'], \ -['#00A0FF', '#9A5200'], \ -['#FF8F00', '#00A0FF'], \ -['#00A0FF', '#FF8F00'], \ -['#FFC169', '#00A0FF'], \ -['#807500', '#00A0FF'], \ -['#00A0FF', '#807500'], \ -['#BE9E00', '#00A0FF'], \ -['#00A0FF', '#BE9E00'], \ -['#F8E800', '#00A0FF'], \ -['#008009', '#00A0FF'], \ -['#00A0FF', '#008009'], \ -['#00B20D', '#00A0FF'], \ -['#00A0FF', '#00B20D'], \ -['#8BFF7A', '#00A0FF'], \ -['#5E008C', '#AC32FF'], \ -['#AC32FF', '#5E008C'], \ -['#7F00BF', '#AC32FF'], \ -['#AC32FF', '#7F00BF'], \ -['#D1A3FF', '#AC32FF'], \ -['#B20008', '#AC32FF'], \ -['#AC32FF', '#B20008'], \ -['#FF2B34', '#AC32FF'], \ -['#AC32FF', '#FF2B34'], \ -['#FFADCE', '#AC32FF'], \ -['#9A5200', '#AC32FF'], \ -['#AC32FF', '#9A5200'], \ -['#FF8F00', '#AC32FF'], \ -['#AC32FF', '#FF8F00'], \ -['#FFC169', '#AC32FF'], \ -['#807500', '#AC32FF'], \ -['#AC32FF', '#807500'], \ -['#BE9E00', '#AC32FF'], \ -['#AC32FF', '#BE9E00'], \ -['#F8E800', '#AC32FF'], \ -['#008009', '#AC32FF'], \ -['#AC32FF', '#008009'], \ -['#00B20D', '#AC32FF'], \ -['#AC32FF', '#00B20D'], \ -['#8BFF7A', '#AC32FF'], \ -['#00588C', '#AC32FF'], \ -['#AC32FF', '#00588C'], \ -['#005FE4', '#AC32FF'], \ -['#AC32FF', '#005FE4'], \ -['#BCCDFF', '#AC32FF'], \ -] - -def _parse_string(color_string): - if color_string == 'white': - return ['#ffffff', '#414141'] - elif color_string == 'insensitive': - return ['#ffffff', '#e2e2e2'] - - splitted = color_string.split(',') - if len(splitted) == 2: - return [splitted[0], splitted[1]] - else: - return None - -def is_valid(color_string): - return (_parse_string(color_string) != None) - -class XoColor: - def __init__(self, color_string=None): - if color_string == None or not is_valid(color_string): - n = int(random.random() * (len(_colors) - 1)) - [self._stroke, self._fill] = _colors[n] - else: - [self._stroke, self._fill] = _parse_string(color_string) - - def __cmp__(self, other): - if isinstance(other, XoColor): - if self._stroke == other._stroke and self._fill == other._fill: - return 0 - return -1 - - def get_stroke_color(self): - return self._stroke - - def get_fill_color(self): - return self._fill - - def to_string(self): - return '%s,%s' % (self._stroke, self._fill) - -if __name__ == "__main__": - import sys - import re - - f = open(sys.argv[1], 'r') - - print '_colors = [' - - for line in f.readlines(): - match = re.match(r'fill: ([A-Z0-9]*) stroke: ([A-Z0-9]*)', line) - print "['#%s', '#%s'], \\" % (match.group(2), match.group(1)) - - print ']' - - f.close() diff --git a/lib/sugar/network.py b/lib/sugar/network.py deleted file mode 100644 index 49d4882..0000000 --- a/lib/sugar/network.py +++ /dev/null @@ -1,575 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -# pylint: disable-msg = W0221 - -import socket -import os -import threading -import traceback -import xmlrpclib -import sys -import httplib -import urllib -import fcntl -import tempfile - -import gobject -import SimpleXMLRPCServer -import SimpleHTTPServer -import SocketServer - - -__authinfos = {} - -def _add_authinfo(authinfo): - __authinfos[threading.currentThread()] = authinfo - -def get_authinfo(): - return __authinfos.get(threading.currentThread()) - -def _del_authinfo(): - del __authinfos[threading.currentThread()] - - -class GlibTCPServer(SocketServer.TCPServer): - """GlibTCPServer - - Integrate socket accept into glib mainloop. - """ - - allow_reuse_address = True - request_queue_size = 20 - - def __init__(self, server_address, RequestHandlerClass): - SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass) - self.socket.setblocking(0) # Set nonblocking - - # Watch the listener socket for data - gobject.io_add_watch(self.socket, gobject.IO_IN, self._handle_accept) - - def _handle_accept(self, source, condition): - """Process incoming data on the server's socket by doing an accept() - via handle_request().""" - if not (condition & gobject.IO_IN): - return True - self.handle_request() - return True - - def close_request(self, request): - """Called to clean up an individual request.""" - # let the request be closed by the request handler when its done - pass - - -class ChunkedGlibHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): - """RequestHandler class that integrates with Glib mainloop. It writes - the specified file to the client in chunks, returning control to the - mainloop between chunks. - """ - - CHUNK_SIZE = 4096 - - def __init__(self, request, client_address, server): - self._file = None - self._srcid = 0 - SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self, request, client_address, server) - - def log_request(self, code='-', size='-'): - pass - - def do_GET(self): - """Serve a GET request.""" - self._file = self.send_head() - if self._file: - self._srcid = gobject.io_add_watch(self.wfile, gobject.IO_OUT | gobject.IO_ERR, self._send_next_chunk) - else: - self._file.close() - self._cleanup() - - def _send_next_chunk(self, source, condition): - if condition & gobject.IO_ERR: - self._cleanup() - return False - if not (condition & gobject.IO_OUT): - self._cleanup() - return False - data = self._file.read(self.CHUNK_SIZE) - count = os.write(self.wfile.fileno(), data) - if count != len(data) or len(data) != self.CHUNK_SIZE: - self._cleanup() - return False - return True - - def _cleanup(self): - if self._file: - self._file.close() - self._file = None - if self._srcid > 0: - gobject.source_remove(self._srcid) - self._srcid = 0 - if not self.wfile.closed: - self.wfile.flush() - self.wfile.close() - self.rfile.close() - - def finish(self): - """Close the sockets when we're done, not before""" - pass - - def send_head(self): - """Common code for GET and HEAD commands. - - This sends the response code and MIME headers. - - Return value is either a file object (which has to be copied - to the outputfile by the caller unless the command was HEAD, - and must be closed by the caller under all circumstances), or - None, in which case the caller has nothing further to do. - - ** [dcbw] modified to send Content-disposition filename too - """ - path = self.translate_path(self.path) - if not path or not os.path.exists(path): - self.send_error(404, "File not found") - return None - - f = None - if os.path.isdir(path): - for index in "index.html", "index.htm": - index = os.path.join(path, index) - if os.path.exists(index): - path = index - break - else: - return self.list_directory(path) - ctype = self.guess_type(path) - try: - # Always read in binary mode. Opening files in text mode may cause - # newline translations, making the actual size of the content - # transmitted *less* than the content-length! - f = open(path, 'rb') - except IOError: - self.send_error(404, "File not found") - return None - self.send_response(200) - self.send_header("Content-type", ctype) - self.send_header("Content-Length", str(os.fstat(f.fileno())[6])) - self.send_header("Content-Disposition", 'attachment; filename="%s"' % os.path.basename(path)) - self.end_headers() - return f - -class GlibURLDownloader(gobject.GObject): - """Grabs a URL in chunks, returning to the mainloop after each chunk""" - - __gsignals__ = { - 'finished': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), - 'error': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'progress': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) - } - - CHUNK_SIZE = 4096 - - def __init__(self, url, destdir=None): - self._url = url - if not destdir: - destdir = tempfile.gettempdir() - self._destdir = destdir - self._srcid = 0 - self._fname = None - self._outf = None - self._written = 0 - gobject.GObject.__init__(self) - - def start(self, destfile=None, destfd=None): - self._info = urllib.urlopen(self._url) - self._outf = None - self._fname = None - if destfd and not destfile: - raise ValueError("Must provide destination file too when specifying file descriptor") - if destfile: - self._suggested_fname = os.path.basename(destfile) - self._fname = os.path.abspath(os.path.expanduser(destfile)) - if destfd: - # Use the user-supplied destination file descriptor - self._outf = destfd - else: - self._outf = os.open(self._fname, os.O_RDWR | os.O_TRUNC | os.O_CREAT, 0644) - else: - self._suggested_fname = self._get_filename_from_headers(self._info.headers) - garbage, path = urllib.splittype(self._url) - garbage, path = urllib.splithost(path or "") - path, garbage = urllib.splitquery(path or "") - path, garbage = urllib.splitattr(path or "") - suffix = os.path.splitext(path)[1] - (self._outf, self._fname) = tempfile.mkstemp(suffix=suffix, dir=self._destdir) - - fcntl.fcntl(self._info.fp.fileno(), fcntl.F_SETFD, os.O_NDELAY) - self._srcid = gobject.io_add_watch(self._info.fp.fileno(), - gobject.IO_IN | gobject.IO_ERR, - self._read_next_chunk) - - def cancel(self): - if self._srcid == 0: - raise RuntimeError("Download already canceled or stopped") - self.cleanup(remove=True) - - def _get_filename_from_headers(self, headers): - if not headers.has_key("Content-Disposition"): - return None - - ftag = "filename=" - data = headers["Content-Disposition"] - fidx = data.find(ftag) - if fidx < 0: - return None - fname = data[fidx+len(ftag):] - if fname[0] == '"' or fname[0] == "'": - fname = fname[1:] - if fname[len(fname)-1] == '"' or fname[len(fname)-1] == "'": - fname = fname[:len(fname)-1] - return fname - - def _read_next_chunk(self, source, condition): - if condition & gobject.IO_ERR: - self.cleanup(remove=True) - self.emit("error", "Error downloading file.") - return False - elif not (condition & gobject.IO_IN): - # shouldn't get here, but... - return True - - try: - data = self._info.fp.read(self.CHUNK_SIZE) - count = os.write(self._outf, data) - self._written += len(data) - - # error writing data to file? - if count < len(data): - self.cleanup(remove=True) - self.emit("error", "Error writing to download file.") - return False - - self.emit("progress", self._written) - - # done? - if len(data) < self.CHUNK_SIZE: - self.cleanup() - self.emit("finished", self._fname, self._suggested_fname) - return False - except Exception, err: - self.cleanup(remove=True) - self.emit("error", "Error downloading file: %s" % err) - return False - return True - - def cleanup(self, remove=False): - if self._srcid > 0: - gobject.source_remove(self._srcid) - self._srcid = 0 - del self._info - self._info = None - os.close(self._outf) - if remove: - os.remove(self._fname) - self._outf = None - - -class GlibXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler): - """ GlibXMLRPCRequestHandler - - The stock SimpleXMLRPCRequestHandler and server don't allow any way to pass - the client's address and/or SSL certificate into the function that actually - _processes_ the request. So we have to store it in a thread-indexed dict. - """ - - def do_POST(self): - _add_authinfo(self.client_address) - try: - SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self) - except socket.timeout: - pass - except socket.error, e: - print "Error (%s): socket error - '%s'" % (self.client_address, e) - except: - print "Error while processing POST:" - traceback.print_exc() - _del_authinfo() - -class GlibXMLRPCServer(GlibTCPServer, SimpleXMLRPCServer.SimpleXMLRPCDispatcher): - """GlibXMLRPCServer - - Use nonblocking sockets and handle the accept via glib rather than - blocking on accept(). - """ - - def __init__(self, addr, requestHandler=GlibXMLRPCRequestHandler, - logRequests=0, allow_none=False): - self.logRequests = logRequests - if sys.version_info[:3] >= (2, 5, 0): - SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self, allow_none, encoding="utf-8") - else: - SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self) - GlibTCPServer.__init__(self, addr, requestHandler) - - def _marshaled_dispatch(self, data, dispatch_method = None): - """Dispatches an XML-RPC method from marshalled (XML) data. - - XML-RPC methods are dispatched from the marshalled (XML) data - using the _dispatch method and the result is returned as - marshalled data. For backwards compatibility, a dispatch - function can be provided as an argument (see comment in - SimpleXMLRPCRequestHandler.do_POST) but overriding the - existing method through subclassing is the prefered means - of changing method dispatch behavior. - """ - - params, method = xmlrpclib.loads(data) - - # generate response - try: - if dispatch_method is not None: - response = dispatch_method(method, params) - else: - response = self._dispatch(method, params) - # wrap response in a singleton tuple - response = (response,) - response = xmlrpclib.dumps(response, methodresponse=1) - except xmlrpclib.Fault, fault: - response = xmlrpclib.dumps(fault) - except: - print "Exception while processing request:" - traceback.print_exc() - - # report exception back to server - response = xmlrpclib.dumps( - xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value)) - ) - - return response - - -class GlibHTTP(httplib.HTTP): - """Subclass HTTP so we can return it's connection class' socket.""" - def connect(self, host=None, port=None): - httplib.HTTP.connect(self, host, port) - self._conn.sock.setblocking(0) - -class GlibXMLRPCTransport(xmlrpclib.Transport): - """Integrate the request with the glib mainloop rather than blocking.""" - ## - # Connect to server. - # - # @param host Target host. - # @return A connection handle. - - def __init__(self, use_datetime=0): - if sys.version_info[:3] >= (2, 5, 0): - xmlrpclib.Transport.__init__(self, use_datetime) - - def make_connection(self, host): - """Use our own connection object so we can get its socket.""" - # create a HTTP connection object from a host descriptor - host, extra_headers, x509 = self.get_host_info(host) - return GlibHTTP(host) - - ## - # Send a complete request, and parse the response. - # - # @param host Target host. - # @param handler Target PRC handler. - # @param request_body XML-RPC request body. - # @param verbose Debugging flag. - # @return Parsed response. - - def start_request(self, host, handler, request_body, verbose=0, reply_handler=None, error_handler=None, user_data=None): - """Do the first half of the request by sending data to the remote - server. The bottom half bits get run when the remote server's response - actually comes back.""" - # issue XML-RPC request - - h = self.make_connection(host) - if verbose: - h.set_debuglevel(1) - - self.send_request(h, handler, request_body) - self.send_host(h, host) - self.send_user_agent(h) - self.send_content(h, request_body) - - # Schedule a GIOWatch so we don't block waiting for the response - gobject.io_add_watch(h._conn.sock, gobject.IO_IN, self._finish_request, - h, host, handler, verbose, reply_handler, error_handler, user_data) - - def _finish_request(self, source, condition, h, host, handler, verbose, reply_handler=None, error_handler=None, user_data=None): - """Parse and return response when the remote server actually returns it.""" - if not (condition & gobject.IO_IN): - return True - - try: - errcode, errmsg, headers = h.getreply() - except socket.error, err: - if err[0] != 104: - raise socket.error(err) - else: - if error_handler: - gobject.idle_add(error_handler, err, user_data) - return False - - if errcode != 200: - raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) - self.verbose = verbose - response = self._parse_response(h.getfile(), h._conn.sock) - if reply_handler: - # Coerce to a list so we can append user data - response = response[0] - if not isinstance(response, list): - response = [response] - response.append(user_data) - gobject.idle_add(reply_handler, *response) - return False - -class _Method: - """Right, so python people thought it would be funny to make this - class private to xmlrpclib.py...""" - # some magic to bind an XML-RPC method to an RPC server. - # supports "nested" methods (e.g. examples.getStateName) - def __init__(self, send, name): - self.__send = send - self.__name = name - def __getattr__(self, name): - return _Method(self.__send, "%s.%s" % (self.__name, name)) - def __call__(self, *args, **kwargs): - return self.__send(self.__name, *args, **kwargs) - - -class GlibServerProxy(xmlrpclib.ServerProxy): - """Subclass xmlrpclib.ServerProxy so we can run the XML-RPC request - in two parts, integrated with the glib mainloop, such that we don't - block anywhere. - - Using this object is somewhat special; it requires more arguments to each - XML-RPC request call than the normal xmlrpclib.ServerProxy object: - - client = GlibServerProxy("http://127.0.0.1:8888") - user_data = "bar" - xmlrpc_arg1 = "test" - xmlrpc_arg2 = "foo" - client.test(xmlrpc_test_cb, user_data, xmlrpc_arg1, xmlrpc_arg2) - - Here, 'xmlrpc_test_cb' is the callback function, which has the following - signature: - - def xmlrpc_test_cb(result_status, response, user_data=None): - ... - """ - def __init__(self, uri, encoding=None, verbose=0, allow_none=0): - self._transport = GlibXMLRPCTransport() - self._encoding = encoding - self._verbose = verbose - self._allow_none = allow_none - xmlrpclib.ServerProxy.__init__(self, uri, self._transport, encoding, verbose, allow_none) - - # get the url - import urllib - urltype, uri = urllib.splittype(uri) - if urltype not in ("http", "https"): - raise IOError, "unsupported XML-RPC protocol" - self._host, self._handler = urllib.splithost(uri) - if not self._handler: - self._handler = "/RPC2" - - def __request(self, methodname, *args, **kwargs): - """Call the method on the remote server. We just start the request here - and the transport itself takes care of scheduling the response callback - when the remote server returns the response. We don't want to block anywhere.""" - - request = xmlrpclib.dumps(args, methodname, encoding=self._encoding, - allow_none=self._allow_none) - - reply_hdl = kwargs.get("reply_handler") - err_hdl = kwargs.get("error_handler") - udata = kwargs.get("user_data") - try: - response = self._transport.start_request( - self._host, - self._handler, - request, - verbose=self._verbose, - reply_handler=reply_hdl, - error_handler=err_hdl, - user_data=udata - ) - except socket.error, exc: - if err_hdl: - gobject.idle_add(err_hdl, exc, udata) - - def __getattr__(self, name): - # magic method dispatcher - return _Method(self.__request, name) - - -class Test(object): - def test(self, arg1, arg2): - print "Request got %s, %s" % (arg1, arg2) - return "success", "bork" - -def xmlrpc_success_cb(response, resp2, loop): - print "Response was %s %s" % (response, resp2) - loop.quit() - -def xmlrpc_error_cb(err, loop): - print "Error: %s" % err - loop.quit() - -def xmlrpc_test(loop): - client = GlibServerProxy("http://127.0.0.1:8888") - client.test("bar", "baz", - reply_handler=xmlrpc_success_cb, - error_handler=xmlrpc_error_cb, - user_data=loop) - -def start_xmlrpc(): - server = GlibXMLRPCServer(("", 8888)) - inst = Test() - server.register_instance(inst) - gobject.idle_add(xmlrpc_test, loop) - -class TestReqHandler(ChunkedGlibHTTPRequestHandler): - def translate_path(self, path): - return "/tmp/foo" - -def start_http(): - server = GlibTCPServer(("", 8890), TestReqHandler) - -def main(): - loop = gobject.MainLoop() -# start_xmlrpc() - start_http() - try: - loop.run() - except KeyboardInterrupt: - print 'Ctrl+C pressed, exiting...' - print "Done." - -if __name__ == "__main__": - main() - - diff --git a/lib/sugar/presence/Makefile.am b/lib/sugar/presence/Makefile.am deleted file mode 100644 index cb52a41..0000000 --- a/lib/sugar/presence/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -sugardir = $(pythondir)/sugar/presence -sugar_PYTHON = \ - __init__.py \ - activity.py \ - buddy.py \ - tubeconn.py \ - presenceservice.py - diff --git a/lib/sugar/presence/__init__.py b/lib/sugar/presence/__init__.py deleted file mode 100644 index 3834ab2..0000000 --- a/lib/sugar/presence/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Client-code's interface to the PresenceService - -Provides a simplified API for accessing the dbus service -which coordinates native network presence and sharing -information. This includes both "buddies" and "shared -activities". -""" - -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. diff --git a/lib/sugar/presence/activity.py b/lib/sugar/presence/activity.py deleted file mode 100644 index b0110a0..0000000 --- a/lib/sugar/presence/activity.py +++ /dev/null @@ -1,407 +0,0 @@ -"""UI interface to an activity in the presence service""" -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging - -import dbus -import gobject -import telepathy - -_logger = logging.getLogger('sugar.presence.activity') - -class Activity(gobject.GObject): - """UI interface for an Activity in the presence service - - Activities in the presence service represent your and other user's - shared activities. - - Properties: - id - color - name - type - joined - """ - __gsignals__ = { - 'buddy-joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'buddy-left': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'new-channel': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), - } - - __gproperties__ = { - 'id' : (str, None, None, None, gobject.PARAM_READABLE), - 'name' : (str, None, None, None, gobject.PARAM_READWRITE), - 'tags' : (str, None, None, None, gobject.PARAM_READWRITE), - 'color' : (str, None, None, None, gobject.PARAM_READWRITE), - 'type' : (str, None, None, None, gobject.PARAM_READABLE), - 'private' : (bool, None, None, True, gobject.PARAM_READWRITE), - 'joined' : (bool, None, None, False, gobject.PARAM_READABLE), - } - - _PRESENCE_SERVICE = "org.laptop.Sugar.Presence" - _ACTIVITY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Activity" - - def __init__(self, bus, new_obj_cb, del_obj_cb, object_path): - """Initialse the activity interface, connecting to service""" - gobject.GObject.__init__(self) - self._object_path = object_path - self._ps_new_object = new_obj_cb - self._ps_del_object = del_obj_cb - bobj = bus.get_object(self._PRESENCE_SERVICE, object_path) - self._activity = dbus.Interface(bobj, self._ACTIVITY_DBUS_INTERFACE) - self._activity.connect_to_signal('BuddyHandleJoined', - self._buddy_handle_joined_cb) - self._activity.connect_to_signal('BuddyLeft', - self._buddy_left_cb) - self._activity.connect_to_signal('NewChannel', self._new_channel_cb) - self._activity.connect_to_signal('PropertiesChanged', - self._properties_changed_cb, - utf8_strings=True) - # FIXME: this *would* just use a normal proxy call, but I want the - # pending call object so I can block on it, and normal proxy methods - # don't return those as of dbus-python 0.82.1; so do it the hard way - self._get_properties_call = bus.call_async(self._PRESENCE_SERVICE, - object_path, self._ACTIVITY_DBUS_INTERFACE, 'GetProperties', - '', (), self._get_properties_reply_cb, - self._get_properties_error_cb, utf8_strings=True) - - self._id = None - self._color = None - self._name = None - self._type = None - self._tags = None - self._private = True - self._joined = False - # Cache for get_buddy_by_handle, maps handles to buddy object paths - self._handle_to_buddy_path = {} - self._buddy_path_to_handle = {} - - # Set up by set_up_tubes() - self.telepathy_conn = None - self.telepathy_tubes_chan = None - self.telepathy_text_chan = None - self._telepathy_room = None - - def __repr__(self): - return ('' % (self._object_path, id(self))) - - def _get_properties_reply_cb(self, new_props): - self._get_properties_call = None - _logger.debug('%r: initial GetProperties returned', self) - self._properties_changed_cb(new_props) - - def _get_properties_error_cb(self, e): - self._get_properties_call = None - # FIXME: do something with the error - _logger.warning('%r: Error doing initial GetProperties: %s', self, e) - - def _properties_changed_cb(self, new_props): - _logger.debug('%r: Activity properties changed to %r', self, new_props) - val = new_props.get('name', self._name) - if isinstance(val, str) and val != self._name: - self._name = val - self.notify('name') - val = new_props.get('tags', self._tags) - if isinstance(val, str) and val != self._tags: - self._tags = val - self.notify('tags') - val = new_props.get('color', self._color) - if isinstance(val, str) and val != self._color: - self._color = val - self.notify('color') - val = bool(new_props.get('private', self._private)) - if val != self._private: - self._private = val - self.notify('private') - val = new_props.get('id', self._id) - if isinstance(val, str) and self._id is None: - self._id = val - self.notify('id') - val = new_props.get('type', self._type) - if isinstance(val, str) and self._type is None: - self._type = val - self.notify('type') - - def object_path(self): - """Get our dbus object path""" - return self._object_path - - def do_get_property(self, pspec): - """Retrieve a particular property from our property dictionary""" - - if pspec.name == "joined": - return self._joined - - if self._get_properties_call is not None: - _logger.debug('%r: Blocking on GetProperties() because someone ' - 'wants property %s', self, pspec.name) - self._get_properties_call.block() - - if pspec.name == "id": - return self._id - elif pspec.name == "name": - return self._name - elif pspec.name == "color": - return self._color - elif pspec.name == "type": - return self._type - elif pspec.name == "tags": - return self._tags - elif pspec.name == "private": - return self._private - - # FIXME: need an asynchronous API to set these properties, particularly - # 'private' - def do_set_property(self, pspec, val): - """Set a particular property in our property dictionary""" - if pspec.name == "name": - self._activity.SetProperties({'name': val}) - self._name = val - elif pspec.name == "color": - self._activity.SetProperties({'color': val}) - self._color = val - elif pspec.name == "tags": - self._activity.SetProperties({'tags': val}) - self._tags = val - elif pspec.name == "private": - self._activity.SetProperties({'private': val}) - self._private = val - - def set_private(self, val, reply_handler, error_handler): - self._activity.SetProperties({'private': bool(val)}, - reply_handler=reply_handler, - error_handler=error_handler) - - def _emit_buddy_joined_signal(self, object_path): - """Generate buddy-joined GObject signal with presence Buddy object""" - self.emit('buddy-joined', self._ps_new_object(object_path)) - return False - - def _buddy_handle_joined_cb(self, object_path, handle): - _logger.debug('%r: buddy %s joined with handle %u', self, object_path, - handle) - gobject.idle_add(self._emit_buddy_joined_signal, object_path) - self._handle_to_buddy_path[handle] = object_path - self._buddy_path_to_handle[object_path] = handle - - def _emit_buddy_left_signal(self, object_path): - """Generate buddy-left GObject signal with presence Buddy object - - XXX note use of _ps_new_object instead of _ps_del_object here - """ - self.emit('buddy-left', self._ps_new_object(object_path)) - return False - - def _buddy_left_cb(self, object_path): - _logger.debug('%r: buddy %s left', self, object_path) - gobject.idle_add(self._emit_buddy_left_signal, object_path) - handle = self._buddy_path_to_handle.pop(object_path, None) - if handle: - self._handle_to_buddy_path.pop(handle, None) - - def _emit_new_channel_signal(self, object_path): - """Generate new-channel GObject signal with channel object path - - New telepathy-python communications channel has been opened - """ - self.emit('new-channel', object_path) - return False - - def _new_channel_cb(self, object_path): - _logger.debug('%r: new channel created at %s', self, object_path) - gobject.idle_add(self._emit_new_channel_signal, object_path) - - def get_joined_buddies(self): - """Retrieve the set of Buddy objects attached to this activity - - returns list of presence Buddy objects - """ - resp = self._activity.GetJoinedBuddies() - buddies = [] - for item in resp: - buddies.append(self._ps_new_object(item)) - return buddies - - def get_buddy_by_handle(self, handle): - """Retrieve the Buddy object given a telepathy handle. - - buddy object paths are cached in self._handle_to_buddy_path, - so we can get the buddy without calling PS. - """ - object_path = self._handle_to_buddy_path.get(handle, None) - if object_path: - buddy = self._ps_new_object(object_path) - return buddy - return None - - def invite(self, buddy, message, response_cb): - """Invite the given buddy to join this activity. - - The callback will be called with one parameter: None on success, - or an exception on failure. - """ - op = buddy.object_path() - _logger.debug('%r: inviting %s', self, op) - self._activity.Invite(op, message, - reply_handler=lambda: response_cb(None), - error_handler=response_cb) - - # Joining and sharing (FIXME: sharing is actually done elsewhere) - - def set_up_tubes(self, reply_handler, error_handler): - - cpaths = [] - - def tubes_chan_ready(chan): - _logger.debug('%r: Tubes channel %r is ready', self, chan) - self.telepathy_tubes_chan = chan - - _logger.debug('%r: finished setting up tubes', self) - reply_handler() - - def got_tubes_chan(path): - _logger.debug('%r: got Tubes channel at %s', self, path) - telepathy.client.Channel(self.telepathy_conn.service_name, - path, ready_handler=tubes_chan_ready, - error_handler=error_handler) - - def text_chan_ready(chan): - _logger.debug('%r: Text channel %r is ready', self, chan) - self.telepathy_text_chan = chan - - self.telepathy_conn.RequestChannel(telepathy.CHANNEL_TYPE_TUBES, - telepathy.HANDLE_TYPE_ROOM, - self._telepathy_room_handle, - True, - reply_handler=got_tubes_chan, - error_handler=error_handler) - - def got_text_chan(path): - _logger.debug('%r: got Text channel at %s', self, path) - telepathy.client.Channel(self.telepathy_conn.service_name, - path, ready_handler=text_chan_ready, - error_handler=error_handler) - - def conn_ready(conn): - _logger.debug('%r: Connection %r is ready', self, conn) - self.telepathy_conn = conn - - # For the moment we'll do this synchronously. - # If the PS gained a GetRoom method, we could - # do this async too - - for channel_path in cpaths: - channel = telepathy.client.Channel(conn.service_name, - channel_path) - handle_type, handle = channel.GetHandle() - if handle_type == telepathy.HANDLE_TYPE_ROOM: - room = handle - break - - if room is None: - error_handler(AssertionError("Presence Service didn't create " - "a chatroom")) - else: - self._telepathy_room_handle = room - - conn.RequestChannel(telepathy.CHANNEL_TYPE_TEXT, - telepathy.HANDLE_TYPE_ROOM, - room, True, - reply_handler=got_text_chan, - error_handler=error_handler) - - def got_channels(bus_name, conn_path, channel_paths): - _logger.debug('%r: Connection on %s at %s, channel paths: %r', - self, bus_name, conn_path, channel_paths) - - # can't use assignment for this due to Python scoping - cpaths.extend(channel_paths) - - telepathy.client.Connection(bus_name, conn_path, - ready_handler=conn_ready, - error_handler=error_handler) - - self._activity.GetChannels(reply_handler=got_channels, - error_handler=error_handler) - - def _join_cb(self): - _logger.debug('%r: Join finished', self) - self._joined = True - self.emit("joined", True, None) - - def _join_error_cb(self, err): - _logger.debug('%r: Join failed because: %s', self, err) - self.emit("joined", False, str(err)) - - def join(self): - """Join this activity. - - Emits 'joined' and otherwise does nothing if we're already joined. - """ - if self._joined: - self.emit("joined", True, None) - return - - _logger.debug('%r: joining', self) - - def joined(): - self.set_up_tubes(reply_handler=self._join_cb, - error_handler=self._join_error_cb) - - self._activity.Join(reply_handler=joined, - error_handler=self._join_error_cb) - - # GetChannels() wrapper - - def get_channels(self): - """Retrieve communications channel descriptions for the activity - - Returns a tuple containing: - - the D-Bus well-known service name of the connection - (FIXME: this is redundant; in Telepathy it can be derived - from that of the connection) - - the D-Bus object path of the connection - - a list of D-Bus object paths representing the channels - associated with this activity - """ - (bus_name, connection, channels) = self._activity.GetChannels() - _logger.debug('%r: bus name is %s, connection is %s, channels are %r', - self, bus_name, connection, channels) - return bus_name, connection, channels - - # Leaving - - def _leave_cb(self): - """Callback for async action of leaving shared activity.""" - self.emit("joined", False, "left activity") - - def _leave_error_cb(self, err): - """Callback for error in async leaving of shared activity.""" - _logger.debug('Failed to leave activity: %s', err) - - def leave(self): - """Leave this shared activity""" - _logger.debug('%r: leaving', self) - self._joined = False - self._activity.Leave(reply_handler=self._leave_cb, - error_handler=self._leave_error_cb) diff --git a/lib/sugar/presence/buddy.py b/lib/sugar/presence/buddy.py deleted file mode 100644 index 1030cfc..0000000 --- a/lib/sugar/presence/buddy.py +++ /dev/null @@ -1,236 +0,0 @@ -"""UI interface to a buddy in the presence service""" -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gobject -import gtk -import dbus - - -class Buddy(gobject.GObject): - """UI interface for a Buddy in the presence service - - Each buddy interface tracks a set of activities and properties - that can be queried to provide UI controls for manipulating - the presence interface. - - Properties Dictionary: - 'key': public key, - 'nick': nickname , - 'color': color (XXX what format), - 'current-activity': (XXX dbus path?), - 'owner': (XXX dbus path?), - 'icon': (XXX pixel data for an icon?) - See __gproperties__ - """ - __gsignals__ = { - 'icon-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([])), - 'joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'property-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - } - - __gproperties__ = { - 'key' : (str, None, None, None, gobject.PARAM_READABLE), - 'icon' : (str, None, None, None, gobject.PARAM_READABLE), - 'nick' : (str, None, None, None, gobject.PARAM_READABLE), - 'color' : (str, None, None, None, gobject.PARAM_READABLE), - 'current-activity' : (object, None, None, gobject.PARAM_READABLE), - 'owner' : (bool, None, None, False, gobject.PARAM_READABLE), - 'ip4-address' : (str, None, None, None, gobject.PARAM_READABLE) - } - - _PRESENCE_SERVICE = "org.laptop.Sugar.Presence" - _BUDDY_DBUS_INTERFACE = "org.laptop.Sugar.Presence.Buddy" - - def __init__(self, bus, new_obj_cb, del_obj_cb, object_path): - """Initialise the reference to the buddy - - bus -- dbus bus object - new_obj_cb -- callback to call when this buddy joins an activity - del_obj_cb -- callback to call when this buddy leaves an activity - object_path -- path to the buddy object - """ - gobject.GObject.__init__(self) - self._object_path = object_path - self._ps_new_object = new_obj_cb - self._ps_del_object = del_obj_cb - self._properties = {} - self._activities = {} - - bobj = bus.get_object(self._PRESENCE_SERVICE, object_path) - self._buddy = dbus.Interface(bobj, self._BUDDY_DBUS_INTERFACE) - - self._icon_changed_signal = self._buddy.connect_to_signal( - 'IconChanged', self._icon_changed_cb, byte_arrays=True) - self._joined_activity_signal = self._buddy.connect_to_signal( - 'JoinedActivity', self._joined_activity_cb) - self._left_activity_signal = self._buddy.connect_to_signal( - 'LeftActivity', self._left_activity_cb) - self._property_changed_signal = self._buddy.connect_to_signal( - 'PropertyChanged', self._property_changed_cb) - - self._properties = self._get_properties_helper() - - activities = self._buddy.GetJoinedActivities() - for op in activities: - self._activities[op] = self._ps_new_object(op) - self._icon = None - - def destroy(self): - self._icon_changed_signal.remove() - self._joined_activity_signal.remove() - self._left_activity_signal.remove() - self._property_changed_signal.remove() - - def _get_properties_helper(self): - """Retrieve the Buddy's property dictionary from the service object - """ - props = self._buddy.GetProperties(byte_arrays=True) - if not props: - return {} - return props - - def do_get_property(self, pspec): - """Retrieve a particular property from our property dictionary - - pspec -- XXX some sort of GTK specifier object with attributes - including 'name', 'active' and 'icon-name' - """ - if pspec.name == "key": - return self._properties["key"] - elif pspec.name == "nick": - return self._properties["nick"] - elif pspec.name == "color": - return self._properties["color"] - elif pspec.name == "current-activity": - if not self._properties.has_key("current-activity"): - return None - curact = self._properties["current-activity"] - if not len(curact): - return None - for activity in self._activities.values(): - if activity.props.id == curact: - return activity - return None - elif pspec.name == "owner": - return self._properties["owner"] - elif pspec.name == "icon": - if not self._icon: - self._icon = str(self._buddy.GetIcon(byte_arrays=True)) - return self._icon - elif pspec.name == "ip4-address": - # IPv4 address will go away quite soon - if not self._properties.has_key("ip4-address"): - return None - return self._properties["ip4-address"] - - def object_path(self): - """Retrieve our dbus object path""" - return self._object_path - - def _emit_icon_changed_signal(self, bytes): - """Emit GObject signal when icon has changed""" - self._icon = str(bytes) - self.emit('icon-changed') - return False - - def _icon_changed_cb(self, icon_data): - """Handle dbus signal by emitting a GObject signal""" - gobject.idle_add(self._emit_icon_changed_signal, icon_data) - - def _emit_joined_activity_signal(self, object_path): - """Emit activity joined signal with Activity object""" - self.emit('joined-activity', self._ps_new_object(object_path)) - return False - - def _joined_activity_cb(self, object_path): - """Handle dbus signal by emitting a GObject signal - - Stores the activity in activities dictionary as well - """ - if not self._activities.has_key(object_path): - self._activities[object_path] = self._ps_new_object(object_path) - gobject.idle_add(self._emit_joined_activity_signal, object_path) - - def _emit_left_activity_signal(self, object_path): - """Emit activity left signal with Activity object - - XXX this calls self._ps_new_object instead of self._ps_del_object, - which would seem to be the incorrect callback? - """ - self.emit('left-activity', self._ps_new_object(object_path)) - return False - - def _left_activity_cb(self, object_path): - """Handle dbus signal by emitting a GObject signal - - Also removes from the activities dictionary - """ - if self._activities.has_key(object_path): - del self._activities[object_path] - gobject.idle_add(self._emit_left_activity_signal, object_path) - - def _handle_property_changed_signal(self, prop_list): - """Emit property-changed signal with property dictionary - - Generates a property-changed signal with the results of - _get_properties_helper() - """ - self._properties = self._get_properties_helper() - # FIXME: don't leak unexposed property names - self.emit('property-changed', prop_list) - return False - - def _property_changed_cb(self, prop_list): - """Handle dbus signal by emitting a GObject signal""" - gobject.idle_add(self._handle_property_changed_signal, prop_list) - - def get_icon_pixbuf(self): - """Retrieve Buddy's icon as a GTK pixel buffer - - XXX Why aren't the icons coming in as SVG? - """ - if self.props.icon and len(self.props.icon): - pbl = gtk.gdk.PixbufLoader() - pbl.write(self.props.icon) - pbl.close() - return pbl.get_pixbuf() - else: - return None - - def get_joined_activities(self): - """Retrieve the set of all activities which this buddy has joined - - Uses the GetJoinedActivities method on the service - object to produce object paths, wraps each in an - Activity object. - - returns list of presence Activity objects - """ - try: - resp = self._buddy.GetJoinedActivities() - except dbus.exceptions.DBusException: - return [] - acts = [] - for item in resp: - acts.append(self._ps_new_object(item)) - return acts diff --git a/lib/sugar/presence/presenceservice.py b/lib/sugar/presence/presenceservice.py deleted file mode 100644 index cb47a3a..0000000 --- a/lib/sugar/presence/presenceservice.py +++ /dev/null @@ -1,577 +0,0 @@ -"""UI class to access system-level presence object""" -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import logging - -import dbus -import dbus.exceptions -import dbus.glib -import gobject - -from sugar.presence.buddy import Buddy -from sugar.presence.activity import Activity - - -DBUS_SERVICE = "org.laptop.Sugar.Presence" -DBUS_INTERFACE = "org.laptop.Sugar.Presence" -DBUS_PATH = "/org/laptop/Sugar/Presence" - -_logger = logging.getLogger('sugar.presence.presenceservice') - - -class PresenceService(gobject.GObject): - """UI-side interface to the dbus presence service - - This class provides UI programmers with simplified access - to the dbus service of the same name. It allows for observing - various events from the presence service as GObject events, - as well as some basic introspection queries. - """ - __gsignals__ = { - 'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'buddy-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - # parameters: (activity: Activity, inviter: Buddy, message: unicode) - 'activity-invitation': (gobject.SIGNAL_RUN_FIRST, None, ([object]*3)), - 'private-invitation': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, - gobject.TYPE_PYOBJECT])), - 'activity-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'activity-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'activity-shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, - gobject.TYPE_PYOBJECT])) - } - - _PS_BUDDY_OP = DBUS_PATH + "/Buddies/" - _PS_ACTIVITY_OP = DBUS_PATH + "/Activities/" - - - def __init__(self, allow_offline_iface=True): - """Initialise the service and attempt to connect to events - """ - gobject.GObject.__init__(self) - self._objcache = {} - - # Get a connection to the session bus - self._bus = dbus.SessionBus() - self._bus.add_signal_receiver(self._name_owner_changed_cb, - signal_name="NameOwnerChanged", - dbus_interface="org.freedesktop.DBus") - - # attempt to load the interface to the service... - self._allow_offline_iface = allow_offline_iface - self._get_ps() - - def _name_owner_changed_cb(self, name, old, new): - if name != DBUS_SERVICE: - return - if (old and len(old)) and (not new and not len(new)): - # PS went away, clear out PS dbus service wrapper - self._ps_ = None - elif (not old and not len(old)) and (new and len(new)): - # PS started up - self._get_ps() - - _ps_ = None - def _get_ps(self): - """Retrieve dbus interface to PresenceService - - Also registers for updates from various dbus events on the - interface. - - If unable to retrieve the interface, we will temporarily - return an _OfflineInterface object to allow the calling - code to continue functioning as though it had accessed a - real presence service. - - If successful, caches the presence service interface - for use by other methods and returns that interface - """ - if not self._ps_: - try: - # NOTE: We need to follow_name_owner_changes here - # because we can not connect to a signal unless - # we follow the changes or we start the service - # before we connect. Starting the service here - # causes a major bottleneck during startup - ps = dbus.Interface( - self._bus.get_object(DBUS_SERVICE, - DBUS_PATH, - follow_name_owner_changes=True), - DBUS_INTERFACE - ) - except dbus.exceptions.DBusException, err: - _logger.error( - """Failure retrieving %r interface from the D-BUS service %r %r: %s""", - DBUS_INTERFACE, DBUS_SERVICE, DBUS_PATH, err - ) - if self._allow_offline_iface: - return _OfflineInterface() - raise RuntimeError("Failed to connect to the presence service.") - else: - self._ps_ = ps - ps.connect_to_signal('BuddyAppeared', self._buddy_appeared_cb) - ps.connect_to_signal('BuddyDisappeared', self._buddy_disappeared_cb) - ps.connect_to_signal('ActivityAppeared', self._activity_appeared_cb) - ps.connect_to_signal('ActivityDisappeared', self._activity_disappeared_cb) - ps.connect_to_signal('ActivityInvitation', self._activity_invitation_cb) - ps.connect_to_signal('PrivateInvitation', self._private_invitation_cb) - return self._ps_ - - _ps = property( - _get_ps, None, None, - """DBUS interface to the PresenceService (services/presence/presenceservice)""" - ) - - def _new_object(self, object_path): - """Turn new object path into (cached) Buddy/Activity instance - - object_path -- full dbus path of the new object, must be - prefixed with either of _PS_BUDDY_OP or _PS_ACTIVITY_OP - - Note that this method is called throughout the class whenever - the representation of the object is required, it is not only - called when the object is first discovered. The point is to only have - _one_ Python object for any D-Bus object represented by an object path, - effectively wrapping the D-Bus object in a single Python GObject. - - returns presence Buddy or Activity representation - """ - obj = None - try: - obj = self._objcache[object_path] - _logger.debug('Reused proxy %r', obj) - except KeyError: - if object_path.startswith(self._PS_BUDDY_OP): - obj = Buddy(self._bus, self._new_object, - self._del_object, object_path) - elif object_path.startswith(self._PS_ACTIVITY_OP): - obj = Activity(self._bus, self._new_object, - self._del_object, object_path) - try: - # Pre-fill the activity's ID - foo = obj.props.id - except dbus.exceptions.DBusException, err: - pass - else: - raise RuntimeError("Unknown object type") - self._objcache[object_path] = obj - _logger.debug('Created proxy %r', obj) - return obj - - def _have_object(self, object_path): - return object_path in self._objcache.keys() - - def _del_object(self, object_path): - """Fully remove an object from the object cache when it's no longer needed. - """ - del self._objcache[object_path] - - def _emit_buddy_appeared_signal(self, object_path): - """Emit GObject event with presence.buddy.Buddy object""" - self.emit('buddy-appeared', self._new_object(object_path)) - return False - - def _buddy_appeared_cb(self, op): - """Callback for dbus event (forwards to method to emit GObject event)""" - gobject.idle_add(self._emit_buddy_appeared_signal, op) - - def _emit_buddy_disappeared_signal(self, object_path): - """Emit GObject event with presence.buddy.Buddy object""" - # Don't try to create a new object here if needed; it will probably - # fail anyway because the object has already been destroyed in the PS - if self._have_object(object_path): - obj = self._objcache[object_path] - self.emit('buddy-disappeared', obj) - - # We cannot maintain the object in the cache because that would keep - # a lot of objects from being collected. That includes UI objects - # due to signals using strong references. - # If we want to cache some despite the memory usage increase, - # we could use a LRU cache limited to some value. - del self._objcache[object_path] - obj.destroy() - - return False - - def _buddy_disappeared_cb(self, object_path): - """Callback for dbus event (forwards to method to emit GObject event)""" - gobject.idle_add(self._emit_buddy_disappeared_signal, object_path) - - def _emit_activity_invitation_signal(self, activity_path, buddy_path, - message): - """Emit GObject event with presence.activity.Activity object""" - self.emit('activity-invitation', self._new_object(activity_path), - self._new_object(buddy_path), unicode(message)) - return False - - def _activity_invitation_cb(self, activity_path, buddy_path, message): - """Callback for dbus event (forwards to method to emit GObject event)""" - gobject.idle_add(self._emit_activity_invitation_signal, activity_path, - buddy_path, message) - - def _emit_private_invitation_signal(self, bus_name, connection, channel): - """Emit GObject event with bus_name, connection and channel""" - self.emit('private-invitation', bus_name, connection, channel) - return False - - def _private_invitation_cb(self, bus_name, connection, channel): - """Callback for dbus event (forwards to method to emit GObject event)""" - gobject.idle_add(self._emit_service_disappeared_signal, bus_name, - connection, channel) - - def _emit_activity_appeared_signal(self, object_path): - """Emit GObject event with presence.activity.Activity object""" - self.emit('activity-appeared', self._new_object(object_path)) - return False - - def _activity_appeared_cb(self, object_path): - """Callback for dbus event (forwards to method to emit GObject event)""" - gobject.idle_add(self._emit_activity_appeared_signal, object_path) - - def _emit_activity_disappeared_signal(self, object_path): - """Emit GObject event with presence.activity.Activity object""" - self.emit('activity-disappeared', self._new_object(object_path)) - return False - - def _activity_disappeared_cb(self, object_path): - """Callback for dbus event (forwards to method to emit GObject event)""" - gobject.idle_add(self._emit_activity_disappeared_signal, object_path) - - def get(self, object_path): - """Return the Buddy or Activity object corresponding to the given - D-Bus object path. - """ - return self._new_object(object_path) - - def get_activities(self): - """Retrieve set of all activities from service - - returns list of Activity objects for all object paths - the service reports exist (using GetActivities) - """ - try: - resp = self._ps.GetActivities() - except dbus.exceptions.DBusException, err: - _logger.warn( - """Unable to retrieve activity list from presence service: %s""" - % err - ) - return [] - else: - acts = [] - for item in resp: - acts.append(self._new_object(item)) - return acts - - def _get_activities_cb(self, reply_handler, resp): - acts = [] - for item in resp: - acts.append(self._new_object(item)) - - reply_handler(acts) - - def _get_activities_error_cb(self, error_handler, e): - if error_handler: - error_handler(e) - else: - _logger.warn( - """Unable to retrieve activity-list from presence service: %s""" - % e - ) - - def get_activities_async(self, reply_handler=None, error_handler=None): - """Retrieve set of all activities from service asyncronously - """ - - if not reply_handler: - logging.error('Function get_activities_async called without a reply handler. Can not run.') - return - - self._ps.GetActivities( - reply_handler=lambda resp:self._get_activities_cb(reply_handler, resp), - error_handler=lambda e:self._get_activities_error_cb(error_handler, e)) - - - def get_activity(self, activity_id, warn_if_none=True): - """Retrieve single Activity object for the given unique id - - activity_id -- unique ID for the activity - - returns single Activity object or None if the activity - is not found using GetActivityById on the service - """ - try: - act_op = self._ps.GetActivityById(activity_id) - except dbus.exceptions.DBusException, err: - if warn_if_none: - _logger.warn("Unable to retrieve activity handle for %r from " - "presence service: %s", activity_id, err) - return None - return self._new_object(act_op) - - def get_buddies(self): - """Retrieve set of all buddies from service - - returns list of Buddy objects for all object paths - the service reports exist (using GetBuddies) - """ - try: - resp = self._ps.GetBuddies() - except dbus.exceptions.DBusException, err: - _logger.warn( - """Unable to retrieve buddy-list from presence service: %s""" - % err - ) - return [] - else: - buddies = [] - for item in resp: - buddies.append(self._new_object(item)) - return buddies - - def _get_buddies_cb(self, reply_handler, resp): - buddies = [] - for item in resp: - buddies.append(self._new_object(item)) - - reply_handler(buddies) - - def _get_buddies_error_cb(self, error_handler, e): - if error_handler: - error_handler(e) - else: - _logger.warn( - """Unable to retrieve buddy-list from presence service: %s""" - % e - ) - - def get_buddies_async(self, reply_handler=None, error_handler=None): - """Retrieve set of all buddies from service asyncronously - """ - - if not reply_handler: - logging.error('Function get_buddies_async called without a reply handler. Can not run.') - return - - self._ps.GetBuddies( - reply_handler=lambda resp:self._get_buddies_cb(reply_handler, resp), - error_handler=lambda e:self._get_buddies_error_cb(error_handler, e)) - - def get_buddy(self, key): - """Retrieve single Buddy object for the given public key - - key -- buddy's public encryption key - - returns single Buddy object or None if the activity - is not found using GetBuddyByPublicKey on the - service - """ - try: - buddy_op = self._ps.GetBuddyByPublicKey(dbus.ByteArray(key)) - except dbus.exceptions.DBusException, err: - _logger.warn( - """Unable to retrieve buddy handle for %r from presence service: %s""" - % key, err - ) - return None - return self._new_object(buddy_op) - - def get_buddy_by_telepathy_handle(self, tp_conn_name, tp_conn_path, - handle): - """Retrieve single Buddy object for the given public key - - :Parameters: - `tp_conn_name` : str - The well-known bus name of a Telepathy connection - `tp_conn_path` : dbus.ObjectPath - The object path of the Telepathy connection - `handle` : int or long - The handle of a Telepathy contact on that connection, - of type HANDLE_TYPE_CONTACT. This may not be a - channel-specific handle. - :Returns: the Buddy object, or None if the buddy is not found - """ - try: - buddy_op = self._ps.GetBuddyByTelepathyHandle(tp_conn_name, - tp_conn_path, - handle) - except dbus.exceptions.DBusException, err: - _logger.warn('Unable to retrieve buddy handle for handle %u at ' - 'conn %s:%s from presence service: %s', - handle, tp_conn_name, tp_conn_path, err) - return None - return self._new_object(buddy_op) - - def get_owner(self): - """Retrieves the laptop "owner" Buddy object.""" - try: - owner_op = self._ps.GetOwner() - except dbus.exceptions.DBusException, err: - _logger.warn( - """Unable to retrieve local user/owner from presence service: %s""" - % err - ) - raise RuntimeError("Could not get owner object from presence service.") - return self._new_object(owner_op) - - def _share_activity_cb(self, activity, op): - """Finish sharing the activity - """ - psact = self._new_object(op) - psact._joined = True - _logger.debug('%r: Just shared, setting up tubes', activity) - psact.set_up_tubes(reply_handler=lambda: - self.emit("activity-shared", True, psact, None), - error_handler=lambda e: - self._share_activity_error_cb(activity, e)) - - def _share_activity_error_cb(self, activity, err): - """Notify with GObject event of unsuccessful sharing of activity""" - _logger.debug("Error sharing activity %s: %s" % (activity.get_id(), err)) - self.emit("activity-shared", False, None, err) - - def share_activity(self, activity, properties={}, private=True): - """Ask presence service to ask the activity to share itself publicly. - - Uses the AdvertiseActivity method on the service to ask for the - sharing of the given activity. Arranges to emit activity-shared - event with: - - (success, Activity, err) - - on success/failure. - - returns None - """ - actid = activity.get_id() - - # Ensure the activity is not already shared/joined - for obj in self._objcache.values(): - if not isinstance(object, Activity): - continue - if obj.props.id == actid or obj.props.joined: - raise RuntimeError("Activity %s is already shared." % - actid) - - atype = activity.get_bundle_id() - name = activity.props.title - properties['private'] = bool(private) - self._ps.ShareActivity(actid, atype, name, properties, - reply_handler=lambda op: \ - self._share_activity_cb(activity, op), - error_handler=lambda e: \ - self._share_activity_error_cb(activity, e)) - - def get_preferred_connection(self): - """Gets the preferred telepathy connection object that an activity - should use when talking directly to telepathy - - returns the bus name and the object path of the Telepathy connection""" - - try: - bus_name, object_path = self._ps.GetPreferredConnection() - except dbus.exceptions.DBusException: - return None - - return bus_name, object_path - -class _OfflineInterface( object ): - """Offline-presence-service interface - - Used to mimic the behaviour of a real PresenceService sufficiently - to avoid crashing client code that expects the given interface. - - XXX we could likely return a "MockOwner" object reasonably - easily, but would it be worth it? - """ - def raiseException( self, *args, **named ): - """Raise dbus.exceptions.DBusException""" - raise dbus.exceptions.DBusException( - """PresenceService Interface not available""" - ) - GetActivities = raiseException - GetActivityById = raiseException - GetBuddies = raiseException - GetBuddyByPublicKey = raiseException - GetOwner = raiseException - GetPreferredConnection = raiseException - def ShareActivity( - self, actid, atype, name, properties, - reply_handler, error_handler, - ): - """Pretend to share and fail...""" - exc = IOError( - """Unable to share activity as PresenceService is not currenly available""" - ) - return error_handler( exc ) - -class _MockPresenceService(gobject.GObject): - """Test fixture allowing testing of items that use PresenceService - - See PresenceService for usage and purpose - """ - __gsignals__ = { - 'buddy-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'buddy-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'activity-invitation': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'private-invitation': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, - gobject.TYPE_PYOBJECT])), - 'activity-appeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'activity-disappeared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) - } - - def __init__(self): - gobject.GObject.__init__(self) - - def get_activities(self): - return [] - - def get_activity(self, activity_id): - return None - - def get_buddies(self): - return [] - - def get_buddy(self, key): - return None - - def get_owner(self): - return None - - def share_activity(self, activity, properties={}): - return None - -_ps = None -def get_instance(allow_offline_iface=False): - """Retrieve this process' view of the PresenceService""" - global _ps - if not _ps: - _ps = PresenceService(allow_offline_iface) - return _ps - diff --git a/lib/sugar/presence/test_presence.txt b/lib/sugar/presence/test_presence.txt deleted file mode 100644 index d0736a9..0000000 --- a/lib/sugar/presence/test_presence.txt +++ /dev/null @@ -1,26 +0,0 @@ -This is a test of presence. - -To test this service we will start up a mock dbus library: - - >>> from sugar.testing import mockdbus - >>> import dbus - >>> pres_service = mockdbus.MockService( - ... 'org.laptop.Presence', '/org/laptop/Presence', name='pres') - >>> pres_service.install() - >>> pres_interface = dbus.Interface(pres_service, 'org.laptop.Presence') - -Then we import the library (second, to make sure it connects to our -mocked system, though the lazy instantiation in get_instance() should -handle it): - - >>> from sugar.presence import PresenceService - >>> ps = PresenceService.get_instance() - >>> pres_interface.make_response('getServices', []) - >>> ps.get_services() - Called pres.org.laptop.Presence:getServices() - [] - >>> pres_interface.make_response('getBuddies', []) - >>> ps.get_buddies() - Called pres.org.laptop.Presence:getBuddies() - [] - diff --git a/lib/sugar/presence/tubeconn.py b/lib/sugar/presence/tubeconn.py deleted file mode 100644 index b487391..0000000 --- a/lib/sugar/presence/tubeconn.py +++ /dev/null @@ -1,107 +0,0 @@ -# This should eventually land in telepathy-python, so has the same license: - -# Copyright (C) 2007 Collabora Ltd. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -__all__ = ('TubeConnection',) -__docformat__ = 'reStructuredText' - - -import logging - -from dbus.connection import Connection - - -logger = logging.getLogger('telepathy.tubeconn') - - -class TubeConnection(Connection): - - def __new__(cls, conn, tubes_iface, tube_id, address=None, - group_iface=None, mainloop=None): - if address is None: - address = tubes_iface.GetDBusTubeAddress(tube_id) - self = super(TubeConnection, cls).__new__(cls, address, - mainloop=mainloop) - - self._tubes_iface = tubes_iface - self.tube_id = tube_id - self.participants = {} - self.bus_name_to_handle = {} - self._mapping_watches = [] - - if group_iface is None: - method = conn.GetSelfHandle - else: - method = group_iface.GetSelfHandle - method(reply_handler=self._on_get_self_handle_reply, - error_handler=self._on_get_self_handle_error) - - return self - - def _on_get_self_handle_reply(self, handle): - self.self_handle = handle - match = self._tubes_iface.connect_to_signal('DBusNamesChanged', - self._on_dbus_names_changed) - self._tubes_iface.GetDBusNames(self.tube_id, - reply_handler=self._on_get_dbus_names_reply, - error_handler=self._on_get_dbus_names_error) - self._dbus_names_changed_match = match - - def _on_get_self_handle_error(self, e): - logging.basicConfig() - logger.error('GetSelfHandle failed: %s', e) - - def close(self): - self._dbus_names_changed_match.remove() - self._on_dbus_names_changed(self.tube_id, (), self.participants.keys()) - super(TubeConnection, self).close() - - def _on_get_dbus_names_reply(self, names): - self._on_dbus_names_changed(self.tube_id, names, ()) - - def _on_get_dbus_names_error(self, e): - logging.basicConfig() - logger.error('GetDBusNames failed: %s', e) - - def _on_dbus_names_changed(self, tube_id, added, removed): - if tube_id == self.tube_id: - for handle, bus_name in added: - if handle == self.self_handle: - # I've just joined - set my unique name - self.set_unique_name(bus_name) - self.participants[handle] = bus_name - self.bus_name_to_handle[bus_name] = handle - - # call the callback while the removed people are still in - # participants, so their bus names are available - for callback in self._mapping_watches: - callback(added, removed) - - for handle in removed: - bus_name = self.participants.pop(handle, None) - self.bus_name_to_handle.pop(bus_name, None) - - def watch_participants(self, callback): - self._mapping_watches.append(callback) - if self.participants: - # GetDBusNames already returned: fake a participant add event - # immediately - added = [] - for k, v in self.participants.iteritems(): - added.append((k, v)) - callback(added, []) diff --git a/lib/sugar/profile.py b/lib/sugar/profile.py deleted file mode 100644 index 11991dd..0000000 --- a/lib/sugar/profile.py +++ /dev/null @@ -1,207 +0,0 @@ -"""User settings/configuration loading""" -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import os -import logging -from ConfigParser import ConfigParser - -from sugar import env -from sugar import util -from sugar.graphics.xocolor import XoColor - -DEFAULT_JABBER_SERVER = 'olpc.collabora.co.uk' -DEFAULT_VOLUME = 81 - -_profile = None - -def _set_key(cp, section, key, value): - if not cp.has_section(section): - cp.add_section(section) - cp.set(section, key, value) - -class Profile(object): - """Local user's current options/profile information - - User settings are stored in an INI-style configuration - file. This object uses the ConfigParser module to load - the settings. (We only very rarely set keys, so we don't - keep the ConfigParser around between calls.) - - The profile is also responsible for loading the user's - public and private ssh keys from disk. - - Attributes: - - name -- child's name - color -- XoColor for the child's icon - server -- school server with which the child is - associated - server_registered -- whether the child has registered - with the school server or not - backup1 -- temporary backup info key for Trial-2 - - pubkey -- public ssh key - privkey_hash -- SHA has of the child's public key - """ - def __init__(self, path): - self.nick_name = None - self.color = None - self.jabber_server = DEFAULT_JABBER_SERVER - self.jabber_registered = False - self.backup1 = None - self.sound_volume = DEFAULT_VOLUME - - self._pubkey = None - self._privkey_hash = None - self._config_path = path - - self._load_config() - - def is_valid(self): - return self.nick_name is not None and \ - self.color is not None and \ - self.pubkey is not None and \ - self.privkey_hash is not None - - def is_registered(self): - return self.backup1 is not None - - def save(self): - cp = ConfigParser() - cp.read([self._config_path]) - - if self.nick_name: - _set_key(cp, 'Buddy', 'NickName', self.nick_name.encode('utf8')) - if self.color: - _set_key(cp, 'Buddy', 'Color', self.color.to_string()) - if self.backup1: - _set_key(cp, 'Server', 'Backup1', self.backup1) - if self.jabber_server: - _set_key(cp, 'Jabber', 'Server', self.jabber_server) - - _set_key(cp, 'Jabber', 'Registered', self.jabber_registered) - - _set_key(cp, 'Sound', 'Volume', self.sound_volume) - - f = open(self._config_path, 'w') - cp.write(f) - f.close() - - def _load_config(self): - cp = ConfigParser() - cp.read([self._config_path]) - - if cp.has_option('Buddy', 'NickName'): - name = cp.get('Buddy', 'NickName') - # decode nickname from ascii-safe chars to unicode - self.nick_name = name.decode("utf-8") - if cp.has_option('Buddy', 'Color'): - self.color = XoColor(cp.get('Buddy', 'Color')) - if cp.has_option('Jabber', 'Server'): - self.jabber_server = cp.get('Jabber', 'Server') - if cp.has_option('Jabber', 'Registered'): - registered = cp.get('Jabber', 'Registered') - if registered.lower() == "true": - self.jabber_registered = True - if cp.has_option('Server', 'Backup1'): - self.backup1 = cp.get('Server', 'Backup1') - if cp.has_option('Sound', 'Volume'): - self.sound_volume = float(cp.get('Sound', 'Volume')) - - del cp - - def _load_pubkey(self): - key_path = os.path.join(env.get_profile_path(), 'owner.key.pub') - try: - f = open(key_path, "r") - lines = f.readlines() - f.close() - except IOError, e: - logging.error("Error reading public key: %s" % e) - return None - - magic = "ssh-dss " - for l in lines: - l = l.strip() - if not l.startswith(magic): - continue - return l[len(magic):] - else: - logging.error("Error parsing public key.") - return None - - def _get_pubkey(self): - # load on-demand. - if not self._pubkey: - self._pubkey = self._load_pubkey() - return self._pubkey - - def _hash_private_key(self): - key_path = os.path.join(env.get_profile_path(), 'owner.key') - try: - f = open(key_path, "r") - lines = f.readlines() - f.close() - except IOError, e: - logging.error("Error reading private key: %s" % e) - return None - - key = "" - for l in lines: - l = l.strip() - if l.startswith("-----BEGIN DSA PRIVATE KEY-----"): - continue - if l.startswith("-----END DSA PRIVATE KEY-----"): - continue - key += l - if not len(key): - logging.error("Error parsing public key.") - return None - - # hash it - key_hash = util._sha_data(key) - return util.printable_hash(key_hash) - - def _get_privkey_hash(self): - # load on-demand. - if not self._privkey_hash: - self._privkey_hash = self._hash_private_key() - return self._privkey_hash - - privkey_hash = property(_get_privkey_hash) - pubkey = property(_get_pubkey) - -def get_profile(): - global _profile - - if not _profile: - path = os.path.join(env.get_profile_path(), 'config') - _profile = Profile(path) - - return _profile - -# Convenience methods for frequently used properties - -def get_nick_name(): - return get_profile().nick_name - -def get_color(): - return get_profile().color - -def get_pubkey(): - return get_profile().pubkey diff --git a/lib/sugar/sexy-icon-entry.c b/lib/sugar/sexy-icon-entry.c deleted file mode 100644 index ca35209..0000000 --- a/lib/sugar/sexy-icon-entry.c +++ /dev/null @@ -1,984 +0,0 @@ -/* - * @file libsexy/sexy-icon-entry.c Entry widget - * - * @Copyright (C) 2004-2006 Christian Hammond. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#include -#include -#include - -#define ICON_MARGIN 2 -#define MAX_ICONS 2 - -#define IS_VALID_ICON_ENTRY_POSITION(pos) \ - ((pos) == SEXY_ICON_ENTRY_PRIMARY || \ - (pos) == SEXY_ICON_ENTRY_SECONDARY) - -typedef struct -{ - GtkImage *icon; - gboolean highlight; - gboolean hovered; - GdkWindow *window; - -} SexyIconInfo; - -struct _SexyIconEntryPriv -{ - SexyIconInfo icons[MAX_ICONS]; - - gulong icon_released_id; -}; - -enum -{ - ICON_PRESSED, - ICON_RELEASED, - LAST_SIGNAL -}; - -static void sexy_icon_entry_class_init(SexyIconEntryClass *klass); -static void sexy_icon_entry_editable_init(GtkEditableClass *iface); -static void sexy_icon_entry_init(SexyIconEntry *entry); -static void sexy_icon_entry_finalize(GObject *obj); -static void sexy_icon_entry_destroy(GtkObject *obj); -static void sexy_icon_entry_map(GtkWidget *widget); -static void sexy_icon_entry_unmap(GtkWidget *widget); -static void sexy_icon_entry_realize(GtkWidget *widget); -static void sexy_icon_entry_unrealize(GtkWidget *widget); -static void sexy_icon_entry_size_request(GtkWidget *widget, - GtkRequisition *requisition); -static void sexy_icon_entry_size_allocate(GtkWidget *widget, - GtkAllocation *allocation); -static gint sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event); -static gint sexy_icon_entry_enter_notify(GtkWidget *widget, - GdkEventCrossing *event); -static gint sexy_icon_entry_leave_notify(GtkWidget *widget, - GdkEventCrossing *event); -static gint sexy_icon_entry_button_press(GtkWidget *widget, - GdkEventButton *event); -static gint sexy_icon_entry_button_release(GtkWidget *widget, - GdkEventButton *event); - -static GtkEntryClass *parent_class = NULL; -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE_EXTENDED(SexyIconEntry, sexy_icon_entry, GTK_TYPE_ENTRY, - 0, - G_IMPLEMENT_INTERFACE(GTK_TYPE_EDITABLE, - sexy_icon_entry_editable_init)); - -static void -sexy_icon_entry_class_init(SexyIconEntryClass *klass) -{ - GObjectClass *gobject_class; - GtkObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkEntryClass *entry_class; - - parent_class = g_type_class_peek_parent(klass); - - gobject_class = G_OBJECT_CLASS(klass); - object_class = GTK_OBJECT_CLASS(klass); - widget_class = GTK_WIDGET_CLASS(klass); - entry_class = GTK_ENTRY_CLASS(klass); - - gobject_class->finalize = sexy_icon_entry_finalize; - - object_class->destroy = sexy_icon_entry_destroy; - - widget_class->map = sexy_icon_entry_map; - widget_class->unmap = sexy_icon_entry_unmap; - widget_class->realize = sexy_icon_entry_realize; - widget_class->unrealize = sexy_icon_entry_unrealize; - widget_class->size_request = sexy_icon_entry_size_request; - widget_class->size_allocate = sexy_icon_entry_size_allocate; - widget_class->expose_event = sexy_icon_entry_expose; - widget_class->enter_notify_event = sexy_icon_entry_enter_notify; - widget_class->leave_notify_event = sexy_icon_entry_leave_notify; - widget_class->button_press_event = sexy_icon_entry_button_press; - widget_class->button_release_event = sexy_icon_entry_button_release; - - /** - * SexyIconEntry::icon-pressed: - * @entry: The entry on which the signal is emitted. - * @icon_pos: The position of the clicked icon. - * @button: The mouse button clicked. - * - * The ::icon-pressed signal is emitted when an icon is clicked. - */ - signals[ICON_PRESSED] = - g_signal_new("icon_pressed", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET(SexyIconEntryClass, icon_pressed), - NULL, NULL, - gtk_marshal_VOID__INT_INT, - G_TYPE_NONE, 2, - G_TYPE_INT, - G_TYPE_INT); - - /** - * SexyIconEntry::icon-released: - * @entry: The entry on which the signal is emitted. - * @icon_pos: The position of the clicked icon. - * @button: The mouse button clicked. - * - * The ::icon-released signal is emitted on the button release from a - * mouse click. - */ - signals[ICON_RELEASED] = - g_signal_new("icon_released", - G_TYPE_FROM_CLASS(gobject_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET(SexyIconEntryClass, icon_released), - NULL, NULL, - gtk_marshal_VOID__INT_INT, - G_TYPE_NONE, 2, - G_TYPE_INT, - G_TYPE_INT); -} - -static void -sexy_icon_entry_editable_init(GtkEditableClass *iface) -{ -}; - -static void -sexy_icon_entry_init(SexyIconEntry *entry) -{ - entry->priv = g_new0(SexyIconEntryPriv, 1); -} - -static void -sexy_icon_entry_finalize(GObject *obj) -{ - SexyIconEntry *entry; - - g_return_if_fail(obj != NULL); - g_return_if_fail(SEXY_IS_ICON_ENTRY(obj)); - - entry = SEXY_ICON_ENTRY(obj); - - g_free(entry->priv); - - if (G_OBJECT_CLASS(parent_class)->finalize) - G_OBJECT_CLASS(parent_class)->finalize(obj); -} - -static void -sexy_icon_entry_destroy(GtkObject *obj) -{ - SexyIconEntry *entry; - - entry = SEXY_ICON_ENTRY(obj); - - sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_PRIMARY, NULL); - sexy_icon_entry_set_icon(entry, SEXY_ICON_ENTRY_SECONDARY, NULL); - - if (GTK_OBJECT_CLASS(parent_class)->destroy) - GTK_OBJECT_CLASS(parent_class)->destroy(obj); -} - -static void -sexy_icon_entry_map(GtkWidget *widget) -{ - if (GTK_WIDGET_REALIZED(widget) && !GTK_WIDGET_MAPPED(widget)) - { - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - int i; - - GTK_WIDGET_CLASS(parent_class)->map(widget); - - for (i = 0; i < MAX_ICONS; i++) - { - if (entry->priv->icons[i].icon != NULL) - gdk_window_show(entry->priv->icons[i].window); - } - } -} - -static void -sexy_icon_entry_unmap(GtkWidget *widget) -{ - if (GTK_WIDGET_MAPPED(widget)) - { - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - int i; - - for (i = 0; i < MAX_ICONS; i++) - { - if (entry->priv->icons[i].icon != NULL) - gdk_window_hide(entry->priv->icons[i].window); - } - - GTK_WIDGET_CLASS(parent_class)->unmap(widget); - } -} - -static gint -get_icon_width(SexyIconEntry *entry, SexyIconEntryPosition icon_pos) -{ - GtkRequisition requisition; - gint menu_icon_width; - gint width; - SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; - - if (icon_info->icon == NULL) - return 0; - - gtk_widget_size_request(GTK_WIDGET(icon_info->icon), &requisition); - gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &menu_icon_width, NULL); - - width = MAX(requisition.width, menu_icon_width); - - return width; -} - -static void -get_borders(SexyIconEntry *entry, gint *xborder, gint *yborder) -{ - GtkWidget *widget = GTK_WIDGET(entry); - gint focus_width; - gboolean interior_focus; - - gtk_widget_style_get(widget, - "interior-focus", &interior_focus, - "focus-line-width", &focus_width, - NULL); - - if (gtk_entry_get_has_frame(GTK_ENTRY(entry))) - { - *xborder = widget->style->xthickness; - *yborder = widget->style->ythickness; - } - else - { - *xborder = 0; - *yborder = 0; - } - - if (!interior_focus) - { - *xborder += focus_width; - *yborder += focus_width; - } -} - -static void -get_text_area_size(SexyIconEntry *entry, GtkAllocation *alloc) -{ - GtkWidget *widget = GTK_WIDGET(entry); - GtkRequisition requisition; - gint xborder, yborder; - - gtk_widget_get_child_requisition(widget, &requisition); - get_borders(entry, &xborder, &yborder); - - alloc->x = xborder; - alloc->y = yborder; - alloc->width = widget->allocation.width - xborder * 2; - alloc->height = requisition.height - yborder * 2; -} - -static void -get_icon_allocation(SexyIconEntry *icon_entry, - gboolean left, - GtkAllocation *widget_alloc, - GtkAllocation *text_area_alloc, - GtkAllocation *allocation, - SexyIconEntryPosition *icon_pos) -{ - gboolean rtl; - - rtl = (gtk_widget_get_direction(GTK_WIDGET(icon_entry)) == - GTK_TEXT_DIR_RTL); - - if (left) - *icon_pos = (rtl ? SEXY_ICON_ENTRY_SECONDARY : SEXY_ICON_ENTRY_PRIMARY); - else - *icon_pos = (rtl ? SEXY_ICON_ENTRY_PRIMARY : SEXY_ICON_ENTRY_SECONDARY); - - allocation->y = text_area_alloc->y; - allocation->width = get_icon_width(icon_entry, *icon_pos); - allocation->height = text_area_alloc->height; - - if (left) - allocation->x = text_area_alloc->x + ICON_MARGIN; - else - { - allocation->x = text_area_alloc->x + text_area_alloc->width - - allocation->width - ICON_MARGIN; - } -} - -static void -sexy_icon_entry_realize(GtkWidget *widget) -{ - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - GdkWindowAttr attributes; - gint attributes_mask; - int i; - - GTK_WIDGET_CLASS(parent_class)->realize(widget); - - attributes.x = 0; - attributes.y = 0; - attributes.width = 1; - attributes.height = 1; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.wclass = GDK_INPUT_OUTPUT; - attributes.visual = gtk_widget_get_visual(widget); - attributes.colormap = gtk_widget_get_colormap(widget); - attributes.event_mask = gtk_widget_get_events(widget); - attributes.event_mask |= - (GDK_EXPOSURE_MASK - | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); - - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - - for (i = 0; i < MAX_ICONS; i++) - { - SexyIconInfo *icon_info; - - icon_info = &entry->priv->icons[i]; - icon_info->window = gdk_window_new(widget->window, &attributes, - attributes_mask); - gdk_window_set_user_data(icon_info->window, widget); - - gdk_window_set_background(icon_info->window, - &widget->style->base[GTK_WIDGET_STATE(widget)]); - } - - gtk_widget_queue_resize(widget); -} - -static void -sexy_icon_entry_unrealize(GtkWidget *widget) -{ - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - int i; - - GTK_WIDGET_CLASS(parent_class)->unrealize(widget); - - for (i = 0; i < MAX_ICONS; i++) - { - SexyIconInfo *icon_info = &entry->priv->icons[i]; - - gdk_window_destroy(icon_info->window); - icon_info->window = NULL; - } -} - -static void -sexy_icon_entry_size_request(GtkWidget *widget, GtkRequisition *requisition) -{ - GtkEntry *gtkentry; - SexyIconEntry *entry; - gint icon_widths = 0; - int i; - - gtkentry = GTK_ENTRY(widget); - entry = SEXY_ICON_ENTRY(widget); - - for (i = 0; i < MAX_ICONS; i++) - { - int icon_width = get_icon_width(entry, i); - - if (icon_width > 0) - icon_widths += icon_width + ICON_MARGIN; - } - - GTK_WIDGET_CLASS(parent_class)->size_request(widget, requisition); - - if (icon_widths > requisition->width) - requisition->width += icon_widths; -} - -static void -place_windows(SexyIconEntry *icon_entry, GtkAllocation *widget_alloc) -{ - SexyIconEntryPosition left_icon_pos; - SexyIconEntryPosition right_icon_pos; - GtkAllocation left_icon_alloc; - GtkAllocation right_icon_alloc; - GtkAllocation text_area_alloc; - - get_text_area_size(icon_entry, &text_area_alloc); - get_icon_allocation(icon_entry, TRUE, widget_alloc, &text_area_alloc, - &left_icon_alloc, &left_icon_pos); - get_icon_allocation(icon_entry, FALSE, widget_alloc, &text_area_alloc, - &right_icon_alloc, &right_icon_pos); - - if (left_icon_alloc.width > 0) - { - text_area_alloc.x = left_icon_alloc.x + left_icon_alloc.width + - ICON_MARGIN; - } - - if (right_icon_alloc.width > 0) - text_area_alloc.width -= right_icon_alloc.width + ICON_MARGIN; - - text_area_alloc.width -= text_area_alloc.x; - - gdk_window_move_resize(icon_entry->priv->icons[left_icon_pos].window, - left_icon_alloc.x, left_icon_alloc.y, - left_icon_alloc.width, left_icon_alloc.height); - - gdk_window_move_resize(icon_entry->priv->icons[right_icon_pos].window, - right_icon_alloc.x, right_icon_alloc.y, - right_icon_alloc.width, right_icon_alloc.height); - - gdk_window_move_resize(GTK_ENTRY(icon_entry)->text_area, - text_area_alloc.x, text_area_alloc.y, - text_area_alloc.width, text_area_alloc.height); -} - -static void -sexy_icon_entry_size_allocate(GtkWidget *widget, GtkAllocation *allocation) -{ - g_return_if_fail(SEXY_IS_ICON_ENTRY(widget)); - g_return_if_fail(allocation != NULL); - - widget->allocation = *allocation; - - GTK_WIDGET_CLASS(parent_class)->size_allocate(widget, allocation); - - if (GTK_WIDGET_REALIZED(widget)) - place_windows(SEXY_ICON_ENTRY(widget), allocation); -} - -static GdkPixbuf * -get_pixbuf_from_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos) -{ - GdkPixbuf *pixbuf = NULL; - gchar *stock_id; - SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; - GtkIconSize size; - - switch (gtk_image_get_storage_type(GTK_IMAGE(icon_info->icon))) - { - case GTK_IMAGE_PIXBUF: - pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(icon_info->icon)); - g_object_ref(pixbuf); - break; - - case GTK_IMAGE_STOCK: - gtk_image_get_stock(GTK_IMAGE(icon_info->icon), &stock_id, &size); - pixbuf = gtk_widget_render_icon(GTK_WIDGET(entry), - stock_id, size, NULL); - break; - - default: - return NULL; - } - - return pixbuf; -} - -/* Kudos to the gnome-panel guys. */ -static void -colorshift_pixbuf(GdkPixbuf *dest, GdkPixbuf *src, int shift) -{ - gint i, j; - gint width, height, has_alpha, src_rowstride, dest_rowstride; - guchar *target_pixels; - guchar *original_pixels; - guchar *pix_src; - guchar *pix_dest; - int val; - guchar r, g, b; - - has_alpha = gdk_pixbuf_get_has_alpha(src); - width = gdk_pixbuf_get_width(src); - height = gdk_pixbuf_get_height(src); - src_rowstride = gdk_pixbuf_get_rowstride(src); - dest_rowstride = gdk_pixbuf_get_rowstride(dest); - original_pixels = gdk_pixbuf_get_pixels(src); - target_pixels = gdk_pixbuf_get_pixels(dest); - - for (i = 0; i < height; i++) - { - pix_dest = target_pixels + i * dest_rowstride; - pix_src = original_pixels + i * src_rowstride; - - for (j = 0; j < width; j++) - { - r = *(pix_src++); - g = *(pix_src++); - b = *(pix_src++); - - val = r + shift; - *(pix_dest++) = CLAMP(val, 0, 255); - - val = g + shift; - *(pix_dest++) = CLAMP(val, 0, 255); - - val = b + shift; - *(pix_dest++) = CLAMP(val, 0, 255); - - if (has_alpha) - *(pix_dest++) = *(pix_src++); - } - } -} - -static void -draw_icon(GtkWidget *widget, SexyIconEntryPosition icon_pos) -{ - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - SexyIconInfo *icon_info = &entry->priv->icons[icon_pos]; - GdkPixbuf *pixbuf; - gint x, y, width, height; - - if (icon_info->icon == NULL || !GTK_WIDGET_REALIZED(widget)) - return; - - if ((pixbuf = get_pixbuf_from_icon(entry, icon_pos)) == NULL) - return; - - gdk_drawable_get_size(icon_info->window, &width, &height); - - if (width == 1 || height == 1) - { - /* - * size_allocate hasn't been called yet. These are the default values. - */ - return; - } - - if (gdk_pixbuf_get_height(pixbuf) > height) - { - GdkPixbuf *temp_pixbuf; - int scale; - - scale = height - (2 * ICON_MARGIN); - - temp_pixbuf = gdk_pixbuf_scale_simple(pixbuf, scale, scale, - GDK_INTERP_BILINEAR); - - g_object_unref(pixbuf); - - pixbuf = temp_pixbuf; - } - - x = (width - gdk_pixbuf_get_width(pixbuf)) / 2; - y = (height - gdk_pixbuf_get_height(pixbuf)) / 2; - - if (icon_info->hovered) - { - GdkPixbuf *temp_pixbuf; - - temp_pixbuf = gdk_pixbuf_copy(pixbuf); - - colorshift_pixbuf(temp_pixbuf, pixbuf, 30); - - g_object_unref(pixbuf); - - pixbuf = temp_pixbuf; - } - - gdk_draw_pixbuf(icon_info->window, widget->style->black_gc, pixbuf, - 0, 0, x, y, -1, -1, - GDK_RGB_DITHER_NORMAL, 0, 0); - - g_object_unref(pixbuf); -} - -static gint -sexy_icon_entry_expose(GtkWidget *widget, GdkEventExpose *event) -{ - SexyIconEntry *entry; - - g_return_val_if_fail(SEXY_IS_ICON_ENTRY(widget), FALSE); - g_return_val_if_fail(event != NULL, FALSE); - - entry = SEXY_ICON_ENTRY(widget); - - if (GTK_WIDGET_DRAWABLE(widget)) - { - gboolean found = FALSE; - int i; - - for (i = 0; i < MAX_ICONS && !found; i++) - { - SexyIconInfo *icon_info = &entry->priv->icons[i]; - - if (event->window == icon_info->window) - { - gint width; - GtkAllocation text_area_alloc; - - get_text_area_size(entry, &text_area_alloc); - gdk_drawable_get_size(icon_info->window, &width, NULL); - - gtk_paint_flat_box(widget->style, icon_info->window, - GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, - NULL, widget, "entry_bg", - 0, 0, width, text_area_alloc.height); - - draw_icon(widget, i); - - found = TRUE; - } - } - - if (!found) - GTK_WIDGET_CLASS(parent_class)->expose_event(widget, event); - } - - return FALSE; -} - -static void -update_icon(GObject *obj, GParamSpec *param, SexyIconEntry *entry) -{ - if (param != NULL) - { - const char *name = g_param_spec_get_name(param); - - if (strcmp(name, "pixbuf") && strcmp(name, "stock") && - strcmp(name, "image") && strcmp(name, "pixmap") && - strcmp(name, "icon_set") && strcmp(name, "pixbuf_animation")) - { - return; - } - } - - gtk_widget_queue_resize(GTK_WIDGET(entry)); -} - -static gint -sexy_icon_entry_enter_notify(GtkWidget *widget, GdkEventCrossing *event) -{ - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - int i; - - for (i = 0; i < MAX_ICONS; i++) - { - if (event->window == entry->priv->icons[i].window) - { - if (sexy_icon_entry_get_icon_highlight(entry, i)) - { - entry->priv->icons[i].hovered = TRUE; - - update_icon(NULL, NULL, entry); - - break; - } - } - } - - return FALSE; -} - -static gint -sexy_icon_entry_leave_notify(GtkWidget *widget, GdkEventCrossing *event) -{ - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - int i; - - for (i = 0; i < MAX_ICONS; i++) - { - if (event->window == entry->priv->icons[i].window) - { - if (sexy_icon_entry_get_icon_highlight(entry, i)) - { - entry->priv->icons[i].hovered = FALSE; - - update_icon(NULL, NULL, entry); - - break; - } - } - } - - return FALSE; -} - -static gint -sexy_icon_entry_button_press(GtkWidget *widget, GdkEventButton *event) -{ - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - int i; - - for (i = 0; i < MAX_ICONS; i++) - { - if (event->window == entry->priv->icons[i].window) - { - if (event->button == 1 && - sexy_icon_entry_get_icon_highlight(entry, i)) - { - entry->priv->icons[i].hovered = FALSE; - - update_icon(NULL, NULL, entry); - } - - g_signal_emit(entry, signals[ICON_PRESSED], 0, i, event->button); - - return TRUE; - } - } - - if (GTK_WIDGET_CLASS(parent_class)->button_press_event) - return GTK_WIDGET_CLASS(parent_class)->button_press_event(widget, - event); - - return FALSE; -} - -static gint -sexy_icon_entry_button_release(GtkWidget *widget, GdkEventButton *event) -{ - SexyIconEntry *entry = SEXY_ICON_ENTRY(widget); - int i; - - for (i = 0; i < MAX_ICONS; i++) - { - GdkWindow *icon_window = entry->priv->icons[i].window; - - if (event->window == icon_window) - { - int width, height; - gdk_drawable_get_size(icon_window, &width, &height); - - if (event->button == 1 && - sexy_icon_entry_get_icon_highlight(entry, i) && - event->x >= 0 && event->y >= 0 && - event->x <= width && event->y <= height) - { - entry->priv->icons[i].hovered = TRUE; - - update_icon(NULL, NULL, entry); - } - - g_signal_emit(entry, signals[ICON_RELEASED], 0, i, event->button); - - return TRUE; - } - } - - if (GTK_WIDGET_CLASS(parent_class)->button_release_event) - return GTK_WIDGET_CLASS(parent_class)->button_release_event(widget, - event); - - return FALSE; -} - -/** - * sexy_icon_entry_new - * - * Creates a new SexyIconEntry widget. - * - * Returns a new #SexyIconEntry. - */ -GtkWidget * -sexy_icon_entry_new(void) -{ - return GTK_WIDGET(g_object_new(SEXY_TYPE_ICON_ENTRY, NULL)); -} - -/** - * sexy_icon_entry_set_icon - * @entry: A #SexyIconEntry. - * @position: Icon position. - * @icon: A #GtkImage to set as the icon. - * - * Sets the icon shown in the entry - */ -void -sexy_icon_entry_set_icon(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, - GtkImage *icon) -{ - SexyIconInfo *icon_info; - - g_return_if_fail(entry != NULL); - g_return_if_fail(SEXY_IS_ICON_ENTRY(entry)); - g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos)); - g_return_if_fail(icon == NULL || GTK_IS_IMAGE(icon)); - - icon_info = &entry->priv->icons[icon_pos]; - - if (icon == icon_info->icon) - return; - - if (icon_pos == SEXY_ICON_ENTRY_SECONDARY && - entry->priv->icon_released_id != 0) - { - g_signal_handler_disconnect(entry, entry->priv->icon_released_id); - entry->priv->icon_released_id = 0; - } - - if (icon == NULL) - { - if (icon_info->icon != NULL) - { - gtk_widget_destroy(GTK_WIDGET(icon_info->icon)); - icon_info->icon = NULL; - - /* - * Explicitly check, as the pointer may become invalidated - * during destruction. - */ - if (icon_info->window != NULL && GDK_IS_WINDOW(icon_info->window)) - gdk_window_hide(icon_info->window); - } - } - else - { - if (icon_info->window != NULL && icon_info->icon == NULL) - gdk_window_show(icon_info->window); - - g_signal_connect(G_OBJECT(icon), "notify", - G_CALLBACK(update_icon), entry); - - icon_info->icon = icon; - g_object_ref(icon); - } - - update_icon(NULL, NULL, entry); -} - -/** - * sexy_icon_entry_set_icon_highlight - * @entry: A #SexyIconEntry; - * @position: Icon position. - * @highlight: TRUE if the icon should highlight on mouse-over - * - * Determines whether the icon will highlight on mouse-over. - */ -void -sexy_icon_entry_set_icon_highlight(SexyIconEntry *entry, - SexyIconEntryPosition icon_pos, - gboolean highlight) -{ - SexyIconInfo *icon_info; - - g_return_if_fail(entry != NULL); - g_return_if_fail(SEXY_IS_ICON_ENTRY(entry)); - g_return_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos)); - - icon_info = &entry->priv->icons[icon_pos]; - - if (icon_info->highlight == highlight) - return; - - icon_info->highlight = highlight; -} - -/** - * sexy_icon_entry_get_icon - * @entry: A #SexyIconEntry. - * @position: Icon position. - * - * Retrieves the image used for the icon - * - * Returns: A #GtkImage. - */ -GtkImage * -sexy_icon_entry_get_icon(const SexyIconEntry *entry, - SexyIconEntryPosition icon_pos) -{ - g_return_val_if_fail(entry != NULL, NULL); - g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), NULL); - g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), NULL); - - return entry->priv->icons[icon_pos].icon; -} - -/** - * sexy_icon_entry_get_icon_highlight - * @entry: A #SexyIconEntry. - * @position: Icon position. - * - * Retrieves whether entry will highlight the icon on mouseover. - * - * Returns: TRUE if icon highlights. - */ -gboolean -sexy_icon_entry_get_icon_highlight(const SexyIconEntry *entry, - SexyIconEntryPosition icon_pos) -{ - g_return_val_if_fail(entry != NULL, FALSE); - g_return_val_if_fail(SEXY_IS_ICON_ENTRY(entry), FALSE); - g_return_val_if_fail(IS_VALID_ICON_ENTRY_POSITION(icon_pos), FALSE); - - return entry->priv->icons[icon_pos].highlight; -} - -static void -clear_button_clicked_cb(SexyIconEntry *icon_entry, - SexyIconEntryPosition icon_pos, - int button) -{ - if (icon_pos != SEXY_ICON_ENTRY_SECONDARY || button != 1) - return; - - gtk_entry_set_text(GTK_ENTRY(icon_entry), ""); -} - -/** - * sexy_icon_entry_add_clear_button - * @icon_entry: A #SexyIconEntry. - * - * A convenience function to add a clear button to the end of the entry. - * This is useful for search boxes. - */ -void -sexy_icon_entry_add_clear_button(SexyIconEntry *icon_entry) -{ - GtkWidget *icon; - - g_return_if_fail(icon_entry != NULL); - g_return_if_fail(SEXY_IS_ICON_ENTRY(icon_entry)); - - icon = gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_MENU); - gtk_widget_show(icon); - sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(icon_entry), - SEXY_ICON_ENTRY_SECONDARY, - GTK_IMAGE(icon)); - sexy_icon_entry_set_icon_highlight(SEXY_ICON_ENTRY(icon_entry), - SEXY_ICON_ENTRY_SECONDARY, TRUE); - - if (icon_entry->priv->icon_released_id != 0) - { - g_signal_handler_disconnect(icon_entry, - icon_entry->priv->icon_released_id); - } - - icon_entry->priv->icon_released_id = - g_signal_connect(G_OBJECT(icon_entry), "icon_released", - G_CALLBACK(clear_button_clicked_cb), NULL); -} - -GType -sexy_icon_entry_position_get_type (void) -{ - static GType etype = 0; - if (etype == 0) { - static const GEnumValue values[] = { - { SEXY_ICON_ENTRY_PRIMARY, "SEXY_ICON_ENTRY_PRIMARY", "primary" }, - { SEXY_ICON_ENTRY_SECONDARY, "SEXY_ICON_ENTRY_SECONDARY", "secondary" }, - { 0, NULL, NULL } - }; - etype = g_enum_register_static ("SexyIconEntryPosition", values); - } - return etype; -} - diff --git a/lib/sugar/sexy-icon-entry.h b/lib/sugar/sexy-icon-entry.h deleted file mode 100644 index eb83fed..0000000 --- a/lib/sugar/sexy-icon-entry.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * @file libsexy/sexy-icon-entry.h Entry widget - * - * @Copyright (C) 2004-2006 Christian Hammond. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef _SEXY_ICON_ENTRY_H_ -#define _SEXY_ICON_ENTRY_H_ - -typedef struct _SexyIconEntry SexyIconEntry; -typedef struct _SexyIconEntryClass SexyIconEntryClass; -typedef struct _SexyIconEntryPriv SexyIconEntryPriv; - -#include -#include - -#define SEXY_TYPE_ICON_ENTRY (sexy_icon_entry_get_type()) -#define SEXY_ICON_ENTRY(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), SEXY_TYPE_ICON_ENTRY, SexyIconEntry)) -#define SEXY_ICON_ENTRY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), SEXY_TYPE_ICON_ENTRY, SexyIconEntryClass)) -#define SEXY_IS_ICON_ENTRY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj), SEXY_TYPE_ICON_ENTRY)) -#define SEXY_IS_ICON_ENTRY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass), SEXY_TYPE_ICON_ENTRY)) -#define SEXY_ICON_ENTRY_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj), SEXY_TYPE_ICON_ENTRY, SexyIconEntryClass)) - -typedef enum -{ - SEXY_ICON_ENTRY_PRIMARY, - SEXY_ICON_ENTRY_SECONDARY - -} SexyIconEntryPosition; - -GType sexy_icon_entry_position_get_type(void); -#define SEXY_TYPE_ICON_ENTRY_POSITION (sexy_icon_entry_position_get_type()) - -struct _SexyIconEntry -{ - GtkEntry parent_object; - - SexyIconEntryPriv *priv; - - void (*gtk_reserved1)(void); - void (*gtk_reserved2)(void); - void (*gtk_reserved3)(void); - void (*gtk_reserved4)(void); -}; - -struct _SexyIconEntryClass -{ - GtkEntryClass parent_class; - - /* Signals */ - void (*icon_pressed)(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, - int button); - void (*icon_released)(SexyIconEntry *entry, SexyIconEntryPosition icon_pos, - int button); - - void (*gtk_reserved1)(void); - void (*gtk_reserved2)(void); - void (*gtk_reserved3)(void); - void (*gtk_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType sexy_icon_entry_get_type(void); - -GtkWidget *sexy_icon_entry_new(void); - -void sexy_icon_entry_set_icon(SexyIconEntry *entry, - SexyIconEntryPosition position, - GtkImage *icon); - -void sexy_icon_entry_set_icon_highlight(SexyIconEntry *entry, - SexyIconEntryPosition position, - gboolean highlight); - -GtkImage *sexy_icon_entry_get_icon(const SexyIconEntry *entry, - SexyIconEntryPosition position); - -gboolean sexy_icon_entry_get_icon_highlight(const SexyIconEntry *entry, - SexyIconEntryPosition position); -void sexy_icon_entry_add_clear_button(SexyIconEntry *icon_entry); - -G_END_DECLS - -#endif /* _SEXY_ICON_ENTRY_H_ */ diff --git a/lib/sugar/sugar-address-entry.c b/lib/sugar/sugar-address-entry.c deleted file mode 100644 index 7b6d525..0000000 --- a/lib/sugar/sugar-address-entry.c +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include - -#include "sugar-address-entry.h" - -enum { - PROP_0, - PROP_PROGRESS, - PROP_ADDRESS, - PROP_TITLE -}; - -typedef enum { - CURSOR_STANDARD, - CURSOR_DND -} CursorType; - -static void _gtk_entry_effective_inner_border (GtkEntry *entry, - GtkBorder *border); -static void get_text_area_size (GtkEntry *entry, - gint *x, - gint *y, - gint *width, - gint *height); - -G_DEFINE_TYPE(SugarAddressEntry, sugar_address_entry, GTK_TYPE_ENTRY) - -static GQuark quark_inner_border = 0; -static const GtkBorder default_inner_border = { 2, 2, 2, 2 }; - -static void -draw_insertion_cursor (GtkEntry *entry, - GdkRectangle *cursor_location, - gboolean is_primary, - PangoDirection direction, - gboolean draw_arrow) -{ - GtkWidget *widget = GTK_WIDGET (entry); - GtkTextDirection text_dir; - - if (direction == PANGO_DIRECTION_LTR) - text_dir = GTK_TEXT_DIR_LTR; - else - text_dir = GTK_TEXT_DIR_RTL; - - gtk_draw_insertion_cursor (widget, entry->text_area, NULL, - cursor_location, - is_primary, text_dir, draw_arrow); -} - -static void -gtk_entry_get_pixel_ranges (GtkEntry *entry, - gint **ranges, - gint *n_ranges) -{ - gint start_char, end_char; - - if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_char, &end_char)) - { - //PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); - PangoLayout *layout = gtk_entry_get_layout (entry); - PangoLayoutLine *line = pango_layout_get_lines (layout)->data; - const char *text = pango_layout_get_text (layout); - gint start_index = g_utf8_offset_to_pointer (text, start_char) - text; - gint end_index = g_utf8_offset_to_pointer (text, end_char) - text; - gint real_n_ranges, i; - - pango_layout_line_get_x_ranges (line, start_index, end_index, ranges, &real_n_ranges); - - if (ranges) - { - gint *r = *ranges; - - for (i = 0; i < real_n_ranges; ++i) - { - r[2 * i + 1] = (r[2 * i + 1] - r[2 * i]) / PANGO_SCALE; - r[2 * i] = r[2 * i] / PANGO_SCALE; - } - } - - if (n_ranges) - *n_ranges = real_n_ranges; - } - else - { - if (n_ranges) - *n_ranges = 0; - if (ranges) - *ranges = NULL; - } -} - -static void -gtk_entry_get_cursor_locations (GtkEntry *entry, - CursorType type, - gint *strong_x, - gint *weak_x) -{ - if (!entry->visible && !entry->invisible_char) - { - if (strong_x) - *strong_x = 0; - - if (weak_x) - *weak_x = 0; - } - else - { - //PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); - PangoLayout *layout = gtk_entry_get_layout (entry); - const gchar *text = pango_layout_get_text (layout); - PangoRectangle strong_pos, weak_pos; - gint index; - - if (type == CURSOR_STANDARD) - { - index = g_utf8_offset_to_pointer (text, entry->current_pos + entry->preedit_cursor) - text; - } - else /* type == CURSOR_DND */ - { - index = g_utf8_offset_to_pointer (text, entry->dnd_position) - text; - - if (entry->dnd_position > entry->current_pos) - { - if (entry->visible) - index += entry->preedit_length; - else - { - gint preedit_len_chars = g_utf8_strlen (text, -1) - entry->text_length; - index += preedit_len_chars * g_unichar_to_utf8 (entry->invisible_char, NULL); - } - } - } - - pango_layout_get_cursor_pos (layout, index, &strong_pos, &weak_pos); - - if (strong_x) - *strong_x = strong_pos.x / PANGO_SCALE; - - if (weak_x) - *weak_x = weak_pos.x / PANGO_SCALE; - } -} - -static void -gtk_entry_draw_cursor (GtkEntry *entry, - CursorType type) -{ - GdkKeymap *keymap = gdk_keymap_get_for_display (gtk_widget_get_display (GTK_WIDGET (entry))); - PangoDirection keymap_direction = gdk_keymap_get_direction (keymap); - - if (GTK_WIDGET_DRAWABLE (entry)) - { - GtkWidget *widget = GTK_WIDGET (entry); - GdkRectangle cursor_location; - gboolean split_cursor; - - GtkBorder inner_border; - gint xoffset; - gint strong_x, weak_x; - gint text_area_height; - PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL; - PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL; - gint x1 = 0; - gint x2 = 0; - - _gtk_entry_effective_inner_border (entry, &inner_border); - - xoffset = inner_border.left - entry->scroll_offset; - - gdk_drawable_get_size (entry->text_area, NULL, &text_area_height); - - gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x); - - g_object_get (gtk_widget_get_settings (widget), - "gtk-split-cursor", &split_cursor, - NULL); - - dir1 = entry->resolved_dir; - - if (split_cursor) - { - x1 = strong_x; - - if (weak_x != strong_x) - { - dir2 = (entry->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR; - x2 = weak_x; - } - } - else - { - if (keymap_direction == entry->resolved_dir) - x1 = strong_x; - else - x1 = weak_x; - } - - cursor_location.x = xoffset + x1; - cursor_location.y = inner_border.top; - cursor_location.width = 0; - cursor_location.height = text_area_height - inner_border.top - inner_border.bottom; - - draw_insertion_cursor (entry, - &cursor_location, TRUE, dir1, - dir2 != PANGO_DIRECTION_NEUTRAL); - - if (dir2 != PANGO_DIRECTION_NEUTRAL) - { - cursor_location.x = xoffset + x2; - draw_insertion_cursor (entry, - &cursor_location, FALSE, dir2, - TRUE); - } - } -} - -static void -get_layout_position (GtkEntry *entry, - gint *x, - gint *y) -{ - PangoLayout *layout; - PangoRectangle logical_rect; - gint area_width, area_height; - GtkBorder inner_border; - gint y_pos; - PangoLayoutLine *line; - -// layout = gtk_entry_ensure_layout (entry, TRUE); - layout = gtk_entry_get_layout(entry); - - get_text_area_size (entry, NULL, NULL, &area_width, &area_height); - _gtk_entry_effective_inner_border (entry, &inner_border); - - area_height = PANGO_SCALE * (area_height - inner_border.top - inner_border.bottom); - - line = pango_layout_get_lines (layout)->data; - pango_layout_line_get_extents (line, NULL, &logical_rect); - - /* Align primarily for locale's ascent/descent */ - y_pos = ((area_height - entry->ascent - entry->descent) / 2 + - entry->ascent + logical_rect.y); - - /* Now see if we need to adjust to fit in actual drawn string */ - if (logical_rect.height > area_height) - y_pos = (area_height - logical_rect.height) / 2; - else if (y_pos < 0) - y_pos = 0; - else if (y_pos + logical_rect.height > area_height) - y_pos = area_height - logical_rect.height; - - y_pos = inner_border.top + y_pos / PANGO_SCALE; - - if (x) - *x = inner_border.left - entry->scroll_offset; - - if (y) - *y = y_pos; -} - -static void -_gtk_entry_effective_inner_border (GtkEntry *entry, - GtkBorder *border) -{ - GtkBorder *tmp_border; - - tmp_border = g_object_get_qdata (G_OBJECT (entry), quark_inner_border); - - if (tmp_border) - { - *border = *tmp_border; - return; - } - - gtk_widget_style_get (GTK_WIDGET (entry), "inner-border", &tmp_border, NULL); - - if (tmp_border) - { - *border = *tmp_border; - gtk_border_free (tmp_border); - return; - } - - *border = default_inner_border; -} - -static void -gtk_entry_draw_text (GtkEntry *entry) -{ - GtkWidget *widget; - - if (!entry->visible && entry->invisible_char == 0) - return; - - if (GTK_WIDGET_DRAWABLE (entry)) - { - //PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE); - PangoLayout *layout = gtk_entry_get_layout (entry); - cairo_t *cr; - gint x, y; - gint start_pos, end_pos; - - widget = GTK_WIDGET (entry); - - get_layout_position (entry, &x, &y); - - cr = gdk_cairo_create (entry->text_area); - - cairo_move_to (cr, x, y); - gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]); - pango_cairo_show_layout (cr, layout); - - if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry), &start_pos, &end_pos)) - { - gint *ranges; - gint n_ranges, i; - PangoRectangle logical_rect; - GdkColor *selection_color, *text_color; - GtkBorder inner_border; - - pango_layout_get_pixel_extents (layout, NULL, &logical_rect); - gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges); - - if (GTK_WIDGET_HAS_FOCUS (entry)) - { - selection_color = &widget->style->base [GTK_STATE_SELECTED]; - text_color = &widget->style->text [GTK_STATE_SELECTED]; - } - else - { - selection_color = &widget->style->base [GTK_STATE_ACTIVE]; - text_color = &widget->style->text [GTK_STATE_ACTIVE]; - } - - _gtk_entry_effective_inner_border (entry, &inner_border); - - for (i = 0; i < n_ranges; ++i) - cairo_rectangle (cr, - inner_border.left - entry->scroll_offset + ranges[2 * i], - y, - ranges[2 * i + 1], - logical_rect.height); - - cairo_clip (cr); - - gdk_cairo_set_source_color (cr, selection_color); - cairo_paint (cr); - - cairo_move_to (cr, x, y); - gdk_cairo_set_source_color (cr, text_color); - pango_cairo_show_layout (cr, layout); - - g_free (ranges); - } - - cairo_destroy (cr); - } -} - -static void -sugar_address_entry_get_borders (GtkEntry *entry, - gint *xborder, - gint *yborder) -{ - GtkWidget *widget = GTK_WIDGET (entry); - gint focus_width; - gboolean interior_focus; - - gtk_widget_style_get (widget, - "interior-focus", &interior_focus, - "focus-line-width", &focus_width, - NULL); - - if (entry->has_frame) - { - *xborder = widget->style->xthickness; - *yborder = widget->style->ythickness; - } - else - { - *xborder = 0; - *yborder = 0; - } - - if (!interior_focus) - { - *xborder += focus_width; - *yborder += focus_width; - } -} - -static void -get_text_area_size (GtkEntry *entry, - gint *x, - gint *y, - gint *width, - gint *height) -{ - gint xborder, yborder; - GtkRequisition requisition; - GtkWidget *widget = GTK_WIDGET (entry); - - gtk_widget_get_child_requisition (widget, &requisition); - - sugar_address_entry_get_borders (entry, &xborder, &yborder); - - if (x) - *x = xborder; - - if (y) - *y = yborder; - - if (width) - *width = GTK_WIDGET (entry)->allocation.width - xborder * 2; - - if (height) - *height = requisition.height - yborder * 2; -} - -static gint -sugar_address_entry_expose(GtkWidget *widget, - GdkEventExpose *event) -{ - GtkEntry *entry = GTK_ENTRY (widget); - SugarAddressEntry *address_entry = SUGAR_ADDRESS_ENTRY(widget); - cairo_t *cr; - - if (entry->text_area == event->window) { - gint area_width, area_height; - - get_text_area_size (entry, NULL, NULL, &area_width, &area_height); - -/* gtk_paint_flat_box (widget->style, entry->text_area, - GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE, - NULL, widget, "entry_bg", - 0, 0, area_width, area_height); -*/ - - if (address_entry->progress != 0.0 && address_entry->progress != 1.0 && - !GTK_WIDGET_HAS_FOCUS(entry)) { - int bar_width = area_width * address_entry->progress; - float radius = area_height / 2; - - cr = gdk_cairo_create(entry->text_area); - cairo_set_source_rgb(cr, 0xA6 / 255.0, 0xA6 / 255.0, 0xA6 / 255.0); - - cairo_move_to (cr, radius, 0); - cairo_arc (cr, bar_width - radius, radius, radius, M_PI * 1.5, M_PI * 2); - cairo_arc (cr, bar_width - radius, area_height - radius, radius, 0, M_PI * 0.5); - cairo_arc (cr, radius, area_height - radius, radius, M_PI * 0.5, M_PI); - cairo_arc (cr, radius, radius, radius, M_PI, M_PI * 1.5); - - cairo_fill(cr); - cairo_destroy (cr); - } - - - if ((entry->visible || entry->invisible_char != 0) && - GTK_WIDGET_HAS_FOCUS (widget) && - entry->selection_bound == entry->current_pos && entry->cursor_visible) - gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD); - - if (entry->dnd_position != -1) - gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_DND); - - gtk_entry_draw_text (GTK_ENTRY (widget)); - } else { - GtkWidgetClass *parent_class; - parent_class = GTK_WIDGET_CLASS(sugar_address_entry_parent_class); - parent_class->expose_event(widget, event); - } - - return FALSE; -} - -static void -entry_changed_cb(SugarAddressEntry *entry) -{ - if (entry->address) { - g_free (entry->address); - } - - entry->address = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); -} - -static void -update_entry_text(SugarAddressEntry *address_entry, - gboolean has_focus) -{ - g_signal_handlers_block_by_func(address_entry, entry_changed_cb, NULL); - - if (has_focus || address_entry->title == NULL) { - gtk_entry_set_text(GTK_ENTRY(address_entry), - address_entry->address); - } else { - gtk_entry_set_text(GTK_ENTRY(address_entry), - address_entry->title); - } - - g_signal_handlers_unblock_by_func(address_entry, entry_changed_cb, NULL); -} - -static void -sugar_address_entry_set_address(SugarAddressEntry *address_entry, - const char *address) -{ - g_free(address_entry->address); - address_entry->address = g_strdup(address); - - update_entry_text(address_entry, - gtk_widget_is_focus(GTK_WIDGET(address_entry))); -} - -static void -sugar_address_entry_set_title(SugarAddressEntry *address_entry, - const char *title) -{ - g_free(address_entry->title); - address_entry->title = g_strdup(title); - - update_entry_text(address_entry, - gtk_widget_is_focus(GTK_WIDGET(address_entry))); -} - -static void -sugar_address_entry_set_property(GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - SugarAddressEntry *address_entry = SUGAR_ADDRESS_ENTRY(object); - GtkEntry *entry = GTK_ENTRY(object); - - switch (prop_id) { - case PROP_PROGRESS: - address_entry->progress = g_value_get_double(value); - if (GTK_WIDGET_REALIZED(entry)) - gdk_window_invalidate_rect(entry->text_area, NULL, FALSE); - break; - case PROP_ADDRESS: - sugar_address_entry_set_address(address_entry, - g_value_get_string(value)); - break; - case PROP_TITLE: - sugar_address_entry_set_title(address_entry, - g_value_get_string(value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -sugar_address_entry_get_property(GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - SugarAddressEntry *entry = SUGAR_ADDRESS_ENTRY(object); - - switch (prop_id) { - case PROP_PROGRESS: - g_value_set_double(value, entry->progress); - break; - case PROP_TITLE: - g_value_set_string(value, entry->title); - break; - case PROP_ADDRESS: - g_value_set_string(value, entry->address); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -sugar_address_entry_class_init(SugarAddressEntryClass *klass) -{ - GtkWidgetClass *widget_class = (GtkWidgetClass*)klass; - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - - widget_class->expose_event = sugar_address_entry_expose; - - gobject_class->set_property = sugar_address_entry_set_property; - gobject_class->get_property = sugar_address_entry_get_property; - - quark_inner_border = g_quark_from_static_string ("gtk-entry-inner-border"); - - g_object_class_install_property (gobject_class, PROP_PROGRESS, - g_param_spec_double("progress", - "Progress", - "Progress", - 0.0, 1.0, 0.0, - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_TITLE, - g_param_spec_string("title", - "Title", - "Title", - "", - G_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, PROP_ADDRESS, - g_param_spec_string("address", - "Address", - "Address", - "", - G_PARAM_READWRITE)); -} - -static gboolean -button_press_event_cb (GtkWidget *widget, GdkEventButton *event) -{ - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { - gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1); - gtk_widget_grab_focus(widget); - - return TRUE; - } - - return FALSE; -} - -static gboolean -focus_in_event_cb(GtkWidget *widget, GdkEventFocus *event) -{ - update_entry_text(SUGAR_ADDRESS_ENTRY(widget), TRUE); - return FALSE; -} - -static gboolean -focus_out_event_cb(GtkWidget *widget, GdkEventFocus *event) -{ - update_entry_text(SUGAR_ADDRESS_ENTRY(widget), FALSE); - return FALSE; -} - -static void -popup_unmap_cb(GtkWidget *popup, SugarAddressEntry *entry) -{ - g_signal_handlers_unblock_by_func(entry, focus_out_event_cb, NULL); -} - -static void -populate_popup_cb(SugarAddressEntry *entry, GtkWidget *menu) -{ - g_signal_handlers_block_by_func(entry, focus_out_event_cb, NULL); - - g_signal_connect(menu, "unmap", - G_CALLBACK(popup_unmap_cb), entry); -} - -static void -sugar_address_entry_init(SugarAddressEntry *entry) -{ - entry->progress = 0.0; - entry->address = NULL; - entry->title = g_strdup(""); - - g_signal_connect(entry, "focus-in-event", - G_CALLBACK(focus_in_event_cb), NULL); - g_signal_connect(entry, "focus-out-event", - G_CALLBACK(focus_out_event_cb), NULL); - g_signal_connect(entry, "changed", - G_CALLBACK(entry_changed_cb), NULL); - g_signal_connect(entry, "button-press-event", - G_CALLBACK(button_press_event_cb), NULL); - g_signal_connect(entry, "populate-popup", - G_CALLBACK(populate_popup_cb), NULL); -} diff --git a/lib/sugar/sugar-address-entry.h b/lib/sugar/sugar-address-entry.h deleted file mode 100644 index 60c56ab..0000000 --- a/lib/sugar/sugar-address-entry.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2006-2007 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __SUGAR_ADDRESS_ENTRY_H__ -#define __SUGAR_ADDRESS_ENTRY_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _SugarAddressEntry SugarAddressEntry; -typedef struct _SugarAddressEntryClass SugarAddressEntryClass; -typedef struct _SugarAddressEntryPrivate SugarAddressEntryPrivate; - -#define SUGAR_TYPE_ADDRESS_ENTRY (sugar_address_entry_get_type()) -#define SUGAR_ADDRESS_ENTRY(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_ADDRESS_ENTRY, SugarAddressEntry)) -#define SUGAR_ADDRESS_ENTRY_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), SUGAR_TYPE_ADDRESS_ENTRY, SugarAddressEntryClass)) -#define SUGAR_IS_ADDRESS_ENTRY(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_ADDRESS_ENTRY)) -#define SUGAR_IS_ADDRESS_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_ADDRESS_ENTRY)) -#define SUGAR_ADDRESS_ENTRY_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_ADDRESS_ENTRY, SugarAddressEntryClass)) - -struct _SugarAddressEntry { - GtkEntry base_instance; - - float progress; - char *title; - char *address; -}; - -struct _SugarAddressEntryClass { - GtkEntryClass base_class; -}; - -GType sugar_address_entry_get_type (void); - -G_END_DECLS - -#endif /* __SUGAR_ADDRESS_ENTRY_H__ */ diff --git a/lib/sugar/sugar-key-grabber.c b/lib/sugar/sugar-key-grabber.c deleted file mode 100644 index baddab5..0000000 --- a/lib/sugar/sugar-key-grabber.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2006-2007, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include - -#include "sugar-key-grabber.h" -#include "eggaccelerators.h" -#include "sugar-marshal.h" - -/* we exclude shift, GDK_CONTROL_MASK and GDK_MOD1_MASK since we know what - these modifiers mean - these are the mods whose combinations are bound by the keygrabbing code */ -#define IGNORED_MODS (0x2000 /*Xkb modifier*/ | GDK_LOCK_MASK | \ - GDK_MOD2_MASK | GDK_MOD3_MASK | GDK_MOD4_MASK | GDK_MOD5_MASK) -/* these are the ones we actually use for global keys, we always only check - * for these set */ -#define USED_MODS (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) - -enum { - KEY_PRESSED, - KEY_RELEASED, - N_SIGNALS -}; - -typedef struct { - char *key; - guint keysym; - guint state; - guint keycode; -} Key; - -G_DEFINE_TYPE(SugarKeyGrabber, sugar_key_grabber, G_TYPE_OBJECT) - -static guint signals[N_SIGNALS]; - -static void -free_key_info(Key *key_info) -{ - g_free(key_info->key); - g_free(key_info); -} - -static void -sugar_key_grabber_dispose (GObject *object) -{ - SugarKeyGrabber *grabber = SUGAR_KEY_GRABBER(object); - - if (grabber->keys) { - g_list_foreach(grabber->keys, (GFunc)free_key_info, NULL); - g_list_free(grabber->keys); - grabber->keys = NULL; - } -} - -static void -sugar_key_grabber_class_init(SugarKeyGrabberClass *grabber_class) -{ - GObjectClass *g_object_class = G_OBJECT_CLASS (grabber_class); - - g_object_class->dispose = sugar_key_grabber_dispose; - - signals[KEY_PRESSED] = g_signal_new ("key-pressed", - G_TYPE_FROM_CLASS (grabber_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (SugarKeyGrabberClass, key_pressed), - NULL, NULL, - sugar_marshal_BOOLEAN__UINT_UINT, - G_TYPE_BOOLEAN, 2, - G_TYPE_UINT, - G_TYPE_UINT); - signals[KEY_RELEASED] = g_signal_new ("key-released", - G_TYPE_FROM_CLASS (grabber_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (SugarKeyGrabberClass, key_released), - NULL, NULL, - sugar_marshal_BOOLEAN__UINT_UINT, - G_TYPE_BOOLEAN, 2, - G_TYPE_UINT, - G_TYPE_UINT); -} - -char * -sugar_key_grabber_get_key(SugarKeyGrabber *grabber, guint keycode, guint state) -{ - GList *l; - - for (l = grabber->keys; l != NULL; l = l->next) { - Key *keyinfo = (Key *)l->data; - if ((keyinfo->keycode == keycode) && - ((state & USED_MODS) == keyinfo->state)) { - return g_strdup(keyinfo->key); - } - } - - return NULL; -} - -static GdkFilterReturn -filter_events(GdkXEvent *xevent, GdkEvent *event, gpointer data) -{ - SugarKeyGrabber *grabber = (SugarKeyGrabber *)data; - XEvent *xev = (XEvent *)xevent; - - if (xev->type == KeyRelease) { - int return_value; - g_signal_emit (grabber, signals[KEY_RELEASED], 0, xev->xkey.keycode, - xev->xkey.state, &return_value); - if(return_value) - return GDK_FILTER_REMOVE; - } - - if (xev->type == KeyPress) { - int return_value; - g_signal_emit (grabber, signals[KEY_PRESSED], 0, xev->xkey.keycode, - xev->xkey.state, &return_value); - if(return_value) - return GDK_FILTER_REMOVE; - } - - return GDK_FILTER_CONTINUE; -} - -static void -sugar_key_grabber_init(SugarKeyGrabber *grabber) -{ - GdkScreen *screen; - - screen = gdk_screen_get_default(); - grabber->root = gdk_screen_get_root_window(screen); - grabber->keys = NULL; - - gdk_window_add_filter(grabber->root, filter_events, grabber); -} - -/* grab_key and grab_key_real are from - * gnome-control-center/gnome-settings-daemon/gnome-settings-multimedia-keys.c - */ - -static gboolean -grab_key_real (Key *key, GdkWindow *root, gboolean grab, int result) -{ - gdk_error_trap_push (); - if (grab) - XGrabKey (GDK_DISPLAY(), key->keycode, (result | key->state), - GDK_WINDOW_XID (root), True, GrabModeAsync, GrabModeAsync); - else - XUngrabKey(GDK_DISPLAY(), key->keycode, (result | key->state), - GDK_WINDOW_XID (root)); - gdk_flush (); - - gdk_error_trap_pop (); - - return TRUE; -} - -#define N_BITS 32 -static void -grab_key (SugarKeyGrabber *grabber, Key *key, gboolean grab) -{ - int indexes[N_BITS];/*indexes of bits we need to flip*/ - int i, bit, bits_set_cnt; - int uppervalue; - guint mask_to_traverse = IGNORED_MODS & ~ key->state; - - bit = 0; - for (i = 0; i < N_BITS; i++) { - if (mask_to_traverse & (1<root, grab, result) == FALSE) - return; - } -} - -void -sugar_key_grabber_grab(SugarKeyGrabber *grabber, const char *key) -{ - Key *keyinfo; - - keyinfo = g_new0 (Key, 1); - keyinfo->key = g_strdup(key); - egg_accelerator_parse_virtual (key, &keyinfo->keysym, - &keyinfo->keycode, &keyinfo->state); - - grab_key(grabber, keyinfo, TRUE); - - grabber->keys = g_list_append(grabber->keys, keyinfo); -} diff --git a/lib/sugar/sugar-key-grabber.h b/lib/sugar/sugar-key-grabber.h deleted file mode 100644 index 5b734e7..0000000 --- a/lib/sugar/sugar-key-grabber.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2006-2007, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __SUGAR_KEY_GRABBER_H__ -#define __SUGAR_KEY_GRABBER_H__ - -#include -#include - -G_BEGIN_DECLS - -typedef struct _SugarKeyGrabber SugarKeyGrabber; -typedef struct _SugarKeyGrabberClass SugarKeyGrabberClass; -typedef struct _SugarKeyGrabberPrivate SugarKeyGrabberPrivate; - -#define SUGAR_TYPE_KEY_GRABBER (sugar_key_grabber_get_type()) -#define SUGAR_KEY_GRABBER(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_KEY_GRABBER, SugarKeyGrabber)) -#define SUGAR_KEY_GRABBER_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), SUGAR_TYPE_KEY_GRABBER, SugarKeyGrabberClass)) -#define SUGAR_IS_KEY_GRABBER(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_KEY_GRABBER)) -#define SUGAR_IS_KEYGRABBER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_KEY_GRABBER)) -#define SUGAR_KEY_GRABBER_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_KEY_GRABBER, SugarKeyGrabberClass)) - -struct _SugarKeyGrabber { - GObject base_instance; - - GdkWindow *root; - GList *keys; -}; - -struct _SugarKeyGrabberClass { - GObjectClass base_class; - - gboolean (* key_pressed) (SugarKeyGrabber *grabber, - guint keycode, - guint state); - gboolean (* key_released) (SugarKeyGrabber *grabber, - guint keycode, - guint state); -}; - -GType sugar_key_grabber_get_type (void); -void sugar_key_grabber_grab (SugarKeyGrabber *grabber, - const char *key); -char *sugar_key_grabber_get_key (SugarKeyGrabber *grabber, - guint keycode, - guint state); - -G_END_DECLS - -#endif /* __SUGAR_KEY_GRABBER_H__ */ diff --git a/lib/sugar/sugar-marshal.list b/lib/sugar/sugar-marshal.list deleted file mode 100644 index 41ce620..0000000 --- a/lib/sugar/sugar-marshal.list +++ /dev/null @@ -1 +0,0 @@ -BOOLEAN:UINT,UINT diff --git a/lib/sugar/sugar-menu.c b/lib/sugar/sugar-menu.c deleted file mode 100644 index f19dc4b..0000000 --- a/lib/sugar/sugar-menu.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2006-2007, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -#include "sugar-menu.h" - -static void sugar_menu_class_init (SugarMenuClass *menu_class); -static void sugar_menu_init (SugarMenu *menu); - - -G_DEFINE_TYPE(SugarMenu, sugar_menu, GTK_TYPE_MENU) - -void -sugar_menu_set_active(SugarMenu *menu, gboolean active) -{ - GTK_MENU_SHELL(menu)->active = active; -} - -void -sugar_menu_embed(SugarMenu *menu, GtkContainer *parent) -{ - menu->orig_toplevel = GTK_MENU(menu)->toplevel; - - GTK_MENU(menu)->toplevel = gtk_widget_get_toplevel(GTK_WIDGET(parent)); - gtk_widget_reparent(GTK_WIDGET(menu), GTK_WIDGET(parent)); -} - -void -sugar_menu_unembed(SugarMenu *menu) -{ - if (menu->orig_toplevel) { - GTK_MENU(menu)->toplevel = menu->orig_toplevel; - gtk_widget_reparent(GTK_WIDGET(menu), GTK_WIDGET(menu->orig_toplevel)); - } -} - -static void -sugar_menu_class_init(SugarMenuClass *menu_class) -{ -} - -static void -sugar_menu_init(SugarMenu *menu) -{ - menu->orig_toplevel = NULL; -} diff --git a/lib/sugar/sugar-menu.h b/lib/sugar/sugar-menu.h deleted file mode 100644 index 8773a31..0000000 --- a/lib/sugar/sugar-menu.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2006-2007, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __SUGAR_MENU_H__ -#define __SUGAR_MENU_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _SugarMenu SugarMenu; -typedef struct _SugarMenuClass SugarMenuClass; - -#define SUGAR_TYPE_MENU (sugar_menu_get_type()) -#define SUGAR_MENU(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_MENU, SugarMenu)) -#define SUGAR_MENU_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), SUGAR_TYPE_MENU, SugarMenuClass)) -#define SUGAR_IS_MENU(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_MENU)) -#define SUGAR_IS_MENU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_MENU)) -#define SUGAR_MENU_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_MENU, SugarMenuClass)) - -struct _SugarMenu { - GtkMenu base_instance; - - GtkWidget *orig_toplevel; - int min_width; -}; - -struct _SugarMenuClass { - GtkMenuClass base_class; -}; - -GType sugar_menu_get_type (void); -void sugar_menu_set_active (SugarMenu *menu, - gboolean active); -void sugar_menu_embed (SugarMenu *menu, - GtkContainer *parent); - -G_END_DECLS - -#endif /* __SUGAR_MENU_H__ */ diff --git a/lib/sugar/sugar-preview.c b/lib/sugar/sugar-preview.c deleted file mode 100644 index f54045b..0000000 --- a/lib/sugar/sugar-preview.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2007, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include - -#include "sugar-preview.h" - -static void sugar_preview_class_init (SugarPreviewClass *menu_class); -static void sugar_preview_init (SugarPreview *menu); - -G_DEFINE_TYPE(SugarPreview, sugar_preview, G_TYPE_OBJECT) - -void -sugar_preview_set_size(SugarPreview *preview, int width, int height) -{ - preview->width = width; - preview->height = height; -} - -GdkPixbuf * -sugar_preview_get_pixbuf(SugarPreview *preview) -{ - GdkPixbuf *pixbuf; - - if (preview->pixbuf != NULL) { - return preview->pixbuf; - } - - if (preview->image == NULL) { - return NULL; - } - - preview->pixbuf = gdk_pixbuf_get_from_image(NULL, preview->image, NULL, - 0, 0, 0, 0, - preview->image->width, - preview->image->height); - g_object_unref(G_OBJECT(preview->image)); - preview->image = NULL; - - return preview->pixbuf; -} - -void -sugar_preview_clear(SugarPreview *preview) -{ - if (preview->image != NULL) { - g_object_unref(G_OBJECT(preview->image)); - preview->image = NULL; - } - if (preview->pixbuf != NULL) { - g_object_unref(G_OBJECT(preview->pixbuf)); - preview->pixbuf = NULL; - } -} - -void -sugar_preview_take_screenshot(SugarPreview *preview, GdkDrawable *drawable) -{ - GdkScreen *screen; - GdkVisual *visual; - GdkColormap *colormap; - gint width, height; - - sugar_preview_clear(preview); - - gdk_drawable_get_size(drawable, &width, &height); - - screen = gdk_drawable_get_screen(drawable); - visual = gdk_drawable_get_visual(drawable); - colormap = gdk_drawable_get_colormap(drawable); - - preview->image = gdk_image_new(GDK_IMAGE_SHARED, visual, width, height); - gdk_image_set_colormap(preview->image, colormap); - - XShmGetImage(GDK_SCREEN_XDISPLAY(screen), - GDK_DRAWABLE_XID(drawable), - gdk_x11_image_get_ximage(preview->image), - 0, 0, AllPlanes, ZPixmap); -} - -static void -sugar_preview_dispose(GObject *object) -{ - SugarPreview *preview = SUGAR_PREVIEW(object); - sugar_preview_clear(preview); -} - -static void -sugar_preview_class_init(SugarPreviewClass *preview_class) -{ - GObjectClass *g_object_class = G_OBJECT_CLASS (preview_class); - - g_object_class->dispose = sugar_preview_dispose; -} - -static void -sugar_preview_init(SugarPreview *preview) -{ - preview->image = NULL; - preview->pixbuf = NULL; -} diff --git a/lib/sugar/sugar-preview.h b/lib/sugar/sugar-preview.h deleted file mode 100644 index 6029cc1..0000000 --- a/lib/sugar/sugar-preview.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __SUGAR_PREVIEW_H__ -#define __SUGAR_PREVIEW_H__ - -#include - -G_BEGIN_DECLS - -typedef struct _SugarPreview SugarPreview; -typedef struct _SugarPreviewClass SugarPreviewClass; - -#define SUGAR_TYPE_PREVIEW (sugar_preview_get_type()) -#define SUGAR_PREVIEW(object) (G_TYPE_CHECK_INSTANCE_CAST((object), SUGAR_TYPE_PREVIEW, SugarPreview)) -#define SUGAR_PREVIEW_CLASS(klass) (G_TYPE_CHACK_CLASS_CAST((klass), SUGAR_TYPE_PREVIEW, SugarPreviewClass)) -#define SUGAR_IS_PREVIEW(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), SUGAR_TYPE_PREVIEW)) -#define SUGAR_IS_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SUGAR_TYPE_PREVIEW)) -#define SUGAR_PREVIEW_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object), SUGAR_TYPE_PREVIEW, SugarPreviewClass)) - -struct _SugarPreview { - GObject base_instance; - - GdkImage *image; - GdkPixbuf *pixbuf; - - int width; - int height; -}; - -struct _SugarPreviewClass { - GObjectClass base_class; -}; - -GType sugar_preview_get_type (void); -void sugar_preview_take_screenshot (SugarPreview *preview, - GdkDrawable *drawable); -void sugar_preview_set_size (SugarPreview *preview, - int width, - int height); -GdkPixbuf *sugar_preview_get_pixbuf (SugarPreview *preview); -void sugar_preview_clear (SugarPreview *preview); - -G_END_DECLS - -#endif /* __SUGAR_PREVIEW_H__ */ diff --git a/lib/sugar/util.py b/lib/sugar/util.py deleted file mode 100644 index 8a3fb4a..0000000 --- a/lib/sugar/util.py +++ /dev/null @@ -1,175 +0,0 @@ -"""Various utility functions""" -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import time -import sha -import random -import binascii -import string -import os -import logging - -from ConfigParser import ConfigParser -from ConfigParser import NoOptionError - -def printable_hash(in_hash): - """Convert binary hash data into printable characters.""" - printable = "" - for char in in_hash: - printable = printable + binascii.b2a_hex(char) - return printable - -def _sha_data(data): - """sha1 hash some bytes.""" - sha_hash = sha.new() - sha_hash.update(data) - return sha_hash.digest() - -def unique_id(data = ''): - """Generate a likely-unique ID for whatever purpose - - data -- suffix appended to working data before hashing - - Returns a 40-character string with hexidecimal digits - representing an SHA hash of the time, a random digit - within a constrained range and the data passed. - - Note: these are *not* crypotographically secure or - globally unique identifiers. While they are likely - to be unique-enough, no attempt is made to make - perfectly unique values. - """ - data_string = "%s%s%s" % (time.time(), random.randint(10000, 100000), data) - return printable_hash(_sha_data(data_string)) - - -ACTIVITY_ID_LEN = 40 - -def is_hex(s): - return s.strip(string.hexdigits) == '' - -def validate_activity_id(actid): - """Validate an activity ID.""" - if not isinstance(actid, (str,unicode)): - return False - if len(actid) != ACTIVITY_ID_LEN: - return False - if not is_hex(actid): - return False - return True - -def set_proc_title(title): - """Sets the process title so ps and top show more - descriptive names. This does not modify argv[0] - and only the first 15 characters will be shown. - - title -- the title you wish to change the process - title to - - Returns True on success. We don't raise exceptions - because if something goes wrong here it is not a big - deal as this is intended as a nice thing to have for - debugging - """ - try: - import ctypes - libc = ctypes.CDLL('libc.so.6') - libc.prctl(15, str(title), 0, 0, 0) - - return True - except: - return False - -class Node(object): - __slots__ = ['prev', 'next', 'me'] - def __init__(self, prev, me): - self.prev = prev - self.me = me - self.next = None - -class LRU: - """ - Implementation of a length-limited O(1) LRU queue. - Built for and used by PyPE: - http://pype.sourceforge.net - Copyright 2003 Josiah Carlson. - """ - def __init__(self, count, pairs=[]): - self.count = max(count, 1) - self.d = {} - self.first = None - self.last = None - for key, value in pairs: - self[key] = value - def __contains__(self, obj): - return obj in self.d - def __getitem__(self, obj): - a = self.d[obj].me - self[a[0]] = a[1] - return a[1] - def __setitem__(self, obj, val): - if obj in self.d: - del self[obj] - nobj = Node(self.last, (obj, val)) - if self.first is None: - self.first = nobj - if self.last: - self.last.next = nobj - self.last = nobj - self.d[obj] = nobj - if len(self.d) > self.count: - if self.first == self.last: - self.first = None - self.last = None - return - a = self.first - a.next.prev = None - self.first = a.next - a.next = None - del self.d[a.me[0]] - del a - def __delitem__(self, obj): - nobj = self.d[obj] - if nobj.prev: - nobj.prev.next = nobj.next - else: - self.first = nobj.next - if nobj.next: - nobj.next.prev = nobj.prev - else: - self.last = nobj.prev - del self.d[obj] - def __iter__(self): - cur = self.first - while cur != None: - cur2 = cur.next - yield cur.me[1] - cur = cur2 - def iteritems(self): - cur = self.first - while cur != None: - cur2 = cur.next - yield cur.me - cur = cur2 - def iterkeys(self): - return iter(self.d) - def itervalues(self): - for i,j in self.iteritems(): - yield j - def keys(self): - return self.d.keys() diff --git a/lib/sugar/wm.py b/lib/sugar/wm.py deleted file mode 100644 index 47356a5..0000000 --- a/lib/sugar/wm.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk - -def get_activity_id(wnck_window): - window = gtk.gdk.window_foreign_new(wnck_window.get_xid()) - prop_info = window.property_get('_SUGAR_ACTIVITY_ID', 'STRING') - if prop_info is None: - return None - else: - return prop_info[2] - -def get_bundle_id(wnck_window): - window = gtk.gdk.window_foreign_new(wnck_window.get_xid()) - prop_info = window.property_get('_SUGAR_BUNDLE_ID', 'STRING') - if prop_info is None: - return None - else: - return prop_info[2] - -def set_activity_id(window, activity_id): - window.property_change('_SUGAR_ACTIVITY_ID', 'STRING', 8, - gtk.gdk.PROP_MODE_REPLACE, activity_id) - -def set_bundle_id(window, bundle_id): - window.property_change('_SUGAR_BUNDLE_ID', 'STRING', 8, - gtk.gdk.PROP_MODE_REPLACE, bundle_id) diff --git a/m4/python.m4 b/m4/python.m4 deleted file mode 100644 index e1c5266..0000000 --- a/m4/python.m4 +++ /dev/null @@ -1,62 +0,0 @@ -## this one is commonly used with AM_PATH_PYTHONDIR ... -dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]]) -dnl Check if a module containing a given symbol is visible to python. -AC_DEFUN([AM_CHECK_PYMOD], -[AC_REQUIRE([AM_PATH_PYTHON]) -py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'` -AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1) -AC_CACHE_VAL(py_cv_mod_$py_mod_var, [ -ifelse([$2],[], [prog=" -import sys -try: - import $1 -except ImportError: - sys.exit(1) -except: - sys.exit(0) -sys.exit(0)"], [prog=" -import $1 -$1.$2"]) -if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC - then - eval "py_cv_mod_$py_mod_var=yes" - else - eval "py_cv_mod_$py_mod_var=no" - fi -]) -py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"` -if test "x$py_val" != xno; then - AC_MSG_RESULT(yes) - ifelse([$3], [],, [$3 -])dnl -else - AC_MSG_RESULT(no) - ifelse([$4], [],, [$4 -])dnl -fi -]) - -dnl a macro to check for ability to create python extensions -dnl AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE]) -dnl function also defines PYTHON_INCLUDES -AC_DEFUN([AM_CHECK_PYTHON_HEADERS], -[AC_REQUIRE([AM_PATH_PYTHON]) -AC_MSG_CHECKING(for headers required to compile python extensions) -dnl deduce PYTHON_INCLUDES -py_prefix=`$PYTHON -c "import sys; print sys.prefix"` -py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"` -PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}" -if test "$py_prefix" != "$py_exec_prefix"; then - PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}" -fi -AC_SUBST(PYTHON_INCLUDES) -dnl check if the headers exist: -save_CPPFLAGS="$CPPFLAGS" -CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES" -AC_TRY_CPP([#include ],dnl -[AC_MSG_RESULT(found) -$1],dnl -[AC_MSG_RESULT(not found) -$2]) -CPPFLAGS="$save_CPPFLAGS" -]) diff --git a/maint-helper.py b/maint-helper.py deleted file mode 100755 index 7192de4..0000000 --- a/maint-helper.py +++ /dev/null @@ -1,227 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2007, Red Hat, Inc. -# -# 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 - -# Latest source available at git://dev.laptop.org/sugar - -import os -import sys -import re -import datetime -import subprocess - -source_exts = [ '.py', '.c', '.h', '.cpp' ] - -def is_source(path): - for ext in source_exts: - if path.endswith(ext): - return True - -def get_name_and_version(): - f = open('configure.ac', 'r') - config = f.read() - f.close() - - exp = 'AC_INIT\(\[[^\]]+\],\[([^\]]+)\],\[\],\[([^\]]+)\]' - match = re.search(exp, config) - if not match: - print 'Cannot find the package name and version.' - sys.exit(0) - - return [ match.group(2), match.group(1) ] - -def cmd_help(): - print 'Usage: \n\ -maint-helper.py build-snapshot - build a source snapshot \n\ -maint-helper.py fix-copyright [path] - fix the copyright year \n\ -maint-helper.py check-licenses - check licenses in the source' - -def cmd_build_snapshot(): - [ name, version ] = get_name_and_version() - - print 'Update git...' - - retcode = subprocess.call(['git', 'pull']) - if retcode: - print 'ERROR - cannot pull from git' - - cmd = 'git-show-ref --hash=10 refs/heads/master' - alphatag = os.popen(cmd).readline().strip() - - tarball = '%s-%s-git%s.tar.bz2' % (name, version, alphatag) - - print 'Build %s...' % tarball - - retcode = subprocess.call(['make', 'distcheck']) - if retcode: - sys.exit(0) - - if 'JOYBUILD_PATH' in os.environ: - tarball = os.path.join(os.environ['JOYBUILD_PATH'], 'source', tarball) - os.rename('%s-%s.tar.bz2' % (name, version), tarball) - - print 'Update NEWS.sugar...' - - if os.environ.has_key('SUGAR_NEWS'): - sugar_news_path = os.environ['SUGAR_NEWS'] - if os.path.isfile(sugar_news_path): - f = open(sugar_news_path, 'r') - sugar_news = f.read() - f.close() - else: - sugar_news = '' - - [ name, version ] = get_name_and_version() - sugar_news += '%s - %s - %s\n\n' % (name, version, alphatag) - - f = open('NEWS', 'r') - for line in f.readlines(): - if len(line.strip()) > 0: - sugar_news += line - else: - break - f.close() - - f = open(sugar_news_path, 'w') - f.write(sugar_news) - f.close() - - print 'Update NEWS...' - - f = open('NEWS', 'r') - news = f.read() - f.close() - - news = 'Snapshot %s\n\n' % alphatag + news - - f = open('NEWS', 'w') - f.write(news) - f.close() - - print 'Committing to git...' - - changelog = 'Snapshot %s.' % alphatag - retcode = subprocess.call(['git', 'commit', '-a', '-m % s' % changelog]) - if retcode: - print 'ERROR - cannot commit to git' - - retcode = subprocess.call(['git', 'push']) - if retcode: - print 'ERROR - cannot push to git' - - print 'Done.' - -def check_licenses(path, license, missing): - matchers = { 'LGPL' : 'GNU Lesser General Public', - 'GPL' : 'GNU General Public License' } - - license_file = os.path.join(path, '.license') - if os.path.isfile(license_file): - f = open(license_file, 'r') - license = f.readline().strip() - f.close() - - for item in os.listdir(path): - full_path = os.path.join(path, item) - - if os.path.isdir(full_path): - check_licenses(full_path, license, missing) - else: - check_source = is_source(item) - - # Special cases. - if item.find('marshal') > 0 or \ - item.startswith('egg') > 0: - check_source = False - - if check_source: - f = open(full_path, 'r') - source = f.read() - f.close() - - miss_license = True - if source.find(matchers[license]) > 0: - miss_license = False - - # Special cases. - if source.find('THIS FILE IS GENERATED') > 0: - miss_license = False - - if miss_license: - if not missing.has_key(license): - missing[license] = [] - missing[license].append(full_path) - -def cmd_check_licenses(): - missing = {} - check_licenses(os.getcwd(), 'GPL', missing) - - for item in missing.keys(): - print '%s:\n' % item - for path in missing[item]: - print path - print '\n' - -COPYRIGHT = 'Copyright (C) ' - -def fix_copyright(path): - for item in os.listdir(path): - full_path = os.path.join(path, item) - - if os.path.isdir(full_path): - fix_copyright(full_path) - elif is_source(item): - f = open(full_path, 'r') - source = f.read() - f.close() - - year_start = -1 - year_end = -1 - - i1 = source.find(COPYRIGHT) - if i1 != -1: - i1 += len(COPYRIGHT) - i2 = i1 + source[i1:].find(' ') - if i1 > 0: - try: - year_start = int(source[i1:i1 + 4]) - year_end = int(source[i1 + 6: i1 + 10]) - except ValueError: - pass - - if year_start > 0 and year_end < 0: - year_end = year_start - - year = datetime.date.today().year - if year_end < year: - result = '%s%d-%d%s' % (source[:i1], year_start, - year, source[i2:]) - f = open(full_path, 'w') - f.write(result) - f.close() - -def cmd_fix_copyright(path): - fix_copyright(path) - -if len(sys.argv) < 2: - cmd_help() -elif sys.argv[1] == 'build-snapshot': - cmd_build_snapshot() -elif sys.argv[1] == 'check-licenses': - cmd_check_licenses() -elif sys.argv[1] == 'fix-copyright' and len(sys.argv) > 2: - cmd_fix_copyright(sys.argv[2]) diff --git a/pylint.sh b/pylint.sh deleted file mode 100755 index f055f2e..0000000 --- a/pylint.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -TODO="C0111,C0301,C0322,W0311,C0324,W0331,W0212,W0611,W0613,W0201,W0106,W0622,W0403,W0102,W0404,W0704,W0402,W0702,W0401,E0602,E1102,C0321,E0611,E1103,W1001,E0213,W0107,R0921,R0401,E1111,W0101,W0105,W0601,W0602,W0703,W0701,W0312,W0231,W0233,F0401,W0612" - -BROKEN="C0103,E1101" - -DISABLE="W0142,R0913,W0621,R0903,R0201,R0904,W0511,W0232,R0902,W0603,R0914,C0302,C0102,I0011,R0911,R0912,R0901,R0801,R0923,R0915" - -pylint --include-ids=y --disable-msg=$TODO,$BROKEN,$DISABLE shell sugar diff --git a/tests/graphics/common.py b/tests/graphics/common.py deleted file mode 100644 index 2f00099..0000000 --- a/tests/graphics/common.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import gtk - -from sugar.graphics.toolbutton import ToolButton - -class Test(gtk.VBox): - def __init__(self): - gtk.VBox.__init__(self) - -class TestPalette(Test): - def __init__(self): - Test.__init__(self) - - toolbar = gtk.Toolbar() - - self._invoker = ToolButton('go-previous') - toolbar.insert(self._invoker, -1) - self._invoker.show() - - self.pack_start(toolbar, False) - toolbar.show() - - def set_palette(self, palette): - self._invoker.set_palette(palette) - -class TestRunner(object): - def run(self, test): - window = gtk.Window() - window.connect("destroy", lambda w: gtk.main_quit()) - window.add(test) - test.show() - - window.show() - -def main(test): - runner = TestRunner() - runner.run(test) - - gtk.main() diff --git a/tests/graphics/hipposcalability.py b/tests/graphics/hipposcalability.py deleted file mode 100644 index a5cebcc..0000000 --- a/tests/graphics/hipposcalability.py +++ /dev/null @@ -1,50 +0,0 @@ -import hippo -import gtk -import gobject - -from sugar.graphics.icon import CanvasIcon -from sugar.graphics.roundbox import CanvasRoundBox - -import common - -test = common.Test() - -canvas = hippo.Canvas() -test.pack_start(canvas) -canvas.show() - -scrollbars = hippo.CanvasScrollbars() -canvas.set_root(scrollbars) - -box = hippo.CanvasBox(padding=10, spacing=10) -scrollbars.set_root(box) - -def idle_cb(): - global countdown - - for i in range(0, 100): - entry = hippo.CanvasBox(border=2, border_color=0x000000ff, - orientation=hippo.ORIENTATION_HORIZONTAL, - padding=10, spacing=10) - - for j in range(0, 3): - icon = CanvasIcon(icon_name='go-left') - entry.append(icon) - - for j in range(0, 2): - text = hippo.CanvasText(text='Text %s %s' % (countdown, j)) - entry.append(text) - - box.append(entry) - - countdown -= 1 - - return countdown > 0 - -countdown = 1000 -gobject.idle_add(idle_cb) - -test.show() - -if __name__ == "__main__": - common.main(test) diff --git a/tests/graphics/iconcache.py b/tests/graphics/iconcache.py deleted file mode 100644 index b03ecb6..0000000 --- a/tests/graphics/iconcache.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -Test the sugar.graphics.icon.* cache. -""" - -import gtk - -from sugar.graphics.icon import Icon -from sugar.graphics.xocolor import XoColor - -import common - -test = common.Test() - -data = [ - ['battery-000', '#FF8F00,#FF2B34'], - ['battery-010', '#D1A3FF,#00A0FF'], - ['battery-020', '#FF8F00,#FF2B34'], - ['battery-030', '#00A0FF,#D1A3FF'], - ['battery-040', '#AC32FF,#FF2B34'], - ['battery-050', '#D1A3FF,#00A0FF'], - ['battery-060', '#AC32FF,#FF2B34'], - ['battery-070', '#00A0FF,#D1A3FF'], - ['battery-080', '#FF8F00,#FF2B34'], - ['battery-090', '#D1A3FF,#00A0FF'], - ['battery-100', '#AC32FF,#FF2B34']] - -def _button_activated_cb(button): - import random - - global data - random.shuffle(data) - - for i in range(0, len(test.get_children()) - 1): - test.get_children()[i].props.icon_name = data[i][0] - test.get_children()[i].props.xo_color = XoColor(data[i][1]) - -for d in data: - icon = Icon(icon_name=d[0], - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR, - xo_color=XoColor(d[1])) - test.pack_start(icon) - icon.show() - -button = gtk.Button("mec mac") -test.pack_start(button) -button.connect('activate', _button_activated_cb) -button.show() - -test.show() - -if __name__ == "__main__": - common.main(test) diff --git a/tests/graphics/iconwidget.py b/tests/graphics/iconwidget.py deleted file mode 100644 index cacf501..0000000 --- a/tests/graphics/iconwidget.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -Test the sugar.graphics.icon.Icon widget. -""" - -import gtk - -from sugar.graphics.icon import Icon -from sugar.graphics.xocolor import XoColor - -import common - -test = common.Test() - -hbox = gtk.HBox() -test.pack_start(hbox) -sensitive_box = gtk.VBox() -insensitive_box = gtk.VBox() - -hbox.pack_start(sensitive_box) -hbox.pack_start(insensitive_box) -hbox.show_all() - - -def create_icon_widgets(box, sensitive=True): - icon = Icon(icon_name='go-previous') - icon.props.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR - box.pack_start(icon) - icon.set_sensitive(sensitive) - icon.show() - - icon = Icon(icon_name='computer-xo', - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR, - xo_color=XoColor()) - box.pack_start(icon) - icon.set_sensitive(sensitive) - icon.show() - - icon = Icon(icon_name='battery-000', - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR, - badge_name='emblem-busy') - box.pack_start(icon) - icon.set_sensitive(sensitive) - icon.show() - - icon = Icon(icon_name='gtk-new', - icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR, - badge_name='gtk-cancel') - box.pack_start(icon) - icon.set_sensitive(sensitive) - icon.show() - - -create_icon_widgets(sensitive_box, True) -create_icon_widgets(insensitive_box, False) - -test.show() - -# This can be used to test for leaks by setting the LRU cache size -# in icon.py to 1. -#def idle_cb(): -# import gc -# gc.collect() -# test.queue_draw() -# return True -# -#import gobject -#gobject.idle_add(idle_cb) - -if __name__ == "__main__": - common.main(test) diff --git a/tests/graphics/preview.py b/tests/graphics/preview.py deleted file mode 100644 index c1e9ccb..0000000 --- a/tests/graphics/preview.py +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -""" - -import gtk -import gobject - -from sugar import _sugarext - -import common - -def _preview_timeout_cb(): - preview = _sugarext.Preview() - preview.take_screenshot(button.window) - preview.get_pixbuf().save('/home/marco/test.png','png') - preview.clear() - -test = common.Test() - -button = gtk.Button('Hello') -test.pack_start(button) -button.show() - -gobject.timeout_add(2000, _preview_timeout_cb) - -if __name__ == "__main__": - common.main(test) diff --git a/tests/graphics/ticket2855.py b/tests/graphics/ticket2855.py deleted file mode 100644 index cc4b3c0..0000000 --- a/tests/graphics/ticket2855.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -Test the style of toggle and radio buttons inside a palette. The buttons -contains only an icon and should be rendered similarly to the toolbar -controls. Ticket #2855. -""" - -import gtk - -from sugar.graphics.palette import Palette -from sugar.graphics.icon import Icon - -import common - -test = common.TestPalette() - -palette = Palette('Test radio and toggle') -test.set_palette(palette) - -box = gtk.HBox() - -toggle = gtk.ToggleButton() - -icon = Icon(icon_name='go-previous', icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) -toggle.set_image(icon) - -box.pack_start(toggle, False) -toggle.show() - -radio = gtk.RadioButton() - -icon = Icon(icon_name='go-next', icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) -radio.set_image(icon) - -radio.set_mode(False) -box.pack_start(radio, False) -radio.show() - -palette.set_content(box) -box.show() - -if __name__ == "__main__": - common.main(test) diff --git a/tests/graphics/ticket2999.py b/tests/graphics/ticket2999.py deleted file mode 100644 index a7b92d5..0000000 --- a/tests/graphics/ticket2999.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -Spec in ticket #2999. -""" - -import gtk - -from sugar.graphics.palette import Palette -from sugar.graphics.icon import Icon - -import common - -test = common.Test() -test.set_border_width(60) - -text_view = gtk.TextView() -text_view.props.buffer.props.text = 'Blah blah blah, blah blah blah.' -test.pack_start(text_view) -text_view.show() - -if __name__ == "__main__": - common.main(test) diff --git a/tests/graphics/ticket3000.py b/tests/graphics/ticket3000.py deleted file mode 100644 index c28b2cb..0000000 --- a/tests/graphics/ticket3000.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2007, One Laptop Per Child -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -Spec in ticket #3000. -""" - -import gtk - -from sugar.graphics.toolbutton import ToolButton - -import common - -test = common.Test() - -toolbar = gtk.Toolbar() -test.pack_start(toolbar, False) -toolbar.show() - -button = ToolButton('go-previous') -toolbar.insert(button, -1) -button.show() - -separator = gtk.SeparatorToolItem() -toolbar.add(separator) -separator.show() - -button = ToolButton('go-next') -toolbar.insert(button, -1) -button.show() - - -if __name__ == "__main__": - common.main(test) diff --git a/tests/graphics/toolbarpalettes.py b/tests/graphics/toolbarpalettes.py deleted file mode 100644 index 608ef57..0000000 --- a/tests/graphics/toolbarpalettes.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -Test palette positioning for toolbar and tray. -""" - -import gtk - -from sugar.graphics.tray import HTray, TrayButton -from sugar.graphics.toolbutton import ToolButton - -import common - -test = common.Test() - -vbox = gtk.VBox() - -theme_icons = gtk.icon_theme_get_default().list_icons() - -toolbar = gtk.Toolbar() -vbox.pack_start(toolbar, False) -toolbar.show() - -for i in range(0, 5): - button = ToolButton(icon_name=theme_icons[i]) - button.set_tooltip('Icon %d' % i) - toolbar.insert(button, -1) - button.show() - -content = gtk.Label() -vbox.pack_start(content) -content.show() - -tray = HTray() -vbox.pack_start(tray, False) -tray.show() - -for i in range(0, 30): - button = TrayButton(icon_name=theme_icons[i]) - button.set_tooltip('Icon %d' % i) - tray.add_item(button) - button.show() - -test.pack_start(vbox) -vbox.show() - -test.show() - -if __name__ == "__main__": - common.main(test) diff --git a/tests/graphics/tray.py b/tests/graphics/tray.py deleted file mode 100644 index f589f4e..0000000 --- a/tests/graphics/tray.py +++ /dev/null @@ -1,82 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -""" -Test the sugar.graphics.icon.Icon widget. -""" - -import gtk - -from sugar.graphics.tray import HTray, VTray -from sugar.graphics.tray import TrayButton, TrayIcon - -import common - -test = common.Test() - -vbox = gtk.VBox() - -tray = HTray() -vbox.pack_start(tray, False) -tray.show() - -theme_icons = gtk.icon_theme_get_default().list_icons() - -for i in range(0, 100): - button = TrayButton(icon_name=theme_icons[i]) - tray.add_item(button) - button.show() - -tray = HTray() -vbox.pack_start(tray, False) -tray.show() - -for i in range(0, 10): - icon = TrayIcon(icon_name=theme_icons[i]) - tray.add_item(icon) - icon.show() - -hbox = gtk.HBox() - -tray = VTray() -hbox.pack_start(tray, False) -tray.show() - -for i in range(0, 100): - button = TrayButton(icon_name=theme_icons[i]) - tray.add_item(button) - button.show() - -tray = VTray() -hbox.pack_start(tray, False) -tray.show() - -for i in range(0, 4): - button = TrayButton(icon_name=theme_icons[i]) - tray.add_item(button) - button.show() - -vbox.pack_start(hbox) -hbox.show() - -test.pack_start(vbox) -vbox.show() - -test.show() - -if __name__ == "__main__": - common.main(test) diff --git a/tests/lib/runall.py b/tests/lib/runall.py deleted file mode 100644 index ae1bb3a..0000000 --- a/tests/lib/runall.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2007, Red Hat, Inc. -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -import unittest - -import test_mime - -runner = unittest.TextTestRunner() -loader = unittest.TestLoader() - -suite = unittest.TestSuite() -suite.addTest(loader.loadTestsFromModule(test_mime)) - -runner.run(suite) diff --git a/tests/lib/test_mime.py b/tests/lib/test_mime.py deleted file mode 100644 index 3df0ce6..0000000 --- a/tests/lib/test_mime.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2006, Red Hat, Inc. -# Copyright (C) 2007, One Laptop Per Child -# -# 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 sys -import unittest - -from sugar import mime - -class TestMime(unittest.TestCase): - def test_from_file_name(self): - self.assertEqual(mime.get_from_file_name('test.pdf'), - 'application/pdf') - - def test_choose_most_significant(self): - # Mozilla's text in dnd - mime_type = mime.choose_most_significant( - ['text/plain', 'text/_moz_htmlcontext', 'text/unicode', - 'text/html', 'text/_moz_htmlinfo']) - self.assertEqual(mime_type, 'text/html') - - # Mozilla's text in c&v - mime_type = mime.choose_most_significant( - ['text/_moz_htmlcontext', 'STRING', 'text/html', 'text/_moz_htmlinfo', - 'text/x-moz-url-priv', 'UTF8_STRING', 'COMPOUND_TEXT']) - self.assertEqual(mime_type, 'text/html') - - # Mozilla gif in dnd - mime_type = mime.choose_most_significant( - ['application/x-moz-file-promise-url', - 'application/x-moz-file-promise-dest-filename', 'text/_moz_htmlinfo', - 'text/x-moz-url-desc', 'text/_moz_htmlcontext', 'text/x-moz-url-data', - 'text/uri-list']) - self.assertEqual(mime_type, 'text/uri-list') - - # Mozilla url in dnd - mime_type = mime.choose_most_significant( - ['text/_moz_htmlcontext', 'text/html', 'text/_moz_htmlinfo', - '_NETSCAPE_URL', 'text/x-moz-url', 'text/x-moz-url-desc', - 'text/x-moz-url-data', 'text/plain', 'text/unicode']) - self.assertEqual(mime_type, 'text/x-moz-url') - - # Abiword text in dnd - mime_type = mime.choose_most_significant( - ['text/rtf', 'text/uri-list']) - self.assertEqual(mime_type, 'text/uri-list') - - # Abiword text in c&v - mime_type = mime.choose_most_significant( - ['UTF8_STRING', 'STRING', 'text/html', 'TEXT', 'text/rtf', - 'COMPOUND_TEXT', 'application/rtf', 'text/plain', - 'application/xhtml+xml']) - self.assertEqual(mime_type, 'application/rtf') - - # Abiword text in c&v - mime_type = mime.choose_most_significant( - ['GTK_TEXT_BUFFER_CONTENTS', - 'application/x-gtk-text-buffer-rich-text', - 'UTF8_STRING', 'COMPOUND_TEXT', 'TEXT', 'STRING', - 'text/plain;charset=utf-8', 'text/plain;charset=UTF-8', - 'text/plain']) - self.assertEqual(mime_type, 'text/plain') - -if __name__ == "__main__": - unittest.main() - -- cgit v0.9.1