From: epage Date: Thu, 2 Oct 2008 23:46:15 +0000 (+0000) Subject: Clearing out the old version to bring in the new X-Git-Url: http://git.maemo.org/git/?p=gc-dialer;a=commitdiff_plain;h=7e080345fe90941ba88d50eba32ff78c77896ba0;hp=f9bc208c0e4842fa2b2ffab791ed670f11a4e92b Clearing out the old version to bring in the new git-svn-id: file:///svnroot/gc-dialer/trunk@157 c39d3808-3fe2-4d86-a59f-b7f623ee9f21 --- diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 5ab7695..0000000 --- a/LICENSE +++ /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 b/Makefile deleted file mode 100644 index 9933c6a..0000000 --- a/Makefile +++ /dev/null @@ -1,148 +0,0 @@ -PROJECT_NAME=gc_dialer -PROJECT_VERSION=0.8.0 -SOURCE_PATH=src -SOURCE=$(SOURCE_PATH)/gc_dialer.py $(SOURCE_PATH)/evo_backend.py $(SOURCE_PATH)/gc_backend.py $(SOURCE_PATH)/browser_emu.py -OBJ=$(SOURCE:.py=.pyc) -LINT_STATS_PATH=~/.pylint.d -LINT_STATS=$(foreach file, $(addsuffix 1.stats,$(subst /,.,$(basename $(SOURCE)))), $(LINT_STATS_PATH)/$(file) ) -TEST_PATH=./tests -TAG_FILE=~/.ctags/$(PROJECT_NAME).tags -PYPACKAGE_FILE=./support/GrandcentralDialer.pypackager -DEB_METADATA=./support/DEBIAN -SDK_DISPLAY=:2 - -PY_FAST_LAUNCH=1 -PLATFORM=desktop -ifeq ($(PLATFORM),os2007) - LEGACY_GLADE=1 -else - LEGACY_GLADE=0 -endif -PRE_PACKAGE_PATH=./pkg-$(PLATFORM) -PACKAGE_PATH=./deb-$(PLATFORM) -BUILD_PATH=./build-$(PLATFORM) -BUILD_BIN=$(BUILD_PATH)/gc_dialer.py -DEB_PACKAGE=$(PACKAGE_PATH)/$(PROJECT_NAME)-$(PROJECT_VERSION)_$(PLATFORM).deb - -DEBUGGER=winpdb -UNIT_TEST=nosetests -w $(TEST_PATH) -STYLE_TEST=../../Python/tools/pep8.py --ignore=W191 -LINT_RC=./support/pylint.rc -LINT=pylint --rcfile=$(LINT_RC) -COVERAGE_TEST=figleaf -PROFILER=pyprofiler -CTAGS=ctags-exuberant - -.PHONY: all run debug test lint tags build package clean - -all: test package - -run: $(SOURCE) - cd $(SOURCE_PATH) ; ./gc_dialer.py - -debug: $(SOURCE) - cd $(SOURCE_PATH) ; $(DEBUGGER) ./gc_dialer.py - -test: $(SOURCE) - cd $(SOURCE_PATH) ; ./gc_dialer.py -t - -xephyr: - Xephyr $(SDK_DISPLAY) -host-cursor -screen 800x480x16 -dpi 96 -ac - -sdk_start: - export DISPLAY=$(SDK_DISPLAY) - af-sb-ini.sh start - -sdk_stop: - af-sb-ini.sh stop - -lint: $(LINT_STATS) - -tags: $(TAG_FILE) - -build: $(BUILD_PATH) - -package: $(DEB_PACKAGE) - -$(BUILD_PATH): $(BUILD_BIN) - mkdir -p $(BUILD_PATH) - - cp $(SOURCE_PATH)/gc_dialer_256.png $(BUILD_PATH) - cp $(SOURCE_PATH)/gc_dialer_64.png $(BUILD_PATH) - cp $(SOURCE_PATH)/gc_dialer_26.png $(BUILD_PATH) - - cp $(SOURCE_PATH)/gc_dialer.desktop $(BUILD_PATH) - - cp $(SOURCE_PATH)/gc_dialer.glade $(BUILD_PATH) -ifneq ($(PLATFORM),desktop) - sed -i 's/^[ \t]*//;s/GtkWindow/HildonWindow/' $(BUILD_PATH)/gc_dialer.glade -endif - -$(PRE_PACKAGE_PATH): $(BUILD_PATH) - mkdir -p $(PRE_PACKAGE_PATH)/build/usr/share/icons/hicolor/scalable/hildon - mkdir -p $(PRE_PACKAGE_PATH)/build/usr/share/icons/hicolor/26x26/hildon - mkdir -p $(PRE_PACKAGE_PATH)/build/usr/share/icons/hicolor/64x64/hildon - mkdir -p $(PRE_PACKAGE_PATH)/build/usr/share/applications/hildon - mkdir -p $(PRE_PACKAGE_PATH)/build/usr/local/lib - mkdir -p $(PRE_PACKAGE_PATH)/build/usr/local/bin - - cp $(BUILD_PATH)/gc_dialer_256.png $(PRE_PACKAGE_PATH)/build/usr/share/icons/hicolor/scalable/hildon/gc_dialer.png - cp $(BUILD_PATH)/gc_dialer_64.png $(PRE_PACKAGE_PATH)/build/usr/share/icons/hicolor/64x64/hildon/gc_dialer.png - cp $(BUILD_PATH)/gc_dialer_26.png $(PRE_PACKAGE_PATH)/build/usr/share/icons/hicolor/26x26/hildon/gc_dialer.png - - cp $(BUILD_PATH)/gc_dialer.desktop $(PRE_PACKAGE_PATH)/build/usr/share/applications/hildon - - cp $(BUILD_PATH)/gc_dialer.glade $(PRE_PACKAGE_PATH)/build/usr/local/lib - - cp $(BUILD_BIN) $(PRE_PACKAGE_PATH)/build/usr/local/bin - - cp $(PYPACKAGE_FILE) $(PRE_PACKAGE_PATH) - cp -R $(DEB_METADATA) $(PRE_PACKAGE_PATH)/build/ -ifeq ($(PLATFORM),desktop) - #sed -i 's/, python2.5-hildon//' $(PRE_PACKAGE_PATH)/build/DEBIAN/control -endif - sed -i 's/Version: 0.0.0/Version: $(PROJECT_VERSION)/' $(PRE_PACKAGE_PATH)/build/DEBIAN/control - #Autoguess install size - #du -hs pkg-desktop/build/ | sed 's/K *.*//' - sed -i 's/Installed-Size: 0/Installed-Size: 196/' $(PRE_PACKAGE_PATH)/build/DEBIAN/control - cp LICENSE $(PRE_PACKAGE_PATH)/build/DEBIAN/copyright - -$(DEB_PACKAGE): $(PRE_PACKAGE_PATH) - mkdir -p $(PACKAGE_PATH) - dpkg-deb -b $(PRE_PACKAGE_PATH)/build/ $(DEB_PACKAGE) - -clean: - rm -Rf $(PRE_PACKAGE_PATH) $(PACKAGE_PATH) $(BUILD_PATH) - rm -Rf $(DEB_PACKAGE) - rm -Rf $(OBJ) - rm -Rf $(LINT_STATS_PATH)/* - -$(BUILD_BIN): $(SOURCE) - mkdir -p $(dir $(BUILD_BIN)) - - #Construct the program by cat-ing all the python files together -ifeq ($(PY_FAST_LAUNCH),1) - echo "#!/usr/bin/python" > $(BUILD_BIN) -else - echo "#!/usr/bin/python2.5" > $(BUILD_BIN) -endif - #echo "from __future__ import with_statement" >> $(PRE_PACKAGE_PATH)/usr/local/bin/gc_dialer.py - cat $(SOURCE_PATH)/gc_dialer.py $(SOURCE_PATH)/evo_backend.py $(SOURCE_PATH)/gc_backend.py $(SOURCE_PATH)/browser_emu.py | grep -e '^import ' | sort -u >> $(BUILD_BIN) - cat $(SOURCE_PATH)/browser_emu.py $(SOURCE_PATH)/evo_backend.py $(SOURCE_PATH)/gc_backend.py $(SOURCE_PATH)/gc_dialer.py | grep -v 'browser_emu' | grep -v 'gc_backend' | grep -v "evo_backend"| grep -v "#!" >> $(BUILD_BIN) - chmod 755 $(BUILD_BIN) - -$(TAG_FILE): $(SOURCE) - mkdir -p $(dir $(TAG_FILE)) - $(CTAGS) -o $(TAG_FILE) $(SOURCE) - -%1.stats: $(SOURCE) $(LINT_RC) - @ #DESIRED DEPENDENCY: $(subst .,/,$(notdir $*)).py - @ #DESIRED COMMAND: $(LINT) $< - @ $(LINT) $(subst .,/,$(notdir $*)).py - @# echo $* - @# echo $? - -#Makefile Debugging -#Target to print any variable, can be added to the dependencies of any other target -#Userfule flags for make, -d, -p, -n -print-%: ; @$(error $* is $($*) ($(value $*)) (from $(origin $*))) diff --git a/README b/README deleted file mode 100644 index b87ce9c..0000000 --- a/README +++ /dev/null @@ -1,37 +0,0 @@ -Building a package -=================== -Run - make PLATFORM=... package -which will create a "./pkg-.../..." heirarchy. Move this structure to somewhere on the tablet, then run pypackager. - -Supported PLATFORMs include - desktop - os2007 - os2008 - -SDK Enviroment -=================== - -Native - -Follow install instructions - Ubuntu: http://www.linuxuk.org/node/38 -Install Nokia stuff (for each target) - fakeroot apt-get install maemo-explicit - -Userful commands -Login - /scratchbox/login -Change targets - sb-conf select DIABLO_ARMEL - sb-conf select DIABLO_X86 -Fixing it - fakeroot apt-get -f install - -Starting scratchbox - Xephyr :2 -host-cursor -screen 800x480x16 -dpi 96 -ac -extension Composite - scratchbox - export DISPLAY=:2 - af-sb-init.sh start -Then running a command in the "Maemo" terminal will launch it in the Xephyr session - Tip: run with "run-standalone.sh" for niceness? diff --git a/TODO b/TODO deleted file mode 100644 index 711515c..0000000 --- a/TODO +++ /dev/null @@ -1,30 +0,0 @@ -Ideas -================= -User Contacts - It seems the evolution contact API used is specific to the desktop. evolution.ebook combined with abook is what is needed for Maemo. - http://maemo.org/maemo_release_documentation/maemo4.1.x/node8.html#SECTION00870000000000000000 - https://garage.maemo.org/svn/pymaemo/packages/python-abook/trunk/tests/ especially contact_get_iter amd filter_model - http://pymaemo.garage.maemo.org/documentation/api/abook/index.html - - Other possible addressbooks - GMail http://libgmail.sourceforge.net/ - GPE - -Internet Connection - Look into being a bit more advanced, beyond just enabling/disabling the GUI - Possible Approach: - Defer login - While not logged in or device is offline, disable the GUI - Don't attempt to login if not online - -Keep callbacks to a minimum amount of blocking I/O - -Re-examine all use of add_idle - I dont think its a thread but idle processing in mainloop, so it could block for long execution - -Notes -================= -General Python/Maemo stuff - http://pymaemo.garage.maemo.org/documentation.html -DBus - http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/browser_emu.py b/src/browser_emu.py deleted file mode 100644 index 3083a1c..0000000 --- a/src/browser_emu.py +++ /dev/null @@ -1,152 +0,0 @@ -""" -@author: Laszlo Nagy -@copyright: (c) 2005 by Szoftver Messias Bt. -@licence: BSD style - -Objects of the MozillaEmulator class can emulate a browser that is capable of: - - - cookie management - - caching - - configurable user agent string - - GET and POST - - multipart POST (send files) - - receive content into file - - progress indicator - -I have seen many requests on the python mailing list about how to emulate a browser. I'm using this class for years now, without any problems. This is how you can use it: - - 1. Use firefox - 2. Install and open the livehttpheaders plugin - 3. Use the website manually with firefox - 4. Check the GET and POST requests in the livehttpheaders capture window - 5. Create an instance of the above class and send the same GET and POST requests to the server. - -Optional steps: - - - For testing, use a MozillaCacher instance - this will cache all pages and make testing quicker - - You can change user agent string in the build_opened method - - The "encode_multipart_formdata" function can be used alone to create POST data from a list of field values and files -""" - -import urllib2 -import cookielib -import warnings - - -class MozillaEmulator(object): - - def __init__(self, cacher=None, trycount=0): - """Create a new MozillaEmulator object. - - @param cacher: A dictionary like object, that can cache search results on a storage device. - You can use a simple dictionary here, but it is not recommended. - You can also put None here to disable caching completely. - @param trycount: The download() method will retry the operation if it fails. You can specify -1 for infinite retrying. - A value of 0 means no retrying. A value of 1 means one retry. etc.""" - if cacher is None: - cacher = {} - self.cacher = cacher - self.cookies = cookielib.LWPCookieJar() - self.debug = False - self.trycount = trycount - - def build_opener(self, url, postdata=None, extraheaders=None, forbid_redirect=False): - if extraheaders is None: - extraheaders = {} - - txheaders = { - 'Accept': 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png', - 'Accept-Language': 'en,en-us;q=0.5', - 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', - } - for key, value in extraheaders.iteritems(): - txheaders[key] = value - req = urllib2.Request(url, postdata, txheaders) - self.cookies.add_cookie_header(req) - if forbid_redirect: - redirector = HTTPNoRedirector() - else: - redirector = urllib2.HTTPRedirectHandler() - - http_handler = urllib2.HTTPHandler(debuglevel=self.debug) - https_handler = urllib2.HTTPSHandler(debuglevel=self.debug) - - u = urllib2.build_opener( - http_handler, - https_handler, - urllib2.HTTPCookieProcessor(self.cookies), - redirector - ) - u.addheaders = [( - 'User-Agent', - 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.8) Gecko/20050511 Firefox/1.0.4' - )] - if not postdata is None: - req.add_data(postdata) - return (req, u) - - def download(self, url, postdata=None, extraheaders=None, forbid_redirect=False, - trycount=None, fd=None, onprogress=None, only_head=False): - """Download an URL with GET or POST methods. - - @param postdata: It can be a string that will be POST-ed to the URL. - When None is given, the method will be GET instead. - @param extraheaders: You can add/modify HTTP headers with a dict here. - @param forbid_redirect: Set this flag if you do not want to handle - HTTP 301 and 302 redirects. - @param trycount: Specify the maximum number of retries here. - 0 means no retry on error. Using -1 means infinite retring. - None means the default value (that is self.trycount). - @param fd: You can pass a file descriptor here. In this case, - the data will be written into the file. Please note that - when you save the raw data into a file then it won't be cached. - @param onprogress: A function that has two parameters: - the size of the resource and the downloaded size. This will be - called for each 1KB chunk. (If the HTTP header does not contain - the content-length field, then the size parameter will be zero!) - @param only_head: Create the openerdirector and return it. In other - words, this will not retrieve any content except HTTP headers. - - @return: The raw HTML page data, unless fd was specified. When fd - was given, the return value is undefined. - """ - warnings.warn("Performing download of %s" % url, UserWarning, 2) - - if extraheaders is None: - extraheaders = {} - if trycount is None: - trycount = self.trycount - cnt = 0 - while True: - try: - req, u = self.build_opener(url, postdata, extraheaders, forbid_redirect) - openerdirector = u.open(req) - if self.debug: - print req.get_method(), url - print openerdirector.code, openerdirector.msg - print openerdirector.headers - self.cookies.extract_cookies(openerdirector, req) - if only_head: - return openerdirector - return openerdirector.read() - except urllib2.URLError: - cnt += 1 - if (trycount > -1) and (trycount < cnt): - raise - # Retry :-) - if self.debug: - print "MozillaEmulator: urllib2.URLError, retryting ", cnt - - -class HTTPNoRedirector(urllib2.HTTPRedirectHandler): - """This is a custom http redirect handler that FORBIDS redirection.""" - - def http_error_302(self, req, fp, code, msg, headers): - e = urllib2.HTTPError(req.get_full_url(), code, msg, headers, fp) - if e.code in (301, 302): - if 'location' in headers: - newurl = headers.getheaders('location')[0] - elif 'uri' in headers: - newurl = headers.getheaders('uri')[0] - e.newurl = newurl - raise e diff --git a/src/evo_backend.py b/src/evo_backend.py deleted file mode 100644 index c094c2e..0000000 --- a/src/evo_backend.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/python - -# GC Dialer - Front end for Google's Grand Central service. -# Copyright (C) 2008 Eric Warnke ericew AT gmail DOT 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.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 - - -""" -Evolution Contact Support -""" - - -try: - import evolution -except ImportError: - evolution = None - - -class EvolutionAddressBook(object): - """ - @note Combined the factory and the addressbook for "simplicity" and "cutting down" the number of allocations/deallocations - """ - - def __init__(self, bookId = None): - if not self.is_supported(): - return - - self._phoneTypes = None - self._bookId = bookId if bookId is not None else self.get_addressbooks().next()[1] - self._book = evolution.ebook.open_addressbook(self._bookId) - - @classmethod - def is_supported(cls): - return evolution is not None - - def get_addressbooks(self): - """ - @returns Iterable of (Address Book Factory, Book Id, Book Name) - """ - if not self.is_supported(): - return - - if len(evolution.ebook.list_addressbooks()) == 0 and evolution.ebook.open_addressbook('default') is not None: - # It appears that Maemo's e-d-s does not always list the default addressbook, so we're faking it being listed - yield self, "default", "Maemo" - - for bookId in evolution.ebook.list_addressbooks(): - yield self, bookId[1], bookId[0] - - def open_addressbook(self, bookId): - self._bookId = bookId - self._book = evolution.ebook.open_addressbook(self._bookId) - return self - - @staticmethod - def factory_short_name(): - return "Evo" - - @staticmethod - def factory_name(): - return "Evolution" - - def get_contacts(self): - """ - @returns Iterable of (contact id, contact name) - """ - if not self.is_supported(): - return - - for contact in self._book.get_all_contacts(): - yield contact.get_uid(), contact.props.full_name - - def get_contact_details(self, contactId): - """ - @returns Iterable of (Phone Type, Phone Number) - """ - contact = self._book.get_contact(contactId) - - if self._phoneTypes is None and contact is not None: - self._phoneTypes = [pt for pt in dir(contact.props) if "phone" in pt.lower()] - - for phoneType in self._phoneTypes: - phoneNumber = getattr(contact.props, phoneType) - if isinstance(phoneNumber, str): - yield phoneType, phoneNumber - -def print_addressbooks(): - """ - Included here for debugging. - - Either insert it into the code or launch python with the "-i" flag - """ - if not EvolutionAddressBook.is_supported(): - print "No Evolution Support" - return - - eab = EvolutionAddressBook() - for book in eab.get_addressbooks(): - eab = eab.open_addressbook(book[1]) - print book - for contact in eab.get_contacts(): - print "\t", contact - for details in eab.get_contact_details(contact[0]): - print "\t\t", details diff --git a/src/gc_backend.py b/src/gc_backend.py deleted file mode 100644 index d1641de..0000000 --- a/src/gc_backend.py +++ /dev/null @@ -1,315 +0,0 @@ -#!/usr/bin/python - -# GC Dialer - Front end for Google's Grand Central service. -# Copyright (C) 2008 Eric Warnke ericew AT gmail DOT 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.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 - -""" -Grandcentral Dialer backend code -""" - - -import os -import re -import urllib -import urllib2 -import time -import warnings - -from browser_emu import MozillaEmulator - - -class GCDialer(object): - """ - This class encapsulates all of the knowledge necessary to interace with the grandcentral servers - the functions include login, setting up a callback number, and initalting a callback - """ - - _gcDialingStrRe = re.compile("This may take a few seconds", re.M) - _accessTokenRe = re.compile(r"""]*value="(.*)"/>""") - _isLoginPageRe = re.compile(r"""
""") - _callbackRe = re.compile(r"""name="default_number" value="(\d+)" />\s+(.*)\s$""", re.M) - _accountNumRe = re.compile(r"""GrandCentral\s*(.{14})\s* """, re.M) - _inboxRe = re.compile(r""".*?(voicemail|received|missed|call return).*?\s+\s+\s+(.*?)\s+ \| \s+(.*?)\s?\s+
\s+(.*?)\s?(.*?)""", re.S) - _contactsNextRe = re.compile(r""".*Next""", re.S) - _contactDetailGroupRe = re.compile(r"""Group:\s*(\w*)""", re.S) - _contactDetailPhoneRe = re.compile(r"""(\w+):[0-9\-\(\) \t]*?call""", re.S) - - _validateRe = re.compile("^[0-9]{10,}$") - - _forwardselectURL = "http://www.grandcentral.com/mobile/settings/forwarding_select" - _loginURL = "https://www.grandcentral.com/mobile/account/login" - _setforwardURL = "http://www.grandcentral.com/mobile/settings/set_forwarding?from=settings" - _clicktocallURL = "http://www.grandcentral.com/mobile/calls/click_to_call?a_t=%s&destno=%s" - _inboxallURL = "http://www.grandcentral.com/mobile/messages/inbox?types=all" - _contactsURL = "http://www.grandcentral.com/mobile/contacts" - _contactDetailURL = "http://www.grandcentral.com/mobile/contacts/detail" - - def __init__(self, cookieFile = None): - # Important items in this function are the setup of the browser emulation and cookie file - self._msg = "" - - self._browser = MozillaEmulator(None, 0) - if cookieFile is None: - cookieFile = os.path.join(os.path.expanduser("~"), ".gc_dialer_cookies.txt") - self._browser.cookies.filename = cookieFile - if os.path.isfile(cookieFile): - self._browser.cookies.load() - - self._accessToken = None - self._accountNum = None - self._callbackNumbers = {} - self._lastAuthed = 0.0 - - def is_authed(self, force = False): - """ - Attempts to detect a current session and pull the auth token ( a_t ) from the page. - @note Once logged in try not to reauth more than once a minute. - @returns If authenticated - """ - - if (time.time() - self._lastAuthed) < 60 and not force: - return True - - try: - forwardSelectionPage = self._browser.download(GCDialer._forwardselectURL) - except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._forwardselectURL, UserWarning, 2) - return False - - self._browser.cookies.save() - if GCDialer._isLoginPageRe.search(forwardSelectionPage) is None: - self._grab_token(forwardSelectionPage) - self._lastAuthed = time.time() - return True - - return False - - def login(self, username, password): - """ - Attempt to login to grandcentral - @returns Whether login was successful or not - """ - if self.is_authed(): - return True - - loginPostData = urllib.urlencode( {'username' : username , 'password' : password } ) - - try: - loginSuccessOrFailurePage = self._browser.download(GCDialer._loginURL, loginPostData) - except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._loginURL, UserWarning, 2) - return False - - return self.is_authed() - - def logout(self): - self._lastAuthed = 0.0 - self._browser.cookies.clear() - self._browser.cookies.save() - - def dial(self, number): - """ - This is the main function responsible for initating the callback - """ - self._msg = "" - - # If the number is not valid throw exception - if not self.is_valid_syntax(number): - raise ValueError('number is not valid') - - # No point if we don't have the magic cookie - if not self.is_authed(): - self._msg = "Not authenticated" - return False - - # Strip leading 1 from 11 digit dialing - if len(number) == 11 and number[0] == 1: - number = number[1:] - - try: - callSuccessPage = self._browser.download( - GCDialer._clicktocallURL % (self._accessToken, number), - None, - {'Referer' : 'http://www.grandcentral.com/mobile/messages'} - ) - except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._clicktocallURL, UserWarning, 2) - return False - - if GCDialer._gcDialingStrRe.search(callSuccessPage) is not None: - return True - else: - self._msg = "Grand Central returned an error" - return False - - self._msg = "Unknown Error" - return False - - def clear_caches(self): - pass - - def is_valid_syntax(self, number): - """ - @returns If This number be called ( syntax validation only ) - """ - return self._validateRe.match(number) is not None - - def get_account_number(self): - """ - @returns The grand central phone number - """ - return self._accountNum - - def set_sane_callback(self): - """ - Try to set a sane default callback number on these preferences - 1) 1747 numbers ( Gizmo ) - 2) anything with gizmo in the name - 3) anything with computer in the name - 4) the first value - """ - numbers = self.get_callback_numbers() - - for number, description in numbers.iteritems(): - if not re.compile(r"""1747""").match(number) is None: - self.set_callback_number(number) - return - - for number, description in numbers.iteritems(): - if not re.compile(r"""gizmo""", re.I).search(description) is None: - self.set_callback_number(number) - return - - for number, description in numbers.iteritems(): - if not re.compile(r"""computer""", re.I).search(description) is None: - self.set_callback_number(number) - return - - for number, description in numbers.iteritems(): - self.set_callback_number(number) - return - - def get_callback_numbers(self): - """ - @returns a dictionary mapping call back numbers to descriptions - @note These results are cached for 30 minutes. - """ - if time.time() - self._lastAuthed < 1800 or self.is_authed(): - return self._callbackNumbers - - return {} - - def set_callback_number(self, callbacknumber): - """ - Set the number that grandcental calls - @param callbacknumber should be a proper 10 digit number - """ - callbackPostData = urllib.urlencode({ - 'a_t': self._accessToken, - 'default_number': callbacknumber - }) - try: - callbackSetPage = self._browser.download(GCDialer._setforwardURL, callbackPostData) - except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._setforwardURL, UserWarning, 2) - return False - - self._browser.cookies.save() - return True - - def get_callback_number(self): - """ - @returns Current callback number or None - """ - for c in self._browser.cookies: - if c.name == "pda_forwarding_number": - return c.value - return None - - def get_recent(self): - """ - @returns Iterable of (personsName, phoneNumber, date, action) - """ - try: - recentCallsPage = self._browser.download(GCDialer._inboxallURL) - except urllib2.URLError, e: - warnings.warn("%s is not accesible" % GCDialer._inboxallURL, UserWarning, 2) - return - - for match in self._inboxRe.finditer(recentCallsPage): - phoneNumber = match.group(4) - action = match.group(1) - date = match.group(2) - personsName = match.group(3) - yield personsName, phoneNumber, date, action - - def get_addressbooks(self): - """ - @returns Iterable of (Address Book Factory, Book Id, Book Name) - """ - yield self, "", "" - - def open_addressbook(self, bookId): - return self - - @staticmethod - def factory_short_name(): - return "GC" - - @staticmethod - def factory_name(): - return "Grand Central" - - def get_contacts(self): - """ - @returns Iterable of (contact id, contact name) - """ - contactsPagesUrls = [GCDialer._contactsURL] - for contactsPageUrl in contactsPagesUrls: - contactsPage = self._browser.download(contactsPageUrl) - for contact_match in self._contactsRe.finditer(contactsPage): - contactId = contact_match.group(1) - contactName = contact_match.group(2) - yield contactId, contactName - - next_match = self._contactsNextRe.match(contactsPage) - if next_match is not None: - newContactsPageUrl = self._contactsURL + next_match.group(1) - contactsPagesUrls.append(newContactsPageUrl) - - def get_contact_details(self, contactId): - """ - @returns Iterable of (Phone Type, Phone Number) - """ - detailPage = self._browser.download(GCDialer._contactDetailURL + '/' + contactId) - for detail_match in self._contactDetailPhoneRe.finditer(detailPage): - phoneType = detail_match.group(1) - phoneNumber = detail_match.group(2) - yield (phoneType, phoneNumber) - - def _grab_token(self, data): - "Pull the magic cookie from the datastream" - atGroup = GCDialer._accessTokenRe.search(data) - self._accessToken = atGroup.group(1) - - anGroup = GCDialer._accountNumRe.search(data) - self._accountNum = anGroup.group(1) - - self._callbackNumbers = {} - for match in GCDialer._callbackRe.finditer(data): - self._callbackNumbers[match.group(1)] = match.group(2) diff --git a/src/gc_dialer.desktop b/src/gc_dialer.desktop deleted file mode 100644 index f3ebe19..0000000 --- a/src/gc_dialer.desktop +++ /dev/null @@ -1,7 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Version=1.0 -Type=Application -Name=Grandcentral Dialer -Exec=run-standalone.sh /usr/local/bin/gc_dialer.py -Icon=gc_dialer diff --git a/src/gc_dialer.glade b/src/gc_dialer.glade deleted file mode 100644 index f406750..0000000 --- a/src/gc_dialer.glade +++ /dev/null @@ -1,893 +0,0 @@ - - - - - - 400 - 350 - Dialer - - - True - - - True - - - True - _File - True - - - True - - - True - _New Login - True - - - - gtk-new - - - - - - - True - - - - - True - gtk-quit - True - True - - - - - - - - - - True - _Edit - True - - - True - - - True - gtk-paste - True - True - - - - - - True - gtk-delete - True - True - - - - - - - - - - False - - - - - True - True - GTK_POS_BOTTOM - False - True - - - - True - - - 50 - True - <span size="35000" weight="bold">(518) 555-1212</span> - True - GTK_JUSTIFY_CENTER - - - False - False - - - - - True - 4 - 3 - True - - - True - False - 0 - - - - - True - - - True - 1 - gtk-yes - - - - - True - 0 - 5 - <span size="17000" weight="bold">Dial</span> - True - - - 1 - - - - - - - 2 - 3 - 3 - 4 - - - - - True - False - 0 - - - - - True - <span size="33000" weight="bold">0</span> -<span size="9000"></span> - True - GTK_JUSTIFY_CENTER - - - - - 1 - 2 - 3 - 4 - - - - - True - False - 0 - - - - - True - - - True - 1 - gtk-no - - - - - True - 0 - 5 - <span size="17000" weight="Bold">Back</span> - True - - - 1 - - - - - - - 3 - 4 - - - - - True - False - 0 - - - - - - - - - True - <span size="30000" weight="bold">9</span> -<span size="12000">WXYZ</span> - True - GTK_JUSTIFY_CENTER - - - - - 2 - 3 - 2 - 3 - - - - - True - False - 0 - - - - - - - - True - <span size="30000" weight="bold">8</span> -<span size="12000">TUV</span> - True - GTK_JUSTIFY_CENTER - - - - - 1 - 2 - 2 - 3 - - - - - True - False - 0 - - - - - - - - - True - <span size="30000" weight="bold">7</span> -<span size="12000">PQRS</span> - True - GTK_JUSTIFY_CENTER - - - - - 2 - 3 - - - - - True - False - 0 - - - - - - - - True - <span size="30000" weight="bold">6</span> -<span size="12000">MNO</span> - True - GTK_JUSTIFY_CENTER - - - - - 2 - 3 - 1 - 2 - - - - - True - False - 0 - - - - - - - - True - <span size="30000" weight="bold">5</span> -<span size="12000">JKL</span> - True - GTK_JUSTIFY_CENTER - - - - - 1 - 2 - 1 - 2 - - - - - True - False - 0 - - - - - - - - True - <span size="30000" weight="bold">4</span> -<span size="12000">GHI</span> - True - GTK_JUSTIFY_CENTER - - - - - 1 - 2 - - - - - True - False - 0 - - - - - - - - True - <span size="30000" weight="bold" stretch="ultraexpanded">3</span> -<span size="12000">DEF</span> - True - GTK_JUSTIFY_CENTER - - - - - 2 - 3 - - - - - True - False - 0 - - - - - - - - True - <span size="30000" weight="bold">2</span> -<span size="12000">ABC</span> - True - GTK_JUSTIFY_CENTER - - - - - 1 - 2 - - - - - True - False - 0 - - - - - True - <span size="33000" weight="bold">1</span> -<span size="9000"> </span> - True - - - - - - - 1 - - - - - True - False - - - - - 30 - True - Keypad - - - tab - True - False - - - - - True - 2 - 1 - - - True - - - True - True - False - - - - - - GTK_FILL - GTK_FILL - - - - - True - True - GTK_POLICY_NEVER - - - True - True - False - False - True - GTK_TREE_VIEW_GRID_LINES_HORIZONTAL - True - - - - - - 1 - 2 - - - - - 1 - True - False - - - - - True - Contacts - - - tab - 1 - True - False - - - - - True - True - GTK_POLICY_NEVER - - - True - True - False - False - True - GTK_TREE_VIEW_GRID_LINES_HORIZONTAL - True - - - - - - 1 - True - False - - - - - 30 - True - Recent - - - tab - 1 - True - False - - - - - True - 11 - 3 - 2 - - - - - - True - 1 - 5 - GrandCentral -Number: - GTK_JUSTIFY_RIGHT - - - - - True - <span size="15000" weight="bold">(518) 555-1212</span> - True - - - 1 - 2 - - - - - - True - True - True - Clear Account Information -must reauthenticate - 0 - - - - 1 - 2 - 1 - 2 - - - - - - True - 1 - 5 - Callback Number: - - - 2 - 3 - - - - - True - - - True - True - - - - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - - 2 - True - False - - - - - 30 - True - Account - - - tab - 2 - False - - - - - True - - - True - <span size="20000" weight="bold">GrandCentral Dialer</span> -Copyright 2008 - True - GTK_JUSTIFY_CENTER - - - - - True - GUI front-end to initiate outbound call from Grandcentral.com, typically with Grancentral configured to connect the outbound call to a VOIP number accessible via Gizmo on the Internet Tablet. - True - - - 1 - - - - - True - Authors: Mark Bergman <bergman@merctech.com>, Eric Warnke <ericew@gmail.com> - True - - - 2 - - - - - 3 - True - False - - - - - 30 - True - About - - - tab - 3 - False - - - - - 1 - - - - - - - 5 - Grandcentral Login - False - True - GTK_WIN_POS_CENTER_ON_PARENT - True - GDK_WINDOW_TYPE_HINT_DIALOG - True - True - False - Dialpad - False - - - True - 2 - - - True - 2 - 2 - - - True - Username - - - - - True - Password - - - 1 - 2 - - - - - True - True - - - 1 - 2 - - - - - True - True - False - - - 1 - 2 - 1 - 2 - - - - - 1 - - - - - True - GTK_BUTTONBOX_END - - - True - True - True - Login - 0 - - - - - - True - True - Close - 0 - - - - 1 - - - - - False - GTK_PACK_END - - - - - - - 5 - Select Phone Type - False - True - GTK_WIN_POS_CENTER_ON_PARENT - True - GDK_WINDOW_TYPE_HINT_DIALOG - True - True - False - Dialpad - False - - - True - 2 - - - True - True - True - - - - 1 - - - - - True - GTK_BUTTONBOX_END - - - True - True - Select - 0 - - - - - - True - True - True - Cancel - 0 - - - - 1 - - - - - False - GTK_PACK_END - - - - - - diff --git a/src/gc_dialer.py b/src/gc_dialer.py deleted file mode 100755 index e4d5ced..0000000 --- a/src/gc_dialer.py +++ /dev/null @@ -1,784 +0,0 @@ -#!/usr/bin/python - -# GC Dialer - Front end for Google's Grand Central service. -# Copyright (C) 2008 Mark Bergman bergman AT merctech DOT 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.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 - - -""" -Grandcentral Dialer -""" - - -import sys -import gc -import os -import threading -import time -import re -import warnings - -import gobject -import gtk -import gtk.glade - -try: - import hildon -except ImportError: - hildon = None - -try: - import osso -except ImportError: - osso = None - -try: - import conic -except ImportError: - conic = None - -try: - import doctest - import optparse -except ImportError: - doctest = None - optparse = None - -from gc_backend import GCDialer -from evo_backend import EvolutionAddressBook - -import socket - - -socket.setdefaulttimeout(5) - - -def make_ugly(prettynumber): - """ - function to take a phone number and strip out all non-numeric - characters - - >>> make_ugly("+012-(345)-678-90") - '01234567890' - """ - uglynumber = re.sub('\D', '', prettynumber) - return uglynumber - - -def make_pretty(phonenumber): - """ - Function to take a phone number and return the pretty version - pretty numbers: - if phonenumber begins with 0: - ...-(...)-...-.... - if phonenumber begins with 1: ( for gizmo callback numbers ) - 1 (...)-...-.... - if phonenumber is 13 digits: - (...)-...-.... - if phonenumber is 10 digits: - ...-.... - >>> make_pretty("12") - '12' - >>> make_pretty("1234567") - '123-4567' - >>> make_pretty("2345678901") - '(234)-567-8901' - >>> make_pretty("12345678901") - '1 (234)-567-8901' - >>> make_pretty("01234567890") - '+012-(345)-678-90' - """ - if phonenumber is None: - return "" - - if len(phonenumber) < 3: - return phonenumber - - if phonenumber[0] == "0": - prettynumber = "" - prettynumber += "+%s" % phonenumber[0:3] - if 3 < len(phonenumber): - prettynumber += "-(%s)" % phonenumber[3:6] - if 6 < len(phonenumber): - prettynumber += "-%s" % phonenumber[6:9] - if 9 < len(phonenumber): - prettynumber += "-%s" % phonenumber[9:] - return prettynumber - elif len(phonenumber) <= 7: - prettynumber = "%s-%s" % (phonenumber[0:3], phonenumber[3:]) - elif len(phonenumber) > 8 and phonenumber[0] == "1": - prettynumber = "1 (%s)-%s-%s" % (phonenumber[1:4], phonenumber[4:7], phonenumber[7:]) - elif len(phonenumber) > 7: - prettynumber = "(%s)-%s-%s" % (phonenumber[0:3], phonenumber[3:6], phonenumber[6:]) - return prettynumber - - -def make_idler(func): - """ - Decorator that makes a generator-function into a function that will continue execution on next call - """ - a = [] - - def decorated_func(*args, **kwds): - if not a: - a.append(func(*args, **kwds)) - try: - a[0].next() - return True - except StopIteration: - del a[:] - return False - - decorated_func.__name__ = func.__name__ - decorated_func.__doc__ = func.__doc__ - decorated_func.__dict__.update(func.__dict__) - - return decorated_func - - -class DummyAddressBook(object): - """ - Minimal example of both an addressbook factory and an addressbook - """ - - def get_addressbooks(self): - """ - @returns Iterable of (Address Book Factory, Book Id, Book Name) - """ - yield self, "", "None" - - def open_addressbook(self, bookId): - return self - - @staticmethod - def factory_short_name(): - return "" - - @staticmethod - def factory_name(): - return "" - - @staticmethod - def get_contacts(): - """ - @returns Iterable of (contact id, contact name) - """ - return [] - - @staticmethod - def get_contact_details(contactId): - """ - @returns Iterable of (Phone Type, Phone Number) - """ - return [] - - -class PhoneTypeSelector(object): - - def __init__(self, widgetTree, gcBackend): - self._gcBackend = gcBackend - self._widgetTree = widgetTree - self._dialog = self._widgetTree.get_widget("phonetype_dialog") - - self._selectButton = self._widgetTree.get_widget("select_button") - self._selectButton.connect("clicked", self._on_phonetype_select) - - self._cancelButton = self._widgetTree.get_widget("cancel_button") - self._cancelButton.connect("clicked", self._on_phonetype_cancel) - - self._typemodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - self._typeviewselection = None - - typeview = self._widgetTree.get_widget("phonetypes") - typeview.connect("row-activated", self._on_phonetype_select) - typeview.set_model(self._typemodel) - textrenderer = gtk.CellRendererText() - - # Add the column to the treeview - column = gtk.TreeViewColumn("Phone Numbers", textrenderer, text=1) - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - - typeview.append_column(column) - - self._typeviewselection = typeview.get_selection() - self._typeviewselection.set_mode(gtk.SELECTION_SINGLE) - - def run(self, contactDetails): - self._typemodel.clear() - - for phoneType, phoneNumber in contactDetails: - self._typemodel.append((phoneNumber, "%s - %s" % (make_pretty(phoneNumber), phoneType))) - - userResponse = self._dialog.run() - - if userResponse == gtk.RESPONSE_OK: - model, itr = self._typeviewselection.get_selected() - if itr: - phoneNumber = self._typemodel.get_value(itr, 0) - else: - phoneNumber = "" - - self._typeviewselection.unselect_all() - self._dialog.hide() - return phoneNumber - - def _on_phonetype_select(self, *args): - self._dialog.response(gtk.RESPONSE_OK) - - def _on_phonetype_cancel(self, *args): - self._dialog.response(gtk.RESPONSE_CANCEL) - - -class Dialpad(object): - - __pretty_app_name__ = "Dialer" - __app_name__ = "gc_dialer" - __version__ = "0.8.0" - __app_magic__ = 0xdeadbeef - - _glade_files = [ - './gc_dialer.glade', - '../lib/gc_dialer.glade', - '/usr/local/lib/gc_dialer.glade', - ] - - def __init__(self): - self._phonenumber = "" - self._prettynumber = "" - self._areacode = "518" - - self._clipboard = gtk.clipboard_get() - - self._deviceIsOnline = True - self._callbackList = None - self._callbackNeedsSetup = True - - self._recenttime = 0.0 - self._recentmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - self._recentviewselection = None - - self._contactstime = 0.0 - self._contactsmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) - self._contactsviewselection = None - - for path in Dialpad._glade_files: - if os.path.isfile(path): - self._widgetTree = gtk.glade.XML(path) - break - else: - self.display_error_message("Cannot find gc_dialer.glade") - gtk.main_quit() - return - - aboutHeader = self._widgetTree.get_widget("about_title") - aboutHeader.set_label("%s\nVersion %s" % (aboutHeader.get_label(), Dialpad.__version__)) - - #Get the buffer associated with the number display - self._numberdisplay = self._widgetTree.get_widget("numberdisplay") - self.set_number("") - self._notebook = self._widgetTree.get_widget("notebook") - - self._window = self._widgetTree.get_widget("Dialpad") - - global hildon - self._app = None - self._isFullScreen = False - if hildon is not None and self._window is gtk.Window: - warnings.warn("Hildon installed but glade file not updated to work with hildon", UserWarning, 2) - hildon = None - elif hildon is not None: - self._app = hildon.Program() - self._app.add_window(self._window) - self._widgetTree.get_widget("callbackcombo").get_child().set_property('hildon-input-mode', (1 << 4)) - self._widgetTree.get_widget("usernameentry").set_property('hildon-input-mode', 7) - self._widgetTree.get_widget("passwordentry").set_property('hildon-input-mode', 7|(1 << 29)) - - gtkMenu = self._widgetTree.get_widget("dialpad_menubar") - menu = gtk.Menu() - for child in gtkMenu.get_children(): - child.reparent(menu) - self._window.set_menu(menu) - gtkMenu.destroy() - - self._window.connect("key-press-event", self._on_key_press) - self._window.connect("window-state-event", self._on_window_state_change) - else: - warnings.warn("No Hildon", UserWarning, 2) - - if hildon is not None: - self._window.set_title("Keypad") - else: - self._window.set_title("%s - Keypad" % self.__pretty_app_name__) - - self._osso = None - if osso is not None: - self._osso = osso.Context(Dialpad.__app_name__, Dialpad.__version__, False) - device = osso.DeviceState(self._osso) - device.set_device_state_callback(self._on_device_state_change, 0) - else: - warnings.warn("No OSSO", UserWarning, 2) - - self._connection = None - if conic is not None: - self._connection = conic.Connection() - self._connection.connect("connection-event", self._on_connection_change, Dialpad.__app_magic__) - self._connection.request_connection(conic.CONNECT_FLAG_NONE) - else: - warnings.warn("No Internet Connectivity API ", UserWarning, 2) - - callbackMapping = { - # Process signals from buttons - "on_loginbutton_clicked": self._on_loginbutton_clicked, - "on_loginclose_clicked": self._on_loginclose_clicked, - - "on_dialpad_quit": self._on_close, - "on_paste": self._on_paste, - "on_clear_number": self._on_clear_number, - - "on_clearcookies_clicked": self._on_clearcookies_clicked, - "on_notebook_switch_page": self._on_notebook_switch_page, - "on_recentview_row_activated": self._on_recentview_row_activated, - "on_contactsview_row_activated" : self._on_contactsview_row_activated, - - "on_digit_clicked": self._on_digit_clicked, - "on_back_clicked": self._on_backspace, - "on_dial_clicked": self._on_dial_clicked, - } - self._widgetTree.signal_autoconnect(callbackMapping) - self._widgetTree.get_widget("callbackcombo").get_child().connect("changed", self._on_callbackentry_changed) - self._widgetTree.get_widget("addressbook_combo").get_child().connect("changed", self._on_addressbook_entry_changed) - - if self._window: - self._window.connect("destroy", gtk.main_quit) - self._window.show_all() - - self._gcBackend = GCDialer() - - self._addressBookFactories = [ - DummyAddressBook(), - EvolutionAddressBook(), - self._gcBackend, - ] - self._addressBook = None - self.open_addressbook(*self.get_addressbooks().next()[0][0:2]) - - self._booksList = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) - for (factoryId, bookId), (factoryName, bookName) in self.get_addressbooks(): - if factoryName and bookName: - entryName = "%s: %s" % (factoryName, bookName) - elif factoryName: - entryName = factoryName - elif bookName: - entryName = bookName - else: - entryName = "Bad name (%d)" % factoryId - row = (str(factoryId), bookId, entryName) - self._booksList.append(row) - - combobox = self._widgetTree.get_widget("addressbook_combo") - combobox.set_model(self._booksList) - combobox.set_text_column(2) - combobox.set_active(0) - - self._phoneTypeSelector = PhoneTypeSelector(self._widgetTree, self._gcBackend) - - self._init_recent_view() - self._init_contacts_view() - if self._gcBackend.is_authed(): - self.set_account_number() - else: - self.attempt_login(2) - - def _init_recent_view(self): - recentview = self._widgetTree.get_widget("recentview") - recentview.set_model(self._recentmodel) - textrenderer = gtk.CellRendererText() - - # Add the column to the treeview - column = gtk.TreeViewColumn("Calls", textrenderer, text=1) - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - - recentview.append_column(column) - - self._recentviewselection = recentview.get_selection() - self._recentviewselection.set_mode(gtk.SELECTION_SINGLE) - - return False - - def _init_contacts_view(self): - contactsview = self._widgetTree.get_widget("contactsview") - contactsview.set_model(self._contactsmodel) - - # Add the column to the treeview - column = gtk.TreeViewColumn("Contact") - - textrenderer = gtk.CellRendererText() - column.pack_start(textrenderer, expand=True) - column.add_attribute(textrenderer, 'text', 1) - - textrenderer = gtk.CellRendererText() - column.pack_start(textrenderer, expand=True) - column.add_attribute(textrenderer, 'text', 4) - - column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - column.set_sort_column_id(1) - column.set_visible(True) - contactsview.append_column(column) - - #textrenderer = gtk.CellRendererText() - #column = gtk.TreeViewColumn("Location", textrenderer, text=2) - #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - #column.set_sort_column_id(2) - #column.set_visible(True) - #contactsview.append_column(column) - - #textrenderer = gtk.CellRendererText() - #column = gtk.TreeViewColumn("Phone", textrenderer, text=3) - #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) - #column.set_sort_column_id(3) - #column.set_visible(True) - #contactsview.append_column(column) - - self._contactsviewselection = contactsview.get_selection() - self._contactsviewselection.set_mode(gtk.SELECTION_SINGLE) - - return False - - def _idly_populate_callback_combo(self): - self._callbackList = gtk.ListStore(gobject.TYPE_STRING) - for number, description in self._gcBackend.get_callback_numbers().iteritems(): - self._callbackList.append((make_pretty(number),)) - - combobox = self._widgetTree.get_widget("callbackcombo") - combobox.set_model(self._callbackList) - combobox.set_text_column(0) - - combobox.get_child().set_text(make_pretty(self._gcBackend.get_callback_number())) - self._callbackNeedsSetup = False - - def _idly_populate_recentview(self): - self._recentmodel.clear() - - for personsName, phoneNumber, date, action in self._gcBackend.get_recent(): - description = "%s on %s from/to %s - %s" % (action.capitalize(), date, personsName, phoneNumber) - item = (phoneNumber, description) - self._recentmodel.append(item) - - self._recenttime = time.time() - return False - - @make_idler - def _idly_populate_contactsview(self): - self._contactsmodel.clear() - - # completely disable updating the treeview while we populate the data - contactsview = self._widgetTree.get_widget("contactsview") - contactsview.freeze_child_notify() - contactsview.set_model(None) - - contactType = (self._addressBook.factory_short_name(),) - for contactId, contactName in self._addressBook.get_contacts(): - self._contactsmodel.append(contactType + (contactName, "", contactId) + ("",)) - yield - - # restart the treeview data rendering - contactsview.set_model(self._contactsmodel) - contactsview.thaw_child_notify() - - self._contactstime = time.time() - - def attempt_login(self, numOfAttempts = 1): - """ - @note Assumes that you are already logged in - """ - assert 0 < numOfAttempts, "That was pointless having 0 or less login attempts" - - if not self._deviceIsOnline: - warnings.warn("Attempted to login while device was offline", UserWarning, 2) - return False - - dialog = self._widgetTree.get_widget("login_dialog") - for i in range(numOfAttempts): - dialog.run() - - username = self._widgetTree.get_widget("usernameentry").get_text() - password = self._widgetTree.get_widget("passwordentry").get_text() - self._widgetTree.get_widget("passwordentry").set_text("") - - loggedIn = self._gcBackend.login(username, password) - dialog.hide() - if loggedIn: - if self._gcBackend.get_callback_number() is None: - self._gcBackend.set_sane_callback() - self.set_account_number() - return True - - return False - - def display_error_message(self, msg): - error_dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) - - def close(dialog, response, editor): - editor.about_dialog = None - dialog.destroy() - error_dialog.connect("response", close, self) - error_dialog.run() - - def get_addressbooks(self): - """ - @returns Iterable of ((Factory Id, Book Id), (Factory Name, Book Name)) - """ - for i, factory in enumerate(self._addressBookFactories): - for bookFactory, bookId, bookName in factory.get_addressbooks(): - yield (i, bookId), (factory.factory_name(), bookName) - - def open_addressbook(self, bookFactoryId, bookId): - self._addressBook = self._addressBookFactories[bookFactoryId].open_addressbook(bookId) - self._contactstime = 0 - gobject.idle_add(self._idly_populate_contactsview) - - def set_number(self, number): - """ - Set the callback phonenumber - """ - self._phonenumber = make_ugly(number) - self._prettynumber = make_pretty(self._phonenumber) - self._numberdisplay.set_label("%s" % (self._prettynumber)) - - def set_account_number(self): - """ - Displays current account number - """ - accountnumber = self._gcBackend.get_account_number() - self._widgetTree.get_widget("gcnumber_display").set_label("%s" % (accountnumber)) - - @staticmethod - def _on_close(*args, **kwds): - gtk.main_quit() - - def _on_device_state_change(self, shutdown, save_unsaved_data, memory_low, system_inactivity, message, userData): - """ - For shutdown or save_unsaved_data, our only state is cookies and I think the cookie manager handles that for us. - For system_inactivity, we have no background tasks to pause - - @note Hildon specific - """ - if memory_low: - self._gcBackend.clear_caches() - re.purge() - gc.collect() - - def _on_connection_change(self, connection, event, magicIdentifier): - """ - @note Hildon specific - """ - status = event.get_status() - error = event.get_error() - iap_id = event.get_iap_id() - bearer = event.get_bearer_type() - - if status == conic.STATUS_CONNECTED: - self._window.set_sensitive(True) - self._deviceIsOnline = True - if not self._gcBackend.is_authed(): - self.attempt_login(2) - elif status == conic.STATUS_DISCONNECTED: - self._window.set_sensitive(False) - self._deviceIsOnline = False - - def _on_window_state_change(self, widget, event, *args): - """ - @note Hildon specific - """ - if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: - self._isFullScreen = True - else: - self._isFullScreen = False - - def _on_key_press(self, widget, event, *args): - """ - @note Hildon specific - """ - if event.keyval == gtk.keysyms.F6: - if self._isFullScreen: - self._window.unfullscreen() - else: - self._window.fullscreen() - - def _on_loginbutton_clicked(self, *args): - self._widgetTree.get_widget("login_dialog").response(gtk.RESPONSE_OK) - - def _on_loginclose_clicked(self, *args): - self._on_close() - sys.exit(0) - - def _on_clearcookies_clicked(self, *args): - self._gcBackend.logout() - self._callbackNeedsSetup = True - self._recenttime = 0.0 - self._contactstime = 0.0 - self._recentmodel.clear() - self._widgetTree.get_widget("callbackcombo").get_child().set_text("") - - # re-run the inital grandcentral setup - self.attempt_login(2) - gobject.idle_add(self._idly_populate_callback_combo) - - def _on_callbackentry_changed(self, *args): - """ - @todo Potential blocking on web access, maybe we should defer this or put up a dialog? - """ - text = make_ugly(self._widgetTree.get_widget("callbackcombo").get_child().get_text()) - if not self._gcBackend.is_valid_syntax(text): - warnings.warn("%s is not a valid callback number" % text, UserWarning, 2) - elif text == self._gcBackend.get_callback_number(): - warnings.warn("Callback number already is %s" % self._gcBackend.get_callback_number(), UserWarning, 2) - else: - self._gcBackend.set_callback_number(text) - - def _on_recentview_row_activated(self, treeview, path, view_column): - model, itr = self._recentviewselection.get_selected() - if not itr: - return - - self.set_number(self._recentmodel.get_value(itr, 0)) - self._notebook.set_current_page(0) - self._recentviewselection.unselect_all() - - def _on_addressbook_entry_changed(self, *args, **kwds): - combobox = self._widgetTree.get_widget("addressbook_combo") - itr = combobox.get_active_iter() - - factoryId = int(self._booksList.get_value(itr, 0)) - bookId = self._booksList.get_value(itr, 1) - self.open_addressbook(factoryId, bookId) - - def _on_contactsview_row_activated(self, treeview, path, view_column): - model, itr = self._contactsviewselection.get_selected() - if not itr: - return - - contactId = self._contactsmodel.get_value(itr, 3) - contactDetails = self._addressBook.get_contact_details(contactId) - contactDetails = [phoneNumber for phoneNumber in contactDetails] - - if len(contactDetails) == 0: - phoneNumber = "" - elif len(contactDetails) == 1: - phoneNumber = contactDetails[0][1] - else: - phoneNumber = self._phoneTypeSelector.run(contactDetails) - - if 0 < len(phoneNumber): - self.set_number(phoneNumber) - self._notebook.set_current_page(0) - - self._contactsviewselection.unselect_all() - - def _on_notebook_switch_page(self, notebook, page, page_num): - if page_num == 1 and 300 < (time.time() - self._contactstime): - gobject.idle_add(self._idly_populate_contactsview) - elif page_num == 2 and 300 < (time.time() - self._recenttime): - gobject.idle_add(self._idly_populate_recentview) - elif page_num == 3 and self._callbackNeedsSetup: - gobject.idle_add(self._idly_populate_callback_combo) - - tabTitle = self._notebook.get_tab_label(self._notebook.get_nth_page(page_num)).get_text() - if hildon is not None: - self._window.set_title(tabTitle) - else: - self._window.set_title("%s - %s" % (self.__pretty_app_name__, tabTitle)) - - def _on_dial_clicked(self, widget): - """ - @todo Potential blocking on web access, maybe we should defer parts of this or put up a dialog? - """ - loggedIn = self._gcBackend.is_authed() - if not loggedIn: - loggedIn = self.attempt_login(2) - - if not loggedIn or not self._gcBackend.is_authed() or self._gcBackend.get_callback_number() == "": - self.display_error_message("Backend link with grandcentral is not working, please try again") - warnings.warn("Backend Status: Logged in? %s, Authenticated? %s, Callback=%s" % (loggedIn, self._gcBackend.is_authed(), self._gcBackend.get_callback_number()), UserWarning, 2) - return - - try: - callSuccess = self._gcBackend.dial(self._phonenumber) - except ValueError, e: - self._gcBackend._msg = e.message - callSuccess = False - - if not callSuccess: - self.display_error_message(self._gcBackend._msg) - else: - self.set_number("") - - self._recentmodel.clear() - self._recenttime = 0.0 - - def _on_paste(self, *args): - contents = self._clipboard.wait_for_text() - phoneNumber = re.sub('\D', '', contents) - self.set_number(phoneNumber) - - def _on_clear_number(self, *args): - self.set_number("") - - def _on_digit_clicked(self, widget): - self.set_number(self._phonenumber + widget.get_name()[5]) - - def _on_backspace(self, widget): - self.set_number(self._phonenumber[:-1]) - - -def run_doctest(): - failureCount, testCount = doctest.testmod() - if not failureCount: - print "Tests Successful" - sys.exit(0) - else: - sys.exit(1) - - -def run_dialpad(): - gtk.gdk.threads_init() - title = 'Dialpad' - handle = Dialpad() - gtk.main() - - -class DummyOptions(object): - - def __init__(self): - self.test = False - - -if __name__ == "__main__": - if hildon is not None: - gtk.set_application_name(Dialpad.__pretty_app_name__) - - if optparse is not None: - parser = optparse.OptionParser() - parser.add_option("-t", "--test", action="store_true", dest="test", help="Run tests") - (commandOptions, commandArgs) = parser.parse_args() - else: - commandOptions = DummyOptions() - commandArgs = [] - - if commandOptions.test: - run_doctest() - else: - run_dialpad() diff --git a/src/gc_dialer_256.png b/src/gc_dialer_256.png deleted file mode 100644 index a875350..0000000 Binary files a/src/gc_dialer_256.png and /dev/null differ diff --git a/src/gc_dialer_26.png b/src/gc_dialer_26.png deleted file mode 100644 index df50c66..0000000 Binary files a/src/gc_dialer_26.png and /dev/null differ diff --git a/src/gc_dialer_64.png b/src/gc_dialer_64.png deleted file mode 100644 index 8d98390..0000000 Binary files a/src/gc_dialer_64.png and /dev/null differ diff --git a/support/DEBIAN/control b/support/DEBIAN/control deleted file mode 100644 index f1185d9..0000000 --- a/support/DEBIAN/control +++ /dev/null @@ -1,50 +0,0 @@ -Maintainer: Mark Bergman -Package: Dialer -Section: user/Communication -Priority: Optional -Depends: python2.5, python2.5-gtk2 -Recommends: python2.5-hildon, python2.5-evolution -Version: 0.0.0 -Architecture: all -Description: Grand Central frontend written in Python - . - Features - * Dialing of custom numbers. - * GrandCentral contact support. - * Hildon integration where supported. - . - Requirements - * An account with Grandcentral. -Maemo-Icon-26: - iVBORw0KGgoAAAANSUhEUgAAABcAAAAaCAYAAABctMd+AAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A - /wD/oL2nkwAAAAlwSFlzAAAN1wAADdcBQiibeAAAAAd0SU1FB9gGHA8sCwKJ3H4AAAYHSURBVEjH - pZV9TFvXGcZ/9/ravjYBu2BjiEk8yEehWgKiqUBdlnaBbgI0kICsicISiYmOSEumaZomkSxEkZI/ - tkhTomhKoqidiPKhsraoiogil26wKClJmbQvZU1dwAYaGBAMXK6vr6/v3R8rVtamS6c9/5wjnfM+ - 76P3fc57BD7D5cuXrf7+flWSpD/7/f7ezZs3L2ua5lg9VxQF0zTRdR3DMDBNE0VR0HWdRCKBrusI - glAcCARePX369HoAAWBubu54Xl7eL1aJTp48SVdXF0+DoihEIhEikQgTExMkEgkqKipoaGgQMuSW - ZVmPB3V1dVFSUkJvby/pdBpBELDb7QiCgM1my6w2mw1Jkrh69ep/JD1+/Lje3d3tlJ6kaGlpCVmW - qaurA8gQre4dDgeSJGGz2bj9wQfMxeM8+uciuq5Tur6Yo0ePOsY+Gat6InkikWDjxo20tbU9tTRu - v5+010uBw4tsgPRZl54teLZBAtB1HYfDgWEY6LpOMpmkurqaqakpZmdnkSQJURQRRRFN0zLNdWZl - 4fb7icVNXiivorgLfpV7gre8b+D52BMRAcbHxzPl0DSNlZUVAILBICUlJRQVFWGaJteuXSMvLw+f - z4fL5cJlN1m/NouC1p0QG2E8+SG75r/D86UVpIyUK6McIJlMoqoqqVQKAFVVWVhYQJIkwuEwra2t - XLx4kZaWFiQJ/NkihfkyvNcPuMm4Ygpek18TpVVLGYbB8vIyhmGwah5RFJEkCafTSVVVFQCVlZUA - 2AWTQo+dgqrzzNyNAUXI5S28/r3fsST4eKg8DIqrihVFQVVVEolEplmyLBMMBsnNzWXr1q04HA6q - q6txuVx4PB7wOtj1Ug72QA7ZGx18d8c00ppl3H4HpmAaUmdn5zpFUVhYWCCZTKJpGoIgMDAwwIUL - F5ienmZwcJCdO3dSWFhIc3MzO3bs4ODBH1FaKLHvBwcpffnbbPhaIeXPBbh75gbba77F65ffXieV - l5fblpaWWF5eRlGUzKOpqanh1q1bmKYJQCAQoKmpifv376NpGm3f341HG+fWhJ2Tb0tkeU1a6+Fn - WzaTle3CMIykJIpi0LIsVFUlnU5nEgBEIhHOnz8PwLFjx4hGo3R0dPx7rszHCL/Zz7tRL3PvRJkT - HFx60EDdrgd8+sBE07S1otPptKmqmlGeTCbRdZ3+/n727NlDZ2cnqqpy4sQJCgoKOHLkCPfu3ePT - mUe8UvsiJdmPEHKWkfw6m3LHyVqTjZZUURTFIfl8vtDo6CiqqrKyskIymcQwDOrr6xkZGWH37t0A - 7N+/H7fbTXd3N+Pj4wTy1hB0ynyz5hFmaBtF64r4eqmPv/1hiBdeqcX6Tc8zoiAIvry8vIy30+k0 - pmly5swZNmzYQF9fH4qicOrUKTRN49y5c4iiyF/++nc+fDDF7z8SeW+8krc+ep7BqRB1jbuoqHoJ - TdPWSul0erCsrIxoNIqmacTjcVKpFIcOHeLKlSvk5OSQn59PVVUVMzMzNDc3MzY2ht3uxu6S6aic - 54fPXYJ0mqTuJjKxlvdHfovT6UxJjY2Nf7Isi3A4zPDwMJOTkxQXFzM0NMSNGzeQZZloNEo0GmV0 - dJR9+/bh8/no6enBMnQaG+qR5XzcLjc5Hg9JUeBq7yX27t37sgQgCILw+Zkej8dpaWlhaGiIUChE - UVERbW1t3Lx5k2AwyOHDh5mcnCQrK4tAIMDo6Ch9N99nYmKCAwcOvNrY2DgpPE5oWVYBMAKs/fxo - jcfjeL1exsbG8Hg85ObmMjAwwO3bt5mdnQWgtrb2l01NTT9fjRH+26yempr6STQa3Xrnzp3C6enp - F4eHh7NdLhfbt2/vCYVCXpfL9Y/S0tL+LVu2DPL/or293WpqarK+6n3xfyHv6OigrKzsK9//Qlks - y/o18AzwMTAPtAHf+JL4nwIm4AfKgR8LgvDJl2aznoDFxUVrcXHRisVi1lPwxuNcX/igr1+/fvfs - 2bPeWCz2x1Qq9XDbtm2lDoejVZZl0uk0siyTSqWYn5+PhMPhvk2bNmEYRigUCrW2t7efepzrX076 - 2oPGX2oGAAAAAElFTkSuQmCC - -Installed-Size: 0 diff --git a/support/DEBIAN/postinst b/support/DEBIAN/postinst deleted file mode 100755 index 1fe6997..0000000 --- a/support/DEBIAN/postinst +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -gtk-update-icon-cache -f /usr/share/icons/hicolor \ No newline at end of file diff --git a/support/GrandcentralDialer.pypackager b/support/GrandcentralDialer.pypackager deleted file mode 100644 index 3bdcce0..0000000 --- a/support/GrandcentralDialer.pypackager +++ /dev/null @@ -1,25 +0,0 @@ -(S'Grandcentral_Dialer' -S'0.6' -S'user/Communication' -S'all' -S'Optional' -S'Mark Bergman ' -S'python2.5, python2.5-hildon, python2.5-gtk2' -S'Python script that provides a telephone dial-pad in order to enter\nphone numbers to be dialed through Grandcentral.com.\n\nRequirements:\n\tan account with Grandcentral' -S'/tmp/gc_dialer/build' -S'/tmp/gc_dialer/gc_dialer_26.png' -S'#!/bin/sh\n\ngtk-update-icon-cache -f /usr/share/icons/hicolor' -S'' -S'' -S'' -S'0.6 "Daddy brain"\n\nNative login, UI updates, cleanup, and much more\n\n\n0.5\n\nAdded dialing history, changed UI.' -S'extras' -S'chinook' -S'low' -S'email@email.com' -S'' -S'/tmp/gc_dialer/build' -S'z2n' -S'1' -tp1 -. \ No newline at end of file diff --git a/support/pylint.rc b/support/pylint.rc deleted file mode 100644 index b9a1464..0000000 --- a/support/pylint.rc +++ /dev/null @@ -1,305 +0,0 @@ -# lint Python modules using external checkers. -# -# This is the main checker controling the other ones and the reports -# generation. It is itself both a raw checker and an astng checker in order -# to: -# * handle message activation / deactivation at the module level -# * handle some basic but necessary stats'data (number of classes, methods...) -# -[MASTER] - -# Specify a configuration file. -#rcfile= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Profiled execution. -profile=no - -# Add to the black list. It should be a base name, not a -# path. You may set this option multiple times. -ignore=CVS - -# Pickle collected data for later comparisons. -persistent=yes - -# Set the cache size for astng objects. -cache-size=500 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - - -[MESSAGES CONTROL] - -# Enable only checker(s) with the given id(s). This option conflicts with the -# disable-checker option -#enable-checker= - -# Enable all checker(s) except those with the given id(s). This option -# conflicts with the enable-checker option -#disable-checker= - -# Enable all messages in the listed categories. -#enable-msg-cat= - -# Disable all messages in the listed categories. -#disable-msg-cat= - -# Enable the message(s) with the given id(s). -#enable-msg= - -# Disable the message(s) with the given id(s). -disable-msg=W0403,W0612,W0613,C0103,C0111,C0301 - -[REPORTS] - -# set the output format. Available formats are text, parseable, colorized, msvs -# (visual studio) and html -output-format=text - -# Include message's id in output -include-ids=no - -# Put messages in a separate file for each module / package specified on the -# command line instead of printing them on stdout. Reports (if any) will be -# written in a file name "pylint_global.[txt|html]". -files-output=no - -# Tells wether to display a full report or only the messages -reports=yes - -# Python expression which should return a note less than 10 (10 is the highest -# note).You have access to the variables errors warning, statement which -# respectivly contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (R0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Add a comment according to your evaluation note. This is used by the global -# evaluation report (R0004). -comment=no - -# Enable the report(s) with the given id(s). -#enable-report= - -# Disable the report(s) with the given id(s). -#disable-report= - - -# checks for -# * unused variables / imports -# * undefined variables -# * redefinition of variable from builtins or from an outer scope -# * use of variable before assigment -# -[VARIABLES] - -# Tells wether we should check for unused import in __init__ files. -init-import=no - -# A regular expression matching names used for dummy variables (i.e. not used). -dummy-variables-rgx=_|dummy - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - - -# checks for : -# * doc strings -# * modules / classes / functions / methods / arguments / variables name -# * number of arguments, local variables, branchs, returns and statements in -# functions, methods -# * required module attributes -# * dangerous default values as arguments -# * redefinition of function / method / class -# * uses of the global statement -# -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes= - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - -# Regular expression which should only match correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression which should only match correct module level names -const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][a-z0-9_]{2,30}$ - -# Regular expression which should only match correct instance attribute names -attr-rgx=[a-z_][a-zA-Z0-9_]{2,30}$ - -# Regular expression which should only match correct argument names -argument-rgx=[a-z_][a-zA-Z0-9_]{2,30}$ - -# Regular expression which should only match correct variable names -variable-rgx=[a-z_][a-zA-Z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# List of builtins function names that should not be used, separated by a comma -bad-functions=map,filter,apply,input - - -# try to find bugs in the code using type inference -# -[TYPECHECK] - -# Tells wether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# When zope mode is activated, consider the acquired-members option to ignore -# access to some undefined attributes. -zope=no - -# List of members which are usually get through zope's acquisition mecanism and -# so shouldn't trigger E0201 when accessed (need zope=yes to be considered). -acquired-members=REQUEST,acl_users,aq_parent - - -# checks for sign of poor/misdesign: -# * number of methods, attributes, local variables... -# * size, complexity of functions, methods -# -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of branch for function / method body -max-branchs=12 - -# Maximum number of statements in function / method body -max-statements=50 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=1 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - - -# checks for : -# * methods without self as first argument -# * overridden methods signature -# * access only to existant members via self -# * attributes not defined in the __init__ method -# * supported interfaces implementation -# * unreachable code -# -[CLASSES] - -# List of interface methods to ignore, separated by a comma. This is used for -# instance to not check methods defines in Zope's Interface base class. -ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - - -# checks for -# * external modules dependencies -# * relative / wildcard imports -# * cyclic imports -# * uses of deprecated modules -# -[IMPORTS] - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,string,TERMIOS,Bastion,rexec - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report R0402 must not be disabled) -import-graph= - -# Create a graph of external dependencies in the given file (report R0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of internal dependencies in the given file (report R0402 must -# not be disabled) -int-import-graph= - - -# checks for similarities and duplicated code. This computation may be -# memory / CPU intensive, so you should disable it if you experiments some -# problems. -# -[SIMILARITIES] - -# Minimum lines number of a similarity. -min-similarity-lines=4 - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - - -# checks for: -# * warning notes in the code like FIXME, XXX -# * PEP 263: source code with non ascii character but no encoding declaration -# -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -# checks for : -# * unauthorized constructions -# * strict indentation -# * line length -# * use of <> instead of != -# -[FORMAT] - -# Maximum number of characters on a single line. -# @note Limiting this to the most extreme cases -max-line-length=100 - -# Maximum number of lines in a module -max-module-lines=1000 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string='\t'