Skip to content
Browse files

Merge remote-tracking branch 'upstream/master'

  • Loading branch information...
2 parents adf019b + 3d71d01 commit 8ec11eb46930d22d461b8293a0c7a1a437d46ad6 @tomasz-wiszkowski committed
Showing with 2,852 additions and 0 deletions.
  1. +21 −0 .gitignore
  2. +1 −0 AUTHORS
  3. +203 −0 COPYING
  4. +2 −0 ChangeLog
  5. 0 HISTORY
  6. +370 −0 INSTALL
  7. +3 −0 Makefile.am
  8. +2 −0 NEWS
  9. +40 −0 README
  10. +22 −0 configure.ac
  11. +20 −0 data/Makefile.am
  12. +4 −0 data/pixmaps/Makefile.am
  13. BIN data/pixmaps/exclam.png
  14. BIN data/pixmaps/terminal.png
  15. +11 −0 data/xfcon.desktop.in
  16. +2 −0 src/.gitignore
  17. +19 −0 src/Makefile.am
  18. +5 −0 src/constants/Makefile.am
  19. +15 −0 src/constants/__init__.py
  20. +1 −0 src/elements/.gitignore
  21. +16 −0 src/elements/Makefile.am
  22. +19 −0 src/elements/__init__.py
  23. +187 −0 src/elements/xfcon_box.py
  24. +73 −0 src/elements/xfcon_dialogs.py
  25. +10 −0 src/elements/xfcon_globals.py.in
  26. +192 −0 src/elements/xfcon_notebook.py
  27. +149 −0 src/elements/xfcon_notebook_label.py
  28. +192 −0 src/elements/xfcon_object.py
  29. +117 −0 src/elements/xfcon_settings.py
  30. +128 −0 src/elements/xfcon_utils.py
  31. +261 −0 src/elements/xfcon_window.py
  32. +6 −0 src/plugins/Makefile.am
  33. +16 −0 src/plugins/__init__.py
  34. +80 −0 src/plugins/interfaces.py
  35. +5 −0 src/plugins/preferences/Makefile.am
  36. +16 −0 src/plugins/preferences/__init__.py
  37. +37 −0 src/plugins/preferences/plugin.py
  38. +30 −0 src/plugins/preferences/view.py
  39. +5 −0 src/plugins/terminal/Makefile.am
  40. +16 −0 src/plugins/terminal/__init__.py
  41. +45 −0 src/plugins/terminal/plugin.py
  42. +115 −0 src/plugins/terminal/settings.py
  43. +270 −0 src/plugins/terminal/xfcon_terminal.py
  44. +5 −0 src/plugins/test/Makefile.am
  45. +16 −0 src/plugins/test/__init__.py
  46. +37 −0 src/plugins/test/plugin.py
  47. +31 −0 src/plugins/test/test_view.py
  48. +3 −0 src/xfcon.in
  49. +34 −0 src/xfcon.py
View
21 .gitignore
@@ -0,0 +1,21 @@
+*~
+*.swp
+*.pyc
+*.pyo
+stamp-*
+config.*
+
+# By name
+autom4te.cache/
+aclocal.m4
+autoscan.log
+configure
+data/xfcon.desktop
+data/xfcon.schemas
+install-sh
+libtool
+Makefile
+Makefile.in
+missing
+src/elements/xfcon_globals.py
+src/xfcon
View
1 AUTHORS
@@ -0,0 +1 @@
+Tomasz Wiszkowski <tomasz.wiszkowski@gmail.com>
View
203 COPYING
@@ -0,0 +1,203 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.Public License instead of this License.
+
View
2 ChangeLog
@@ -0,0 +1,2 @@
+2012-06-26 Tomasz Wiszkowski <tomasz.wiszkowski@gmail.com>
+ * Initial commit.
View
0 HISTORY
No changes.
View
370 INSTALL
@@ -0,0 +1,370 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
+Inc.
+
+ Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved. This file is offered as-is,
+without warranty of any kind.
+
+Basic Installation
+==================
+
+ Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package. The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package. Some packages provide this
+`INSTALL' file but do not implement all of the features documented
+below. The lack of an optional feature in a given package is not
+necessarily a bug. More recommendations for GNU packages can be found
+in *note Makefile Conventions: (standards)Makefile Conventions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+ The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system.
+
+ Running `configure' might take a while. While running, it prints
+ some messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package, generally using the just-built uninstalled binaries.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation. When installing into a prefix owned by root, it is
+ recommended that the package be configured and built as a regular
+ user, and only the `make install' phase executed with root
+ privileges.
+
+ 5. Optionally, type `make installcheck' to repeat any self-tests, but
+ this time using the binaries in their final installed location.
+ This target does not install anything. Running this target as a
+ regular user, particularly if the prior `make install' required
+ root privileges, verifies that the installation completed
+ correctly.
+
+ 6. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+ 7. Often, you can also type `make uninstall' to remove the installed
+ files again. In practice, not all packages have tested that
+ uninstallation works correctly, even though it is required by the
+ GNU Coding Standards.
+
+ 8. Some packages, particularly those that use Automake, provide `make
+ distcheck', which can by used by developers to test that all other
+ targets like `make install' and `make uninstall' work correctly.
+ This target is generally not run by end users.
+
+Compilers and Options
+=====================
+
+ Some systems require unusual options for compilation or linking that
+the `configure' script does not know about. Run `./configure --help'
+for details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+ You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you can use GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'. This
+is known as a "VPATH" build.
+
+ With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory. After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+ On MacOS X 10.5 and later systems, you can create libraries and
+executables that work on multiple system types--known as "fat" or
+"universal" binaries--by specifying multiple `-arch' options to the
+compiler but only a single `-arch' option to the preprocessor. Like
+this:
+
+ ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
+ CPP="gcc -E" CXXCPP="g++ -E"
+
+ This is not guaranteed to produce working output in all cases, you
+may have to build one architecture at a time and combine the results
+using the `lipo' tool if you have problems.
+
+Installation Names
+==================
+
+ By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX', where PREFIX must be an
+absolute file name.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them. In general, the
+default for these options is expressed in terms of `${prefix}', so that
+specifying just `--prefix' will affect all of the other directory
+specifications that were not explicitly provided.
+
+ The most portable way to affect installation locations is to pass the
+correct locations to `configure'; however, many packages provide one or
+both of the following shortcuts of passing variable assignments to the
+`make install' command line to change installation locations without
+having to reconfigure or recompile.
+
+ The first method involves providing an override variable for each
+affected directory. For example, `make install
+prefix=/alternate/directory' will choose an alternate location for all
+directory configuration variables that were expressed in terms of
+`${prefix}'. Any directories that were specified during `configure',
+but not in terms of `${prefix}', must each be overridden at install
+time for the entire installation to be relocated. The approach of
+makefile variable overrides for each directory variable is required by
+the GNU Coding Standards, and ideally causes no recompilation.
+However, some platforms have known limitations with the semantics of
+shared libraries that end up requiring recompilation when using this
+method, particularly noticeable in packages that use GNU Libtool.
+
+ The second method involves providing the `DESTDIR' variable. For
+example, `make install DESTDIR=/alternate/directory' will prepend
+`/alternate/directory' before all installation names. The approach of
+`DESTDIR' overrides is not required by the GNU Coding Standards, and
+does not work on platforms that have drive letters. On the other hand,
+it does better at avoiding recompilation issues, and works well even
+when some directory options were not specified in terms of `${prefix}'
+at `configure' time.
+
+Optional Features
+=================
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+ Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+ Some packages offer the ability to configure how verbose the
+execution of `make' will be. For these packages, running `./configure
+--enable-silent-rules' sets the default to minimal output, which can be
+overridden with `make V=1'; while running `./configure
+--disable-silent-rules' sets the default to verbose, which can be
+overridden with `make V=0'.
+
+Particular systems
+==================
+
+ On HP-UX, the default C compiler is not ANSI C compatible. If GNU
+CC is not installed, it is recommended to use the following options in
+order to use an ANSI C compiler:
+
+ ./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
+
+and if that doesn't work, install pre-built binaries of GCC for HP-UX.
+
+ HP-UX `make' updates targets which have the same time stamps as
+their prerequisites, which makes it generally unusable when shipped
+generated files such as `configure' are involved. Use GNU `make'
+instead.
+
+ On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
+parse its `<wchar.h>' header file. The option `-nodtk' can be used as
+a workaround. If GNU CC is not installed, it is therefore recommended
+to try
+
+ ./configure CC="cc"
+
+and if that doesn't work, try
+
+ ./configure CC="cc -nodtk"
+
+ On Solaris, don't put `/usr/ucb' early in your `PATH'. This
+directory contains several dysfunctional programs; working variants of
+these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
+in your `PATH', put it _after_ `/usr/bin'.
+
+ On Haiku, software installed for all users goes in `/boot/common',
+not `/usr/local'. It is recommended to use the following options:
+
+ ./configure --prefix=/boot/common
+
+Specifying the System Type
+==========================
+
+ There may be some features `configure' cannot figure out
+automatically, but needs to determine by the type of machine the package
+will run on. Usually, assuming the package is built to be run on the
+_same_ architectures, `configure' can figure that out, but if it prints
+a message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS
+ KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+ If you want to set default values for `configure' scripts to share,
+you can create a site shell script called `config.site' that gives
+default values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+ Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug. Until the bug is fixed you can use this workaround:
+
+ CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+ `configure' recognizes the following options to control how it
+operates.
+
+`--help'
+`-h'
+ Print a summary of all of the options to `configure', and exit.
+
+`--help=short'
+`--help=recursive'
+ Print a summary of the options unique to this package's
+ `configure', and exit. The `short' variant lists options used
+ only in the top level, while the `recursive' variant lists options
+ also present in any nested packages.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`--prefix=DIR'
+ Use DIR as the installation prefix. *note Installation Names::
+ for more details, including other options available for fine-tuning
+ the installation locations.
+
+`--no-create'
+`-n'
+ Run the configure checks, but stop before creating any output
+ files.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
View
3 Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = src data
+
+EXTRA_DIST = AUTHORS NEWS README
View
2 NEWS
@@ -0,0 +1,2 @@
+VERSION: 1.0
+ - First official release
View
40 README
@@ -0,0 +1,40 @@
+XFCon
+=====
+
+** INTRO **
+
+ XfCon is a quake-style modular drop down console for XFCE inspired by
+ Yakuake for KDE and Guake for Gnome.
+
+ The primary goal of XfCon is to provide quick access to terminal window
+ and, possibly, other tools.
+
+ TODO: document how to create modules.
+
+** LICENSE **
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+** DEPENDENCIES **
+ python-keybinder
+ python-vte
+ python-xlib
+
+** BUILDING **
+ Standard procedure:
+ - aclocal
+ - autoconf
+ - automake --add-missing
+ - ./configure
+ - make
+ - make install
View
22 configure.ac
@@ -0,0 +1,22 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.68])
+AC_INIT([xfcon], [1.0], [tomasz.wiszkowski@gmail.com])
+AM_INIT_AUTOMAKE
+AC_CONFIG_MACRO_DIR([m4])
+
+m4_pattern_allow([AS_AC_EXPAND])
+
+AC_CONFIG_FILES([Makefile
+ data/Makefile
+ data/pixmaps/Makefile
+ src/Makefile
+ src/constants/Makefile
+ src/elements/Makefile
+ src/plugins/Makefile
+ src/plugins/terminal/Makefile
+ src/plugins/test/Makefile
+ src/plugins/preferences/Makefile
+ ])
+AC_OUTPUT
View
20 data/Makefile.am
@@ -0,0 +1,20 @@
+SUBDIRS = pixmaps
+
+do_subst = sed -e 's,[@]datadir[@],$(datadir),g' \
+ -e 's,[@]libdir[@],$(libdir),g' \
+ -e 's,[@]PACKAGE[@],$(PACKAGE),g' \
+ -e 's,[@]VERSION[@],$(VERSION),g'
+
+in_files = xfcon.desktop
+
+all-local: $(in_files)
+
+desktopdir = $(datadir)/applications
+desktop_DATA = xfcon.desktop
+
+xfcon.desktop: xfcon.desktop.in
+ @$(do_subst) < "$<" > "$@"
+
+EXTRA_DIST = \
+ $(desktop_DATA)
+
View
4 data/pixmaps/Makefile.am
@@ -0,0 +1,4 @@
+pixmapsdir = $(datadir)/pixmaps/@PACKAGE@
+pixmaps_DATA = terminal.png exclam.png
+
+EXTRA_DIST = $(pixmaps_DATA)
View
BIN data/pixmaps/exclam.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN data/pixmaps/terminal.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
11 data/xfcon.desktop.in
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=XfCon Console
+Comment=Pull-Down Console for XFCE
+TryExec=xfcon
+Exec=xfcon
+# Stub icon, I'm no artist.
+Icon=@datadir@/pixmaps/terminal.xpm
+Type=Application
+Categories=XFCE;GTK;Utility;TerminalEmulator;
+StartupNotify=true
View
2 src/.gitignore
@@ -0,0 +1,2 @@
+/guake
+/guake-prefs
View
19 src/Makefile.am
@@ -0,0 +1,19 @@
+SUBDIRS = elements constants plugins
+
+do_subst = sed -e 's,[@]datadir[@],$(datadir),g' \
+ -e 's,[@]libdir[@],$(libdir),g' \
+ -e 's,[@]PACKAGE[@],$(PACKAGE),g' \
+ -e 's,[@]VERSION[@],$(VERSION),g'
+
+xfconbindir = $(bindir)
+xfconbin_SCRIPTS = xfcon
+
+xfconlibdir = $(libdir)/@PACKAGE@
+xfconlib_DATA = xfcon.py xfcon
+
+xfcon: xfcon.in
+ @$(do_subst) < "$<" > "$@"
+
+EXTRA_DIST = \
+ $(xfconbin_SCRIPTS) \
+ $(xfconlib_DATA)
View
5 src/constants/Makefile.am
@@ -0,0 +1,5 @@
+elemsdir = $(libdir)/@PACKAGE@/constants
+elems_SCRIPTS = *.py
+
+EXTRA_DIST = \
+ $(elems_SCRIPTS)
View
15 src/constants/__init__.py
@@ -0,0 +1,15 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
View
1 src/elements/.gitignore
@@ -0,0 +1 @@
+/guake_globals.py
View
16 src/elements/Makefile.am
@@ -0,0 +1,16 @@
+do_subst = sed -e 's,[@]datadir[@],$(datadir),g' \
+ -e 's,[@]libdir[@],$(libdir),g' \
+ -e 's,[@]PACKAGE[@],$(PACKAGE),g' \
+ -e 's,[@]VERSION[@],$(VERSION),g'
+
+python_in_files = xfcon_globals.py
+
+xfcon_globals.py: xfcon_globals.py.in
+ @$(do_subst) < "$<" > "$@"
+
+all-local: $(python_in_files)
+
+elemsdir = $(libdir)/@PACKAGE@/elements
+elems_SCRIPTS = *.py
+
+EXTRA_DIST = $(elems_SCRIPTS)
View
19 src/elements/__init__.py
@@ -0,0 +1,19 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gettext
+from elements.xfcon_globals import PACKAGE, LOCALE_DIR
+
+gettext.install(PACKAGE, LOCALE_DIR)
View
187 src/elements/xfcon_box.py
@@ -0,0 +1,187 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gobject
+import gtk
+from elements.xfcon_object import XfConObject
+
+class XfConBox(XfConObject):
+ def __xfcon_signals(self):
+ return {
+ XfConObject.XFCON_SIGNAL_MENU_BUILD: self.__on_menu_build,
+ XfConObject.XFCON_SIGNAL_MENU_SHOW: self.__on_menu_show,
+ XfConObject.XFCON_SIGNAL_MENU_HIDE: self.__on_menu_hide,
+ XfConObject.XFCON_SIGNAL_VIEW_TERMINATE: self.__on_child_exit,
+ XfConObject.XFCON_SIGNAL_VIEW_SPLIT_HORIZONTAL: self.__on_split_horizontal,
+ XfConObject.XFCON_SIGNAL_VIEW_SPLIT_VERTICAL: self.__on_split_vertical,
+ XfConObject.XFCON_SIGNAL_VIEW_ACTIVATE_NEXT: self.__on_activate_next,
+ XfConObject.XFCON_SIGNAL_VIEW_ACTIVATE_PREVIOUS: self.__on_activate_previous,
+ "focus-in-event": self.__on_focus_in,
+ "focus-out-event": self.__on_focus_out
+ }
+
+ def __init__(self):
+ self.handlers = {}
+ self.current_focus = None
+
+ def __on_split_vertical(self, source, sibling):
+ self.__split(gtk.ORIENTATION_VERTICAL, source, sibling)
+ return True
+
+ def __on_split_horizontal(self, source, sibling):
+ self.__split(gtk.ORIENTATION_HORIZONTAL, source, sibling)
+ return True
+
+ def __on_focus_in(self, source, event):
+ self.emit("focus-in-event", event)
+ self.current_focus = source
+
+ def __on_focus_out(self, source, event):
+ self.emit("focus-out-event", event)
+
+ def __split(self, orientation, child, sibling):
+ child_position = self.child_get_property(child, 'position')
+
+ # if current orientation is not what we need, then create new box
+ if self.get_orientation() == orientation:
+ if orientation == gtk.ORIENTATION_HORIZONTAL:
+ new_box = XfConVBox()
+ else:
+ new_box = XfConHBox()
+
+ # since we're about to remove child from self, we need to unbind signals on it
+ self.remove(child)
+ new_box.pack_start(child)
+ new_box.pack_start(sibling)
+ new_box.show()
+ self.pack_start(new_box)
+ self.reorder_child(new_box, child_position)
+ else:
+ self.pack_start(sibling)
+ self.reorder_child(sibling, child_position + 1)
+
+ def __activate_first(self):
+ if len(self.get_children()) == 0:
+ return False
+
+ child = self.get_children()[0]
+ if isinstance(child, XfConBox):
+ return child.__activate_first()
+ else:
+ child.grab_focus()
+ return True
+
+ def __activate_last(self):
+ if len(self.get_children()) == 0:
+ return False
+
+ child = self.get_children()[-1]
+ if isinstance(child, XfConBox):
+ return child.__activate_last()
+ else:
+ child.grab_focus()
+ return True
+
+ def __on_menu_build(self, source, menu):
+ return self.emit_menu_build(menu)
+
+ def __on_menu_show(self, *args):
+ return self.emit_menu_show()
+
+ def __on_menu_hide(self, *args):
+ return self.emit_menu_hide()
+
+ def _gtk_pack_start(self, target, *args):
+ self.handlers[target] = target.register_callbacks(self.__xfcon_signals())
+ return gtk.Box.pack_start(self, target)
+
+ def _gtk_remove(self, target):
+ target.unregister_callbacks(self.handlers.pop(target))
+ self.__on_activate_previous(target)
+ return gtk.Box.remove(self, target)
+
+ def _gtk_grab_focus(self):
+ if (self.current_focus):
+ self.current_focus.grab_focus()
+ elif self.get_children():
+ self.get_children()[0].grab_focus()
+
+ def __on_child_exit(self, target):
+ self.remove(target)
+ target.destroy()
+ if len(self.get_children()) == 0:
+ self.emit_view_terminate()
+
+ def __on_activate_next(self, source):
+ position = self.child_get_property(source, 'position')
+ children = self.get_children()
+ if position < (len(children) - 1):
+ child = children[position + 1]
+ if isinstance(child, XfConBox):
+ return child.__activate_first()
+ else:
+ child.grab_focus()
+ return True
+ else:
+ if not self.emit_view_activate_next():
+ return self.__activate_first()
+
+ def __on_activate_previous(self, source):
+ position = self.child_get_property(source, 'position')
+ children = self.get_children()
+ if position > 0:
+ child = children[position - 1]
+ if isinstance(child, XfConBox):
+ return child.__activate_last()
+ else:
+ child.grab_focus()
+ return True
+ else:
+ if not self.emit_view_activate_previous():
+ return self.__activate_last()
+
+
+class XfConHBox(gtk.HBox, XfConBox):
+ __gsignals__ = XfConObject.XfConSignals()
+
+ def __init__(self):
+ super(self.__class__, self).__init__(True, True)
+ XfConBox.__init__(self)
+
+ def pack_start(self, target, *args, **kwargs):
+ return self._gtk_pack_start(target, args)
+
+ def remove(self, target):
+ return self._gtk_remove(target)
+
+ def grab_focus(self):
+ return self._gtk_grab_focus()
+
+
+class XfConVBox(gtk.VBox, XfConBox):
+ __gsignals__ = XfConObject.XfConSignals()
+
+ def __init__(self):
+ super(self.__class__, self).__init__(True, True)
+ XfConBox.__init__(self)
+
+ def pack_start(self, target, *args, **kwargs):
+ return self._gtk_pack_start(target, args)
+
+ def remove(self, target):
+ return self._gtk_remove(target)
+
+ def grab_focus(self):
+ return self._gtk_grab_focus()
View
73 src/elements/xfcon_dialogs.py
@@ -0,0 +1,73 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gtk
+from elements.xfcon_globals import *
+from elements.xfcon_utils import pixmapfile
+
+class XfConDialog:
+ parent = None
+
+ @classmethod
+ def init(cls, parent):
+ cls.__parent = parent
+
+ @classmethod
+ def question_yes_no(cls, first_label, second_label):
+ md = gtk.MessageDialog(cls.__parent,
+ gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION,
+ gtk.BUTTONS_YES_NO, first_label)
+ md.set_markup(first_label)
+ md.format_secondary_markup(second_label)
+ md.set_title(_("XfCon"))
+ response = md.run()
+ md.destroy()
+ return response == gtk.RESPONSE_YES
+
+ @classmethod
+ def warning_yes_no(cls, first_label, second_label):
+ md = gtk.MessageDialog(cls.__parent,
+ gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING,
+ gtk.BUTTONS_YES_NO, first_label)
+ md.set_markup(first_label)
+ md.format_secondary_markup(second_label)
+ md.set_title(_("XfCon"))
+ response = md.run()
+ md.destroy()
+ return response == gtk.RESPONSE_YES
+
+ @classmethod
+ def error_close(cls, first_label, second_label):
+ md = gtk.MessageDialog(cls.__parent,
+ gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR,
+ gtk.BUTTONS_CLOSE, first_label)
+ md.set_markup(first_label)
+ md.format_secondary_markup(second_label)
+ md.set_title(_("XfCon"))
+ md.run()
+ md.destroy()
+
+ @classmethod
+ def about(cls):
+ md = gtk.AboutDialog()
+ md.set_program_name(APPNAME)
+ md.set_version(VERSION)
+ md.set_copyright("(C) 2012 Tomasz <error> Wiszkowski")
+ md.set_comments(_("Guake and Yakuake inspired pull-down console for XFCE"))
+ md.set_website(WEBSITE)
+ md.set_logo(gtk.gdk.pixbuf_new_from_file(pixmapfile('terminal.png')))
+ md.run()
+ md.destroy()
+
View
10 src/elements/xfcon_globals.py.in
@@ -0,0 +1,10 @@
+APPNAME = "XfCon#"
+VERSION = '@VERSION@'
+WEBSITE = "http://www.not-yet.com"
+
+# Locations on disk.
+PACKAGE = '@PACKAGE@'
+IMAGE_DIR = '@datadir@/pixmaps/@PACKAGE@'
+LOCALE_DIR = '@datadir@/locale'
+PLUGINS_DIR = '@libdir@/@PACKAGE@/plugins'
+
View
192 src/elements/xfcon_notebook.py
@@ -0,0 +1,192 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gtk
+import gobject
+from elements.xfcon_utils import pixmapfile, XfConKeyBinder
+from elements.xfcon_object import XfConObject
+from elements.xfcon_notebook_label import XfConNotebookLabel
+from elements.xfcon_settings import XfConSettings
+
+class XfConNotebook(gtk.Notebook, XfConObject):
+ XFCON_SIGNAL_BUILD_DEFAULT_VIEW = "xfcon-build-default-view"
+
+ __gsignals__ = XfConObject.XfConSignals({
+ XFCON_SIGNAL_BUILD_DEFAULT_VIEW: (gobject.SIGNAL_ACTION, gobject.TYPE_OBJECT, ())
+ })
+
+ def __xfcon_label_signals(self):
+ return {
+ XfConObject.XFCON_SIGNAL_MENU_BUILD: self.__on_label_menu_build,
+ XfConObject.XFCON_SIGNAL_MENU_SHOW: self.__on_menu_show,
+ XfConObject.XFCON_SIGNAL_MENU_HIDE: self.__on_menu_hide,
+ XfConObject.XFCON_SIGNAL_VIEW_TERMINATE: self.__on_label_child_exit,
+ }
+
+ def __xfcon_page_signals(self):
+ return {
+ XfConObject.XFCON_SIGNAL_MENU_BUILD: self.__on_menu_build,
+ XfConObject.XFCON_SIGNAL_MENU_SHOW: self.__on_menu_show,
+ XfConObject.XFCON_SIGNAL_MENU_HIDE: self.__on_menu_hide,
+ XfConObject.XFCON_SIGNAL_VIEW_TERMINATE: self.__on_child_exit,
+ 'expose-event': self.__on_page_exposed,
+ }
+
+ def __init__(self):
+ super(self.__class__, self).__init__()
+ self.settings = XfConSettings()
+ self.add_tab_image = gtk.image_new_from_stock(gtk.STOCK_NEW, gtk.ICON_SIZE_SMALL_TOOLBAR)
+ self.add_tab_page = gtk.Label("*")
+ self.add_tab_page.show()
+ self.menu_source = None
+ super(self.__class__, self).append_page(self.add_tab_page, self.add_tab_image)
+ self.__bind_signals()
+ self.__bind_keys()
+ self.set_can_focus(True)
+ self.set_tab_pos(gtk.POS_BOTTOM)
+ self.set_show_border(False)
+ self.popup_disable()
+ self.show()
+
+ def __bind_keys(self):
+ XfConKeyBinder.register(self, [
+ (self.settings.get_property('key-notebook-tab-rename'),
+ self.__on_accel_tab_rename),
+ (self.settings.get_property('key-notebook-tab-close'),
+ self.__on_accel_tab_delete),
+ (self.settings.get_property('key-notebook-tab-next'),
+ self.__on_accel_tab_previous),
+ (self.settings.get_property('key-notebook-tab-previous'),
+ self.__on_accel_tab_next),
+ ])
+
+ def __bind_signals(self):
+ self.add_tab_page.connect("expose-event", self.__on_after_switch)
+ self.connect("page-reordered", self.__on_page_reordered)
+
+ def __on_page_reordered(self, source, page, pos, *ignore):
+ if pos == self.get_n_pages():
+ self.reorder_child(page, pos - 1)
+
+ def __on_child_exit(self, child):
+ self.remove(child)
+
+ def __on_accel_tab_rename(self, *ignore):
+ index = self.get_current_page()
+ page = self.get_nth_page(index)
+ label = self.get_tab_label(page)
+ label.show_rename()
+
+ def __on_accel_tab_previous(self, *args):
+ self.prev_page()
+ return True
+
+ def __on_accel_tab_next(self, *args):
+ self.next_page()
+ return True
+
+ def __on_accel_tab_delete(self, *args):
+ '''
+ Destroys active tab.
+ '''
+ child = self.get_current_page()
+ child = self.get_nth_page(self.get_current_page())
+ self.remove(child)
+ child.destroy()
+
+ def __on_after_switch(self, *ignore):
+ page = self.emit(XfConNotebook.XFCON_SIGNAL_BUILD_DEFAULT_VIEW)
+ if page:
+ self.append_page(page)
+ self.prev_page()
+
+ def __on_menu_build(self, source, menu):
+ self.emit_menu_build(menu)
+
+ def __on_menu_show(self, source):
+ self.menu_source = source
+ self.emit_menu_show()
+
+ def __on_menu_hide(self, source):
+ self.emit_menu_hide()
+
+ def __on_close_tab(self, *ignore):
+ self.__on_label_child_exit(self.menu_source)
+
+ def __on_label_menu_build(self, source, menu):
+ if len(menu.get_children()):
+ separator = gtk.SeparatorMenuItem()
+ separator.show()
+ menu.add(separator)
+
+ item = gtk.ImageMenuItem(gtk.STOCK_CLOSE, True)
+ item.set_label(_("Close Tab"))
+ item.show()
+ item.connect('activate', self.__on_close_tab)
+ menu.add(item)
+
+ def __on_label_child_exit(self, source):
+ for child in self.get_children():
+ label = self.get_tab_label(child)
+ if label == source:
+ self.remove(child)
+ return
+
+ def __on_page_exposed(self, target, *args):
+ index = self.get_current_page()
+ page = self.get_nth_page(index)
+ label = self.get_tab_label(page)
+ if not label.editing():
+ target.grab_focus()
+
+ def get_n_pages(self):
+ count = super(self.__class__, self).get_n_pages()
+ return count - 1
+
+ def append_page(self, page):
+ label_text = _("XfCon #{num_pages}").format(num_pages=self.get_n_pages() + 1)
+ label = XfConNotebookLabel(label_text)
+ label.register_callbacks(self.__xfcon_label_signals())
+
+ index = self.get_n_pages()
+ super(self.__class__, self).insert_page(child=page, tab_label=label, position=index)
+ page.register_callbacks(self.__xfcon_page_signals())
+ self.set_tab_reorderable(page, True)
+ return index
+
+ def prev_page(self):
+ '''
+ Activate previous tab.
+ '''
+ if self.get_current_page() == 0:
+ self.set_current_page(self.get_n_pages() - 1)
+ else:
+ super(XfConNotebook, self).prev_page()
+
+ def next_page(self):
+ '''
+ Activate next tab.
+ '''
+ if self.get_current_page() + 1 == self.get_n_pages():
+ self.set_current_page(0)
+ else:
+ super(XfConNotebook, self).next_page()
+
+ def remove(self, object):
+ page = self.get_current_page()
+ if (page > 0) and (page == self.get_n_pages() - 1) and self.get_nth_page(page) == object:
+ self.set_current_page(page - 1)
+ super(XfConNotebook, self).remove(object)
+
View
149 src/elements/xfcon_notebook_label.py
@@ -0,0 +1,149 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+from elements.xfcon_object import XfConObject
+from elements.xfcon_utils import pixmapfile
+import gtk
+import gobject
+
+class XfConNotebookLabel(gtk.VBox, XfConObject):
+ __gsignals__ = XfConObject.XfConSignals()
+
+ def __init__(self, name, icon = None):
+ super(self.__class__, self).__init__()
+
+ self.accel_group = gtk.AccelGroup()
+
+ self.main_box = gtk.HBox(False)
+ self.main_box.show()
+
+ if (icon == None):
+ icon = pixmapfile('terminal.png')
+ pixbuf = gtk.gdk.pixbuf_new_from_file(icon)
+ pixbuf = pixbuf.scale_simple(20, 20, gtk.gdk.INTERP_BILINEAR)
+ self.icon = gtk.Image()
+ self.icon.set_from_pixbuf(pixbuf)
+ self.icon.show()
+
+ self.label = gtk.Label()
+ self.label.show()
+
+ label_box = gtk.HBox(False, False)
+ label_box.set_spacing(10)
+ label_box.pack_start(self.icon, True, True)
+ label_box.pack_end(self.label, True, True)
+ label_box.show()
+
+ self.event_label = gtk.EventBox()
+ self.event_label.add(label_box)
+ self.event_label.connect('button-press-event', self.__on_tab_menu)
+ self.event_label.set_visible_window(False)
+ self.event_label.show()
+
+ self.image = gtk.Image()
+ self.image.set_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU)
+ self.image.show()
+ self.event_image = gtk.EventBox()
+ self.event_image.add(self.image)
+ self.event_image.set_visible_window(False)
+ self.event_image.connect('button-press-event', self.__on_tab_close)
+ self.event_image.set_visible_window(False)
+ self.event_image.show()
+
+ self.main_box.pack_start(self.event_label, True, True)
+ self.main_box.pack_end(self.event_image, True, True)
+
+ self.edit_box = gtk.Entry()
+ self.edit_box.hide()
+ self.edit_box.connect('focus-out-event', self.__on_show_main)
+ self.edit_box.connect('activate', self.__on_new_name)
+
+ self.set_text(name)
+ self.pack_start(self.main_box, True, True)
+ self.pack_end(self.edit_box, True, True)
+
+ self.__on_show_main()
+ self.pinned = False
+
+ self.show()
+
+ def __on_menu_close(self, source):
+ self.emit_menu_hide()
+
+ def __build_menu(self):
+ menu = gtk.Menu()
+ menu.connect("selection-done", self.__on_menu_close)
+
+ if (self.pinned):
+ item = gtk.ImageMenuItem(gtk.STOCK_REMOVE, True)
+ item.set_label(_("Unpin Tab"))
+ item.connect('activate', self.__on_unpin_tab)
+ else:
+ item = gtk.ImageMenuItem(gtk.STOCK_ADD, True)
+ item.set_label(_("Pin Tab"))
+ item.connect('activate', self.__on_pin_tab)
+ item.show()
+ menu.add(item)
+
+ self.emit_menu_build(menu)
+ return menu
+
+ def __on_pin_tab(self, *ignore):
+ self.label.hide()
+ self.event_image.hide()
+ self.pinned = True
+
+ def __on_unpin_tab(self, *ignore):
+ self.label.show()
+ self.event_image.show()
+ self.pinned = False
+
+ def __on_tab_menu(self, source, event):
+ if event.button == 3:
+ menu = self.__build_menu()
+ self.context_menu_visible = True
+ self.emit_menu_show()
+ menu.popup(None, None, None, 3, event.get_time())
+
+ def __on_tab_close(self, source, event):
+ if event.button == 1:
+ self.emit_view_terminate()
+
+ def __on_show_main(self, *args):
+ self.edit_box.set_sensitive(False)
+ self.edit_box.hide()
+ self.main_box.show()
+
+ def __on_new_name(self, *args):
+ text = self.edit_box.get_text()
+ self.label.set_text(text)
+ self.__on_show_main()
+
+ def show_rename(self):
+ self.edit_box.set_sensitive(True)
+ self.main_box.hide()
+ self.edit_box.show()
+ self.edit_box.grab_focus()
+
+ def get_text(self):
+ return self.label.get_text()
+
+ def set_text(self, text):
+ self.label.set_text(text)
+ self.edit_box.set_text(text)
+
+ def editing(self):
+ return self.edit_box.get_visible()
+
View
192 src/elements/xfcon_object.py
@@ -0,0 +1,192 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gobject
+
+class XfConObject:
+
+ '''
+ Common abstraction of all XfCon objects.
+
+ Every object that wants to be a child of XfCon should at very least
+ be a child of both XfConObject and gtk.Widget.
+ '''
+ XFCON_SIGNAL_VIEW_CREATE = "xfcon-view-create"
+ '''
+ Emitted, when an object wishes to add a new tab.
+
+ Parameters:
+ * object - a new object that will be put on a new tab page.
+ '''
+
+ XFCON_SIGNAL_VIEW_TERMINATE = "xfcon-view-terminate"
+ '''
+ Emitted, when an object has terminated work and wishes to be removed.
+ '''
+
+ XFCON_SIGNAL_MENU_BUILD = "xfcon-menu-build"
+ '''
+ Emitted, when an object wants to populate menu from ancestors.
+
+ Parameters:
+ * menu - an initially prebuilt menu structure.
+ '''
+
+ XFCON_SIGNAL_MENU_SHOW = "xfcon-menu-show"
+ '''
+ Emitted, when an object is about to expose menu.
+ '''
+
+ XFCON_SIGNAL_MENU_HIDE = "xfcon-menu-hide"
+ '''
+ Emitted, when an object has just shut down the menu.
+ '''
+
+ XFCON_SIGNAL_VIEW_SPLIT_VERTICAL = "xfcon-view-split-vertical"
+ '''
+ Emitted, when an object wants to perform a vertical split on self.
+
+ Parameters:
+ * sibling - object, that will be presented below originator of this signal.
+ '''
+
+ XFCON_SIGNAL_VIEW_SPLIT_HORIZONTAL = "xfcon-view-split-horizontal"
+ '''
+ Emitted, when an object wants to perform a horizontal split on self.
+
+ Parameters:
+ * sibling - object, that will be presented to the right of originator of this signal.
+ '''
+
+ XFCON_SIGNAL_VIEW_ACTIVATE_NEXT = "xfcon-view-activate-next"
+ '''
+ Emitted, when an object wishes to pass focus to the next object in chain.
+
+ Return: BOOL indicating whether activation was possible, or object reached last item in chain.
+ '''
+
+ XFCON_SIGNAL_VIEW_ACTIVATE_PREVIOUS = "xfcon-view-activate-previous"
+ '''
+ Emitted, when an object wishes to pass focus to the previous object in chain.
+
+ Return: BOOL indicating whether activation was possible, or object reached first item in chain.
+ '''
+
+ @classmethod
+ def XfConSignals(cls, other = {}):
+ '''
+ List of signals that should be supported by all XfCon views.
+
+ To use it, simply declare it as follows in your class:
+
+ class MyFancyView(gtk.SomeObject, XfConObject):
+ __signals__ = XfConObject.XfConSignals()
+ '''
+ signals = dict({
+ XfConObject.XFCON_SIGNAL_MENU_BUILD:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)),
+ XfConObject.XFCON_SIGNAL_MENU_SHOW:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ()),
+ XfConObject.XFCON_SIGNAL_MENU_HIDE:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ()),
+ XfConObject.XFCON_SIGNAL_VIEW_CREATE:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)),
+ XfConObject.XFCON_SIGNAL_VIEW_TERMINATE:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ()),
+ XfConObject.XFCON_SIGNAL_VIEW_SPLIT_HORIZONTAL:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_BOOLEAN, (gobject.TYPE_OBJECT,)),
+ XfConObject.XFCON_SIGNAL_VIEW_SPLIT_VERTICAL:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_BOOLEAN, (gobject.TYPE_OBJECT,)),
+ XfConObject.XFCON_SIGNAL_VIEW_ACTIVATE_NEXT:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_BOOLEAN, ()),
+ XfConObject.XFCON_SIGNAL_VIEW_ACTIVATE_PREVIOUS:
+ (gobject.SIGNAL_ACTION, gobject.TYPE_BOOLEAN, ())
+ }, **other)
+ return signals;
+
+ def emit_menu_build(self, menu = None):
+ '''
+ Emit menu population signal.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_MENU_BUILD, menu)
+
+ def emit_menu_show(self):
+ '''
+ Emit menu show signal.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_MENU_SHOW)
+
+ def emit_menu_hide(self):
+ '''
+ Emit menu hide signal.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_MENU_HIDE)
+
+ def emit_view_create(self, view = None):
+ '''
+ Emit request to add a new tab.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_VIEW_CREATE, view)
+
+ def emit_view_terminate(self):
+ '''
+ Emit view terminate signal, to indicate that your job is now complete.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_VIEW_TERMINATE)
+
+ def emit_view_split_horizontal(self, sibling = None):
+ '''
+ Emit horizontal split request.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_VIEW_SPLIT_HORIZONTAL, sibling)
+
+ def emit_view_split_vertical(self, sibling = None):
+ '''
+ Emit vertical split request.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_VIEW_SPLIT_VERTICAL, sibling)
+
+ def emit_view_activate_next(self):
+ '''
+ Emit request to activate next view.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_VIEW_ACTIVATE_NEXT)
+
+ def emit_view_activate_previous(self):
+ '''
+ Emit request to activate previous view.
+ '''
+ return self.emit(XfConObject.XFCON_SIGNAL_VIEW_ACTIVATE_PREVIOUS)
+
+ def register_callbacks(self, signals):
+ '''
+ Called by any class that is interested in receiving events from this
+ object to register callbacks.
+
+ Return: dict of bound signals. Use it to unregister your class, once no longer required.
+ '''
+ handlers = {}
+ for key in signals.keys():
+ if gobject.signal_lookup(key, self.__class__):
+ handlers[key] = self.connect(key, signals[key])
+ return handlers
+
+ def unregister_callbacks(self, handlers):
+ '''
+ Unregisters previously registered callbacks.
+ '''
+ for handler in handlers.values():
+ self.disconnect(handler)
+
View
117 src/elements/xfcon_settings.py
@@ -0,0 +1,117 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gobject
+
+class XfConSettings(gobject.GObject):
+ __gproperties__ = {
+ 'key-show-hide' : (gobject.TYPE_STRING,
+ _("Shows / hides the console."),
+ _("Keyboard shortcut"),
+ "Pause",
+ gobject.PARAM_READWRITE),
+
+ 'key-quit' : (gobject.TYPE_STRING,
+ _("Quit XfCon."),
+ _("Keyboard shortcut"),
+ "<Control><Shift>q",
+ gobject.PARAM_READWRITE),
+
+ 'key-new-tab' : (gobject.TYPE_STRING,
+ _("Open new tab with default view."),
+ _("Keyboard shortcut"),
+ "<Control><Shift>t",
+ gobject.PARAM_READWRITE),
+
+ 'key-notebook-tab-close' : (gobject.TYPE_STRING,
+ _("Close current tab."),
+ _("Keyboard shortcut"),
+ "<Control><Shift>w",
+ gobject.PARAM_READWRITE),
+
+ 'key-notebook-tab-rename' : (gobject.TYPE_STRING,
+ _("Rename current tab."),
+ _("Keyboard shortcut"),
+ "<Control><Shift>r",
+ gobject.PARAM_READWRITE),
+
+ 'key-notebook-tab-next' : (gobject.TYPE_STRING,
+ _("Jump to next tab."),
+ _("Keyboard shortcut"),
+ "<Control>Page_Up",
+ gobject.PARAM_READWRITE),
+
+ 'key-notebook-tab-previous' : (gobject.TYPE_STRING,
+ _("Jump to previous tab."),
+ _("Keyboard shortcut"),
+ "<Control>Page_Down",
+ gobject.PARAM_READWRITE),
+
+ 'key-view-split-vertical' : (gobject.TYPE_STRING,
+ _("Split view vertically."),
+ _("Keyboard shortcut"),
+ "<Control><Alt>v",
+ gobject.PARAM_READWRITE),
+
+ 'key-view-split-horizontal' : (gobject.TYPE_STRING,
+ _("Split view horizontally."),
+ _("Keyboard shortcut"),
+ "<Control><Alt>h",
+ gobject.PARAM_READWRITE),
+
+ 'key-view-activate-next' : (gobject.TYPE_STRING,
+ _("Activate next view in split."),
+ _("Keyboard shortcut"),
+ "<Control><Alt>Right",
+ gobject.PARAM_READWRITE),
+
+ 'key-view-activate-previous' : (gobject.TYPE_STRING,
+ _("Activate previous view in split."),
+ _("Keyboard shortcut"),
+ "<Control><Alt>Left",
+ gobject.PARAM_READWRITE),
+
+ 'key-clipboard-copy' : (gobject.TYPE_STRING,
+ _("Copy selection to clipboard."),
+ _("Keyboard shortcut"),
+ "<Control><Shift>c",
+ gobject.PARAM_READWRITE),
+
+ 'key-clipboard-paste' : (gobject.TYPE_STRING,
+ _("Paste clipboard contents."),
+ _("Keyboard shortcut"),
+ "<Control><Shift>v",
+ gobject.PARAM_READWRITE),
+
+ 'window-height': (gobject.TYPE_UINT,
+ _("Window height."),
+ _("Percentage of screen occupied by window."),
+ 10, 100, 80,
+ gobject.PARAM_READWRITE),
+ }
+
+ __properties__ = {}
+
+ def __init__(self):
+ super(XfConSettings, self).__init__()
+ for prop in gobject.list_properties(XfConSettings):
+ self.__properties__[prop.name] = prop.default_value
+
+ def do_get_property(self, name):
+ return self.__properties__[name.name]
+
+ def do_set_property(self, name, value):
+ self.__properties__[name.name] = value
+
View
128 src/elements/xfcon_utils.py
@@ -0,0 +1,128 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gtk
+import keybinder
+import os
+import pygtk
+import pynotify
+from elements.xfcon_globals import APPNAME, IMAGE_DIR
+
+def pixmapfile(x):
+ f = os.path.join(IMAGE_DIR, x)
+ if not os.path.exists(f):
+ raise IOError('No such file or directory: %s' % f)
+ return os.path.abspath(f)
+
+class XfConKeyBinder(gtk.AccelGroup):
+ # Singleton object.
+ # Every class registers here upon import. The goal is to deliver all the configurable keys
+ # to one place.
+ this = None
+
+ def __init__(self):
+ # Initialize this accel group
+ super(self.__class__, self).__init__()
+
+ self.groups = {}
+ def __load_accelerators(self, group):
+ result = True
+ for accel in self.groups[group]:
+ result = result and self.__bind(accel)
+ return result
+
+ def __unbind(self, accelerator):
+ if accelerator['hotkey'] == None:
+ return
+ if accelerator['global']:
+ keybinder.unbind(accelerator['hotkey'])
+ else:
+ self.disconnect_key(accelerator['hotkey'], accelerator['hotmask'])
+ accelerator['hotkey'] = None
+ accelerator['hotmask'] = None
+
+ def __bind(self, accelerator):
+ result = True
+ self.__unbind(accelerator)
+
+ if accelerator['global']:
+ result = keybinder.bind(
+ accelerator['key'], accelerator['function'], None)
+ else:
+ key, mask = gtk.accelerator_parse(accelerator['key'])
+ if key > 0:
+ self.connect_group(key, mask, gtk.ACCEL_VISIBLE, accelerator['function'])
+ accelerator['hotkey'] = key
+ accelerator['hotmask'] = mask
+
+ if not result:
+ self.__notify_key_register_failed(
+ _("Could not bind shortcut (most likely already taken).", key))
+ return result
+
+ def __unregister(self, name):
+ if not self.groups.has_key(name):
+ return
+ accelerators = self.groups.pop(name)
+ for accelerator in accelerators:
+ self.__unbind(accelerator)
+
+ def __notify_key_register_failed(self, reason, label):
+ filename = pixmapfile('exclam.png')
+ notification = pynotify.Notification(
+ _(APPNAME),
+ _('Failed to bind key <b>%s</b>.\n'
+ '%s'
+ 'Please adjust your key mapping.') % (label, reason), filename)
+ notification.show()
+
+ def __register(self, name, accels, glob=False):
+ accellist = []
+
+ if self.groups.has_key(name):
+ self.__notify_key_register_failed(
+ _("This group of shortcuts is already registered"), name)
+ return False
+
+ for pair in accels:
+ per_accel = {
+ 'key': pair[0],
+ 'function': pair[1],
+ 'global':glob,
+ 'hotkey':None,
+ 'hotmask':None }
+ accellist.append(per_accel)
+
+ self.groups[name] = accellist
+ return self.__load_accelerators(name)
+
+ @classmethod
+ def register(cls, groupname, accelerators):
+ return XfConKeyBinder.this.__register(groupname, accelerators)
+
+ @classmethod
+ def register_global(cls, groupname, accelerators):
+ return XfConKeyBinder.this.__register(groupname, accelerators, True)
+
+ @classmethod
+ def unregister(cls, groupname):
+ XfConKeyBinder.this.__unregister(groupname)
+
+ @classmethod
+ def create(cls):
+ if (cls.this is None):
+ cls.this = XfConKeyBinder()
+ return cls.this
+
View
261 src/elements/xfcon_window.py
@@ -0,0 +1,261 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gtk
+import os
+import pygtk
+import pynotify
+
+from elements.xfcon_dialogs import XfConDialog
+from elements.xfcon_globals import PLUGINS_DIR, APPNAME
+from elements.xfcon_notebook import XfConNotebook
+from elements.xfcon_object import XfConObject
+from elements.xfcon_settings import XfConSettings
+from elements.xfcon_utils import pixmapfile, XfConKeyBinder
+pygtk.require('2.0')
+
+class XfConWindow(gtk.Window):
+ def __init__(self):
+ super(XfConWindow, self).__init__()
+
+ XfConDialog.init(self)
+
+ self.settings = XfConSettings()
+
+ self.activate()
+ self.set_decorated(False)
+ self.set_gravity(gtk.gdk.GRAVITY_STATIC)
+ self.set_keep_above(True)
+ self.set_skip_pager_hint(True)
+ self.set_skip_taskbar_hint(True)
+ self.set_title(APPNAME)
+ self.set_urgency_hint(True)
+ self.set_resizable(False)
+ self.add_accel_group(XfConKeyBinder.create())
+
+ self.notebook = XfConNotebook()
+ self.notebook.connect(XfConObject.XFCON_SIGNAL_MENU_BUILD, self.__on_menu_build)
+ self.notebook.connect(XfConObject.XFCON_SIGNAL_MENU_SHOW, self.__on_menu_show)
+ self.notebook.connect(XfConObject.XFCON_SIGNAL_MENU_HIDE, self.__on_menu_hide)
+ self.add(self.notebook)
+
+ # trayicon!
+ # TODO(error): make a nice definition out of this.
+ # Can't see the tray icon on awesome. why's that?
+ img = pixmapfile('terminal.png')
+ self.tray_icon = gtk.status_icon_new_from_file(img)
+ self.tray_icon.set_tooltip(APPNAME)
+ self.tray_icon.set_visible(True)
+ self.tray_icon.connect('popup-menu', self.__on_accel_show_hide)
+ self.tray_icon.connect('activate', self.__on_accel_show_hide)
+
+ self.connect('delete-event', self.__on_destroy)
+ self.connect('set-focus', self.__on_focus_move)
+
+ self.last_focus = None
+
+ self.__import_plugins();
+ self.__bind_config()
+ self.__bind_keys()
+ self.__apply_config()
+ self.__show_start_notification()
+
+ def __show_start_notification(self):
+ # Pop-up that shows that XfCon is working properly (if not
+ # unset in the preferences windows)
+ filename = pixmapfile('exclam.png')
+ label = self.settings.get_property('key-show-hide')
+ notification = pynotify.Notification(
+ APPNAME,
+ _('XfCon is now running,\n'
+ 'press <b>%s</b> to use it.') % label, filename)
+ notification.show()
+
+ def __import_plugins(self):
+ self.module_names = [ filename for filename in \
+ os.listdir(PLUGINS_DIR) if os.path.isdir(PLUGINS_DIR+"/"+filename) ]
+ self.plugins = {}
+ for module_name in self.module_names:
+ module = __import__('plugins.' + module_name + '.plugin', fromlist=['Plugin'])
+ plugin = module.Plugin(self)
+ self.plugins[module_name] = plugin
+ if plugin.is_default():
+ # TODO(ender) fix this.
+ self.default_plugin = plugin
+
+ def __bind_config(self):
+ self.settings.connect('notify::window-height', self.__config_set_window_height)
+ self.notebook.connect(XfConNotebook.XFCON_SIGNAL_BUILD_DEFAULT_VIEW, self.__on_tab_add)
+
+ def __bind_keys(self):
+ XfConKeyBinder.register(self, [
+ (self.settings.get_property('key-quit'),
+ self.__on_accel_quit),
+ (self.settings.get_property('key-new-tab'),
+ self.__on_accel_tab_create)
+ ])
+
+ XfConKeyBinder.register_global("XfCon Global",
+ [ (self.settings.get_property('key-show-hide'),
+ self.__on_accel_show_hide) ])
+
+ def __apply_config(self):
+ self.__config_set_window_height()
+
+ def __config_set_window_height(self, *ignore):
+ rect = self.__calculate_window_size()
+ self.move(rect.x, rect.y)
+ self.resize(rect.width, rect.height)
+
+ def __on_tab_add(self, *ignore):
+ return self.__do_create_default_view()
+
+ def __on_destroy(self, *args):
+ self.hide()
+ return True
+
+ def __on_focus_move(self, window, widget):
+ self.last_focus = widget
+
+ def __on_about_show(self, *args):
+ # TODO(error) implement.
+ for plugin in self.plugins.values():
+ view = plugin.on_about_create()
+ # TODO(error) ATTACH!
+ XfConDialog.about()
+
+ def __on_menu_build(self, source, menu):
+ '''
+ Constructs user menu.
+ '''
+ separator = gtk.SeparatorMenuItem()
+ separator.show()
+ menu.add(separator)
+ for plugin in self.plugins.values():
+ plugin.on_menu_build(menu)
+ separator = gtk.SeparatorMenuItem()
+ separator.show()
+ menu.add(separator)
+
+ item = gtk.ImageMenuItem(gtk.STOCK_CLOSE, True)
+ item.set_label(_("Close Tab"))
+ item.show()
+ item.connect('activate', self.__on_accel_tab_delete)
+ menu.add(item)
+
+ item = gtk.ImageMenuItem(gtk.STOCK_ABOUT, True)
+ item.set_label(_("About"))
+ item.show()
+ item.connect('activate', self.__on_about_show)
+ menu.add(item)
+
+ item = gtk.ImageMenuItem(gtk.STOCK_QUIT, True)
+ item.set_label(_("Quit"))
+ item.show()
+ item.connect('activate', self.__on_accel_quit)
+ menu.add(item)
+
+ def __on_menu_show(self, *args):
+ for plugin in self.plugins.values():
+ plugin.on_menu_show()
+
+ def __on_menu_hide(self, *args):
+ for plugin in self.plugins.values():
+ plugin.on_menu_hide()
+
+ def __calculate_window_size(self):
+ screen = self.get_screen()
+ height = self.settings.get_property('window-height')
+ rect = screen.get_monitor_geometry(0)
+ rect.x = 0
+ rect.y = 0
+ rect.height = rect.height * height / 100
+ return rect
+
+ def __on_accel_show_hide(self, *args):
+ if not self.get_property('visible'):
+ self.show()
+ else:
+ self.hide()
+ return True
+
+ def __on_accel_quit(self, *args):
+ wants_quit = XfConDialog.question_yes_no(
+ _("Are you sure to quit?"),
+ _("All running processes will be killed."))
+ if wants_quit:
+ gtk.main_quit()
+ return True
+
+ def __on_accel_tab_create(self, *args):
+ self.create_tab()
+ return True
+
+ def __on_accel_tab_delete(self, *args):
+ self.delete_tab()
+ return True
+
+ def __do_create_default_view(self, directory=None, command=None):
+ default_box = self.default_plugin.on_view_create()
+ return default_box
+
+###############################################################################
+
+ def create_tab(self, child=None):
+ container = child or self.__do_create_default_view()
+ index = self.notebook.append_page(container)
+ self.notebook.set_current_page(index)
+
+ def delete_tab(self, pagepos= -1):
+ if (pagepos == -1):
+ pagepos = self.notebook.get_current_page()
+
+ child = self.notebook.get_nth_page(pagepos)
+ self.notebook.remove_page(pagepos)
+ child.destroy()
+
+ def save_focus(self):
+ self.last_focus = self.get_focus()
+
+ def restore_focus(self):
+ self.set_focus(self.last_focus)
+
+ def show(self):
+ # setting window in all desktops
+ self.stick()
+
+ for plugin in self.plugins.values():
+ plugin.on_show()
+
+ # if we reposition window before showing it, it will be again repositioned
+ # to respect panels position once shown. we don't want this, although it would
+ # be nice to expose panels later
+ # http://stackoverflow.com/questions/502282
+ rect = self.__calculate_window_size()
+ self.show_all()
+ self.move(rect.x, rect.y)
+ self.set_geometry_hints(self,
+ min_width = rect.width, min_height = rect.height,
+ max_width = rect.width, max_height = rect.height,
+ base_width = rect.width, base_height = rect.height)
+ self.restore_focus()
+
+ def hide(self):
+ self.save_focus()
+ for plugin in self.plugins.values():
+ plugin.on_hide()
+ super(self.__class__, self).hide()
+
+
View
6 src/plugins/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = test terminal preferences
+plugsdir = $(libdir)/@PACKAGE@/plugins
+plugs_SCRIPTS = *.py
+
+EXTRA_DIST = \
+ $(plugs_SCRIPTS)
View
16 src/plugins/__init__.py
@@ -0,0 +1,16 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
View
80 src/plugins/interfaces.py
@@ -0,0 +1,80 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+class XfConPlugin(object):
+
+ def on_menu_create(self, menu):
+ '''
+ Called when XfCon begins populating menu entries.
+ '''
+ pass
+
+ def on_menu_show(self):
+ '''
+ Called when XfCon menu was shown.
+ '''
+ pass
+
+ def on_menu_hide(self):
+ '''
+ Called when XfCon menu was hidden.
+ '''
+ pass
+
+ def on_show(self):
+ '''
+ Called when XfCon window has just shown up.
+ '''
+ pass
+
+ def on_hide(self):
+ '''
+ Called when XfCon window is about to hide.
+ '''
+ pass
+
+ def on_about_create(self):
+ '''
+ Creates a new view that should be attached to about window.
+ '''
+ return None
+
+ def on_view_create(self):
+ '''
+ Creates new instance of UI object that will be presented to the user.
+ '''
+ return None
+
+ def on_prefs_create(self, *ignore):
+ '''
+ Creates a new preference tab for this particular plugin.
+ '''
+ return None
+
+ def is_default(self):
+ '''
+ Indicates, whether plugin should be a default plugin.
+
+ This function will return True, if this plugin should be the default for the system.
+ Don't get too attached to it, it's going to be gone soon.
+ '''
+ # TODO(ender) fix this.
+ return False
+
+
+class XfConObject(object):
+ def __init__(self):
+ pass
+
View
5 src/plugins/preferences/Makefile.am
@@ -0,0 +1,5 @@
+plugsdir = $(libdir)/@PACKAGE@/plugins/preferences
+plugs_SCRIPTS = *.py
+
+EXTRA_DIST = \
+ $(plugs_SCRIPTS)
View
16 src/plugins/preferences/__init__.py
@@ -0,0 +1,16 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
View
37 src/plugins/preferences/plugin.py
@@ -0,0 +1,37 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gtk
+from plugins.interfaces import XfConPlugin
+from view import PreferencesView
+
+class Plugin(XfConPlugin):
+ def __init__(self, xfcon_handle):
+ super(Plugin, self).__init__()
+ self.xfcon_handle = xfcon_handle
+
+ def on_menu_build(self, menu):
+ item = gtk.ImageMenuItem(gtk.STOCK_EXECUTE, True)
+ item.set_label("Preferences");
+ item.show()
+ item.connect('activate', self.__create_view)
+ menu.add(item)
+
+ def __create_view(self, *args):
+ self.xfcon_handle.create_tab(PreferencesView())
+
+ def on_view_create(self):
+ return PreferencesView()
+
View
30 src/plugins/preferences/view.py
@@ -0,0 +1,30 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+import gobject
+import gtk
+from elements.xfcon_object import XfConObject
+
+class PreferencesView(gtk.HBox, XfConObject):
+ __signals__ = XfConObject.XfConSignals()
+
+ def __init__(self):
+ super(PreferencesView, self).__init__(True, True)
+
+ self.label = gtk.Label()
+ self.label.set_label("Settings");
+ self.pack_start(self.label)
+ self.label.show()
+ self.show()
View
5 src/plugins/terminal/Makefile.am
@@ -0,0 +1,5 @@
+plugsdir = $(libdir)/@PACKAGE@/plugins/terminal
+plugs_SCRIPTS = *.py
+
+EXTRA_DIST = \
+ $(plugs_SCRIPTS)
View
16 src/plugins/terminal/__init__.py
@@ -0,0 +1,16 @@
+#
+# Copyright 2012 Tomasz Wiszkowski
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WAR