This is an automated email from the git hooks/post-receive script. x2go pushed a change to branch brokerclient in repository pyhoca-gui. from b53a52c Adapt to new backend concept found in Python X2Go (>= 0.5.0.0). new 7bd3d3a Move most code of the pyhoca-gui executable into a dedicated class named PyHocaGUI_Launcher. The 1 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Summary of changes: debian/changelog | 2 + pyhoca-gui | 403 ++-------------------------------------------- pyhoca/wxgui/__init__.py | 1 + pyhoca/wxgui/launcher.py | 335 ++++++++++++++++++++++++++++++++++++++ pyhoca/wxgui/options.py | 109 +++++++++++++ 5 files changed, 457 insertions(+), 393 deletions(-) create mode 100644 pyhoca/wxgui/launcher.py create mode 100644 pyhoca/wxgui/options.py -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/pyhoca-gui.git
This is an automated email from the git hooks/post-receive script. x2go pushed a commit to branch brokerclient in repository pyhoca-gui. commit 7bd3d3ac9e41d4b43a6b9073297611f2b77969fd Author: Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Date: Wed Feb 5 09:32:54 2014 +0100 Move most code of the pyhoca-gui executable into a dedicated class named PyHocaGUI_Launcher. --- debian/changelog | 2 + pyhoca-gui | 403 ++-------------------------------------------- pyhoca/wxgui/__init__.py | 1 + pyhoca/wxgui/launcher.py | 335 ++++++++++++++++++++++++++++++++++++++ pyhoca/wxgui/options.py | 109 +++++++++++++ 5 files changed, 457 insertions(+), 393 deletions(-) diff --git a/debian/changelog b/debian/changelog index 9f1bbaf..86beb5d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,8 @@ pyhoca-gui (0.5.0.0-0x2go1) UNRELEASED; urgency=low * Adapt to new backend concept found in Python X2Go (>= 0.5.0.0). + * Move most code of the pyhoca-gui executable into a dedicated class + named PyHocaGUI_Launcher. -- Mike Gabriel <mike.gabriel@das-netzwerkteam.de> Wed, 08 Jan 2014 21:28:37 +0100 diff --git a/pyhoca-gui b/pyhoca-gui index e22fd18..cd6bcf4 100755 --- a/pyhoca-gui +++ b/pyhoca-gui @@ -19,403 +19,20 @@ # Free Software Foundation, Inc., # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. -modules ={} - -import sys import os -import re -import shutil -PROG_NAME = os.path.basename(sys.argv[0]).replace('.exe', '') -PROG_PID = os.getpid() - -if hasattr(sys, 'frozen') and str(sys.frozen) in ("windows_exe", "console_exe", "1", ): - class Win32_Logging(object): - - softspace = 0 - _fname = os.path.join(os.environ['AppData'], PROG_NAME, '%s.log' % PROG_NAME) - _file = None - - def __init__(self, filemode='a'): - self._filemode = filemode - if os.path.isfile(self._fname) and self._filemode == "w+": - os.remove(self._fname) - - def write(self, text, **kwargs): - if self._file is None: - try: - try: - os.mkdir(os.path.dirname(self._fname)) - except: - pass - self._file = open(self._fname, self._filemode) - except: - pass - else: - self._file.write(text) - self._file.flush() - - def flush(self): - if self._file is not None: - self._file.flush() - - sys.stdout = Win32_Logging(filemode='w+') - sys.stderr = Win32_Logging(filemode='a') - del Win32_Logging - -import gevent -import gevent.monkey -gevent.monkey.patch_all() - -import subprocess - -try: - import wxversion - wxversion.select('2.9') -except: pass -try: - import wxversion - wxversion.select('2.8') -except: pass - -import argparse -import os -import exceptions -import locale -import gettext -import wx - -from x2go import X2GOCLIENT_OS as _X2GOCLIENT_OS - -if _X2GOCLIENT_OS in ('Linux', 'Mac'): - import setproctitle - setproctitle.setproctitle(PROG_NAME) - -if sys.argv[0].startswith('./') or sys.argv[0].startswith('python'): - sys.path.insert(0, os.getcwd()) - os.environ['PYHOCAGUI_DEVELOPMENT'] = '1' - print '### %s running in development mode ###' % PROG_NAME - -from pyhoca.wxgui.basepath import locale_basepath - -# Python X2Go modules -from x2go import CURRENT_LOCAL_USER as _CURRENT_LOCAL_USER -if _X2GOCLIENT_OS == 'Windows': - from x2go import X2GoClientXConfig as _X2GoClientXConfig -from x2go import X2GoLogger as _X2GoLogger -from x2go import x2go_cleanup as _x2go_cleanup - -# X2Go backends -from x2go.defaults import BACKENDS as _BACKENDS - -from pyhoca.wxgui import __VERSION__ as _version -from pyhoca.wxgui import messages -from pyhoca.wxgui import PyHocaGUI +import sys -if _X2GOCLIENT_OS == 'Windows': - from pyhoca.wxgui.basepath import nxproxy_binary - os.environ.update({'NXPROXY_BINARY': nxproxy_binary, }) +from pyhoca.wxgui import * +from pyhoca.wxgui import __VERSION__ __author__ = "Mike Gabriel, Dick Kniep" -__version__ = _version - -# version information -VERSION=_version -VERSION_TEXT=""" -%s[%s] - an X2Go GUI client written in Python ----------------------------------------------------------------------- -developed by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> -sponsored by Dick Kniep <dick.kniep@lindix.nl> (2010-2013) - -VERSION: %s - -""" % (PROG_NAME, PROG_PID, VERSION) - -def check_running(): - if _X2GOCLIENT_OS in ('Linux', 'Mac'): - - p = subprocess.Popen(['ps', '-U', _CURRENT_LOCAL_USER, '-u', _CURRENT_LOCAL_USER], stdout=subprocess.PIPE) - psA_out = p.communicate() - if psA_out[0].count(PROG_NAME) <= 1: - - if os.path.isdir(os.path.expanduser("~/.x2go/pyhoca-gui/")): - shutil.rmtree(os.path.expanduser("~/.x2go/pyhoca-gui/")) - - my_pid = str(os.getpid()) - if not os.path.exists(os.path.expanduser("~/.x2go/pyhoca-gui/")): - os.makedirs(os.path.expanduser("~/.x2go/pyhoca-gui/")) - my_pidfile = os.path.expanduser("~/.x2go/pyhoca-gui/display.{pid}".format(pid=my_pid)) - - my_display = os.environ['DISPLAY'] - open(my_pidfile, 'w').write(my_display) - - already_running_for_this_display = False - for pidfile in os.listdir(os.path.expanduser("~/.x2go/pyhoca-gui/")): - - # this is our own pid file... - if my_pidfile.endswith(pidfile): - continue - - display = open(os.path.expanduser("~/.x2go/pyhoca-gui/") + pidfile, 'r').read() - - if display.split('.')[0] == my_display.split('.')[0]: - other_pid = pidfile.split('.')[1] - print - print('One instance of PyHoca-GUI (PID: {other_pid}) is already running for this $DISPLAY {display}'.format(other_pid=other_pid, display=my_display)) - - return True - - return False - - elif _X2GOCLIENT_OS == 'Windows': - import wmi - w = wmi.WMI() - _p_names = [] - for process in w.Win32_Process(): - _p_names.append(process.Name) - return len([ _p_name for _p_name in _p_names if _p_name == PROG_NAME]) > 1 - - -def version(): - # print version text and exit - sys.stderr.write ("%s\n" % VERSION_TEXT) - remove_pidfile() - - sys.exit(0) - - -# sometimes we have to fail... -def runtime_error(m, parser=None, exitcode=-1): - """\ - STILL UNDOCUMENTED - """ - if parser is not None: - parser.print_usage() - sys.stderr.write ("%s: error: %s\n" % (PROG_NAME, m)) +__version__ = __VERSION__ - remove_pidfile() - sys.exit(exitcode) - - -if _X2GOCLIENT_OS == 'Windows': - _x = _X2GoClientXConfig() - _known_xservers = _x.known_xservers - _installed_xservers = _x.installed_xservers - -if _X2GOCLIENT_OS == 'Windows': - _config_backends = ('FILE', 'WINREG') -elif _X2GOCLIENT_OS == 'Linux': - _config_backends = ('FILE', 'GCONF') -else: - _config_backends = ('FILE') - -_profiles_backend_default = _BACKENDS['X2GoSessionProfiles']['default'] -_settings_backend_default = _BACKENDS['X2GoClientSettings']['default'] -_printing_backend_default = _BACKENDS['X2GoClientPrinting']['default'] - -# debug options... -debug_options = [ - {'args':['-d','--debug'], 'default': False, 'action': 'store_true', 'help': 'enable application debugging code', }, - {'args':['--quiet'], 'default': False, 'action': 'store_true', 'help': 'disable any kind of log output', }, - {'args':['--libdebug'], 'default': False, 'action': 'store_true', 'help': 'enable debugging code of the underlying Python X2Go module', }, - {'args':['--libdebug-sftpxfer'], 'default': False, 'action': 'store_true', 'help': 'enable debugging code of Python X2Go\'s sFTP server code (very verbose, and even promiscuous)', }, - {'args':['-V', '--version'], 'default': False, 'action': 'store_true', 'help': 'print version number and exit', }, - ] -x2go_gui_options = [ - {'args':['-P','--session-profile'], 'default': None, 'metavar': '<profile-name>', 'help': 'directly connect to a session profile', }, - {'args':['--remember-username'], 'default': False, 'action': 'store_true', 'help': 'for profiles with interactive authentication, remember the last-used username', }, - {'args':['--non-interactive'], 'default': False, 'action': 'store_true', 'help': 'run the session manager in non-interactive mode, this option sets the following options to true: --restricted-trayicon, --single_session_profile, --start-on-connect, --resume-all-on-connect, --exit-on-disconnect, --disconnect-on-suspend and --disconnect-on-terminate', }, - {'args':['--auto-connect'], 'default': False, 'action': 'store_true', 'help': 'connect sessions via SSH pubkey authentication if possible', }, - {'args':['--show-profile-metatypes'], 'default': False, 'action': 'store_true', 'help': 'show descriptive meta information on session profiles in menus (NOTE: this makes menus appear a bit more sluggish, use it mostly for debugging)', }, - {'args':['--single-session-profile'], 'default': False, 'action': 'store_true', 'help': 'disable support of handling multiple session profiles', }, - {'args':['--tray-icon'], 'default': None, 'metavar': '<your-logo>', 'help': 'define an alternative system tray icon file (PNG files only, leave out file extension here, size 22x22 on Linux, 16x16 on Windows)', }, - {'args':['--tray-icon-connecting'], 'default': None, 'metavar': '<your-logo-while-connecting>', 'help': 'define an alternative system tray icon file while connecting to a server (PNG files only, leave out file extension here, size 22x22 on Linux, 16x16 on Windows)', }, - {'args':['--restricted-trayicon'], 'default': False, 'action': 'store_true', 'help': 'restricts session manager\'s main icon functionality to information window and application exit; on left-click only a minimal session menu is shown', }, - {'args':['--add-to-known-hosts'], 'default': False, 'action': 'store_true', 'help': 'automatically add SSH host keys to the known_hosts files of the client-side user', }, - {'args':['--start-on-connect'], 'default': False, 'action': 'store_true', 'help': 'This is now the hard-coded default. start a session directly after authentication if no session is currently running/suspended', }, - {'args':['--exit-on-disconnect'], 'default': False, 'action': 'store_true', 'help': 'exit the session manager after a server connection has died', }, - {'args':['--resume-newest-on-connect', '--resume-on-connect'], 'default': False, 'action': 'store_true', 'help': 'This is now the hard-coded default. On connect auto-resume the newest suspended session', }, - {'args':['--resume-oldest-on-connect'], 'default': False, 'action': 'store_true', 'help': 'on connect auto-resume the oldest suspended session', }, - {'args':['--resume-all-on-connect'], 'default': False, 'action': 'store_true', 'help': 'auto-resume all suspended sessions on connect', }, - {'args':['--disconnect-on-suspend'], 'default': False, 'action': 'store_true', 'help': 'disconnect a server if a session has been suspended', }, - {'args':['--disconnect-on-terminate'], 'default': False, 'action': 'store_true', 'help': 'disconnect a server if a session has been terminated', }, - {'args':['--splash-image'], 'default': None, 'metavar': '<your-splash-image>', 'help': 'define an alternative splash image that gets shown on application startup (PNG files only, full path or filename as found in <share>/img)', }, - {'args':['--about-image'], 'default': None, 'metavar': '<your-about-window-image>', 'help': 'define an alternative image for the application\'s ,,About\'\' window (PNG files only, full path or filename as found in <share>/img)', }, - {'args':['--disable-splash'], 'default': False, 'action': 'store_true', 'help': 'disable the applications splash screen', }, - {'args':['--disable-options'], 'default': False, 'action': 'store_true', 'help': 'disable the client options configuration window', }, - {'args':['--disable-printingprefs'], 'default': False, 'action': 'store_true', 'help': 'disable the client\'s printing preferences window', }, - {'args':['--disable-profilemanager'], 'default': False, 'action': 'store_true', 'help': 'disable the session profile manager window', }, - {'args':['--disable-notifications'], 'default': False, 'action': 'store_true', 'help': 'disable all applet notifications', }, - {'args':['--display'], 'default': None, 'metavar': '<hostname>:<screennumber>', 'help': 'set the DISPLAY environment variable to <hostname>:<screennumber>', }, - {'args':['--logon-window-position'], 'default': None, 'metavar': '<x-pos>x<y-pos>', 'help': 'give a custom position for the logon window, use negative values to position relative to right/bottom border', }, - {'args':['--published-applications-no-submenus'], 'default': 10, 'metavar': '<number>', 'help': 'the number of published applications that will be rendered without submenus', }, - ] -if _X2GOCLIENT_OS == 'Windows': - x2go_gui_options.append( - {'args':['--lang'], 'default': None, 'metavar': 'LANGUAGE', 'help': 'set the GUI language (currently available: en, de, nl, es)', }, - ) - -backend_options = [ - {'args':['--backend-controlsession'], 'default': None, 'metavar': '<CONTROLSESSION_BACKEND>', 'choices': _BACKENDS['X2GoControlSession'].keys(), 'help': 'force usage of a certain CONTROLSESSION_BACKEND (do not use this unless you know exactly what you are doing)', }, - {'args':['--backend-terminalsession'], 'default': None, 'metavar': '<TERMINALSESSION_BACKEND>', 'choices': _BACKENDS['X2GoTerminalSession'].keys(), 'help': 'force usage of a certain TERMINALSESSION_BACKEND (do not use this unless you know exactly what you are doing)', }, - {'args':['--backend-serversessioninfo'], 'default': None, 'metavar': '<SERVERSESSIONINFO_BACKEND>', 'choices': _BACKENDS['X2GoServerSessionInfo'].keys(), 'help': 'force usage of a certain SERVERSESSIONINFO_BACKEND (do not use this unless you know exactly what you are doing)', }, - {'args':['--backend-serversessionlist'], 'default': None, 'metavar': '<SERVERSESSIONLIST_BACKEND>', 'choices': _BACKENDS['X2GoServerSessionList'].keys(), 'help': 'force usage of a certain SERVERSESSIONLIST_BACKEND (do not use this unless you know exactly what you are doing)', }, - {'args':['--backend-proxy'], 'default': None, 'metavar': '<PROXY_BACKEND>', 'choices': _BACKENDS['X2GoProxy'].keys(), 'help': 'force usage of a certain PROXY_BACKEND (do not use this unless you know exactly what you are doing)', }, - {'args':['--backend-sessionprofiles'], 'default': None, 'metavar': '<SESSIONPROFILES_BACKEND>', 'choices': _config_backends, 'help': 'use given backend for accessing session profiles, available backends on your system: %s (default: %s)' % (', '.join(_config_backends), _profiles_backend_default), }, - {'args':['--backend-clientsettings'], 'default': None, 'metavar': '<CLIENTSETTINGS_BACKEND>', 'choices': _config_backends, 'help': 'use given backend for accessing the client settings configuration, available backends on your system: %s (default: %s)' % (', '.join(_config_backends), _settings_backend_default), }, - {'args':['--backend-clientprinting'], 'default': None, 'metavar': '<CLIENTPRINTING_BACKEND>', 'choices': _config_backends, 'help': 'use given backend for accessing the client printing configuration, available backends on your system: %s (default: %s)' % (', '.join(_config_backends), _printing_backend_default), }, - ] - -if _X2GOCLIENT_OS == 'Windows': - contrib_options = [ - {'args':['--start-xserver'], 'default': False, 'action': 'store_true', 'help': 'start the XServer before starting the session manager application, detect best XServer automatically, if more than one XServer is installed on your system', }, - {'args':['-X', '--preferred-xserver'], 'default': None, 'metavar': '<XSERVER>', 'choices': _known_xservers, 'help': 'start either of the currently supported XServers: %s -- make sure your preferred XServer is installed on your system' % _known_xservers, }, - {'args':['--start-pulseaudio'], 'default': False, 'action': 'store_true', 'help': 'start the PulseAudio server before starting the session manager application', }, - ] - -portable_options = [ - {'args':['--client-rootdir'], 'default': None, 'metavar': '</path/to/.x2goclient/dir>', 'help': 'define an alternative location where to find plain text config files (default: <HOME>/.x2goclient). This option will set ,,--backend-profiles FILE\'\', ,,--backend-clientsettings FILE\'\' and ,,--backend-clientprinting FILE\'\'', }, - {'args':['--sessions-rootdir'], 'default': None, 'metavar': '</path/to/.x2go/dir>', 'help': 'define an alternative location for session runtime files'}, - {'args':['--ssh-rootdir'], 'default': None, 'metavar': '</path/to/.ssh/dir>', 'help': 'define an alternative location for SSH files', }, - ] - - -def remove_pidfile(): - - if _X2GOCLIENT_OS in ('Linux', 'Mac'): - my_pid = str(os.getpid()) - if os.path.exists(os.path.expanduser("~/.x2go/pyhoca-gui/display.{pid}".format(pid=my_pid))): - os.remove(os.path.expanduser("~/.x2go/pyhoca-gui/display.{pid}".format(pid=my_pid))) - - -def parseargs(): - - global DEBUG - global print_action_args - - p = argparse.ArgumentParser(description='Graphical X2Go client implemented in (wx)Python.',\ - formatter_class=argparse.RawDescriptionHelpFormatter, \ - add_help=True, argument_default=None) - p_debugopts = p.add_argument_group('Debug options') - p_guiopts = p.add_argument_group('%s options' % PROG_NAME) - p_portableopts = p.add_argument_group('Portable application support') - p_backendopts = p.add_argument_group('Python X2Go backend options (for experts only)') - - if _X2GOCLIENT_OS == 'Windows': - p_contribopts = p.add_argument_group('XServer options (MS Windows only)') - p_portableopts = p.add_argument_group('File locations for portable setups (MS Windows only)') - _option_groups = ((p_guiopts, x2go_gui_options), (p_debugopts, debug_options), (p_contribopts, contrib_options), (p_portableopts, portable_options), (p_backendopts, backend_options), ) - else: - _option_groups = ((p_guiopts, x2go_gui_options), (p_debugopts, debug_options), (p_portableopts, portable_options), (p_backendopts, backend_options), ) - for (p_group, opts) in _option_groups: - required = False - for opt in opts: - - args = opt['args'] - del opt['args'] - p_group.add_argument(*args, **opt) - - a = p.parse_args() - - logger = _X2GoLogger(tag=PROG_NAME) - liblogger = _X2GoLogger() - - if a.debug: - logger.set_loglevel_debug() - - if a.libdebug: - liblogger.set_loglevel_debug() - - if a.quiet: - logger.set_loglevel_quiet() - liblogger.set_loglevel_quiet() - - if a.libdebug_sftpxfer: - liblogger.enable_debug_sftpxfer() - - if a.version: - version() - - if a.single_session_profile and a.session_profile is None: - runtime_error('The --single-session-profile option requires naming of a specific session profile!', parser=p) - - if a.non_interactive: - if a.session_profile is None: - runtime_error('In non-interactive mode you have to use the --session-profile option (or -P) to specify a certain session profile name!', parser=p) - a.restricted_trayicon = True - a.auto_connect = True - a.start_on_connect = True - a.resume_all_on_connect = True - a.exit_on_disconnect = True - a.disconnect_on_suspend = True - a.disconnect_on_terminate = True - a.single_session_profile = True - - if a.non_interactive and (a.resume_newest_on_connect or a.resume_oldest_on_connect): - # allow override... - a.resume_all_on_connect = False - - if _X2GOCLIENT_OS == 'Windows' and a.preferred_xserver: - if a.preferred_xserver not in _installed_xservers: - runtime_error('Xserver ,,%s\'\' is not installed on your Windows system' % a.preferred_xserver, parser=p) - a.start_xserver = a.preferred_xserver - - if _X2GOCLIENT_OS == 'Windows' and a.start_xserver and a.display: - runtime_error('You can tell %s to handle XServer startup and then specify a DISPLAY environment variable!' % PROG_NAME, parser=p) - - if a.display: - os.environ.update({'DISPLAY': a.display}) - else: - if _X2GOCLIENT_OS == 'Windows' and not a.start_xserver: - os.environ.update({'DISPLAY': 'localhost:0'}) - - if a.client_rootdir: - a.client_rootdir = os.path.expanduser(a.client_rootdir) - - if a.sessions_rootdir: - a.sessions_rootdir = os.path.expanduser(a.sessions_rootdir) - - if a.ssh_rootdir: - a.ssh_rootdir = os.path.expanduser(a.ssh_rootdir) - - if a.client_rootdir: - a.backend_sessionprofiles='FILE' - a.backend_clientsettings='FILE' - a.backend_clientprinting='FILE' - - return a, logger, liblogger - -def main(): - args, logger, liblogger = parseargs() - if _X2GOCLIENT_OS == 'Windows': - if args.lang: - lang = gettext.translation('PyHoca-GUI', localedir=locale_basepath, languages=[args.lang], ) - else: - lang = gettext.translation('PyHoca-GUI', localedir=locale_basepath, languages=['en'], ) - lang.install(unicode=True) - else: - gettext.install('PyHoca-GUI', localedir=locale_basepath, unicode=True) - - if check_running(): - sys.stderr.write("\n###############################\n### %s: already running for user %s\n###############################\n" % (PROG_NAME, _CURRENT_LOCAL_USER)) - m = messages.PyHoca_MessageWindow_Ok(wx.App(), shortmsg='ALREADY_RUNNING', title=u'%s (%s)...' % (PROG_NAME, VERSION), icon='pyhoca-trayicon') - m.ShowModal() - version() - - thisPyHocaGUI = None - try: - thisPyHocaGUI = PyHocaGUI(args, logger, liblogger, appname=PROG_NAME, version=VERSION) - thisPyHocaGUI.MainLoop() - except KeyboardInterrupt: - if thisPyHocaGUI is not None: - thisPyHocaGUI.WakeUpIdle() - thisPyHocaGUI.ExitMainLoop() - except SystemExit: - if thisPyHocaGUI is not None: - thisPyHocaGUI.WakeUpIdle() - thisPyHocaGUI.ExitMainLoop() - - remove_pidfile() if __name__ == '__main__': - main() - + app = PyHocaGUI_Launcher() + #app.setup_progname('MyProgramme') + app.setup_consolelog() + app.setup_process() + app.setup_devmode() + app.main() diff --git a/pyhoca/wxgui/__init__.py b/pyhoca/wxgui/__init__.py index a0ea0fa..89a1d1f 100644 --- a/pyhoca/wxgui/__init__.py +++ b/pyhoca/wxgui/__init__.py @@ -21,3 +21,4 @@ __VERSION__ = '0.5.0.0' from frontend import * +from launcher import * \ No newline at end of file diff --git a/pyhoca/wxgui/launcher.py b/pyhoca/wxgui/launcher.py new file mode 100644 index 0000000..5d43a4d --- /dev/null +++ b/pyhoca/wxgui/launcher.py @@ -0,0 +1,335 @@ +# -*- coding: utf-8 -*- + +# Copyright (C) 2010-2014 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> +# Copyright (C) 2010-2014 by Dick Kniep <dick.kniep@lindix.nl> +# +# PyHoca GUI is free software; you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# PyHoca GUI 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +modules ={} + +import sys +import os +import re +import shutil +import argparse +import gettext +import subprocess + +import gevent.monkey +gevent.monkey.patch_all() + +try: + import wxversion + wxversion.select('2.9') +except: pass + +try: + import wxversion + wxversion.select('2.8') +except: pass + + +from x2go import X2GOCLIENT_OS +from x2go import CURRENT_LOCAL_USER +from x2go import X2GoLogger +from pyhoca.wxgui import PyHocaGUI, __VERSION__ +from options import * +from basepath import * +from messages import PyHoca_MessageWindow_Ok +import wx + +class PyHocaGUI_Launcher(object): + + def __init__(self): + self.PROG_NAME = os.path.basename(sys.argv[0]).replace('.exe', '') + self.PROG_PID = os.getpid() + self.VERSION=__VERSION__ + self.VERSION_TEXT=""" +%s[%s] - an X2Go GUI client written in Python +---------------------------------------------------------------------- +developed by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> +sponsored by Dick Kniep <dick.kniep@lindix.nl> (2010-2013) + +VERSION: %s + +""" % (self.PROG_NAME, self.PROG_PID, self.VERSION) + + def setup_progname(self, pname): + self.PROG_NAME = pname + + def setup_version(self, v): + self.VERSION = v + + def setup_version_text(self, text): + self.VERSION_TEXT = text + + def setup_process(self): + if X2GOCLIENT_OS in ('Linux', 'Mac'): + import setproctitle + setproctitle.setproctitle(self.PROG_NAME) + + if X2GOCLIENT_OS == 'Windows': + from pyhoca.wxgui.basepath import nxproxy_binary + os.environ.update({'NXPROXY_BINARY': nxproxy_binary, }) + + def setup_devmode(self): + if sys.argv[0].startswith('./') or sys.argv[0].startswith('python'): + sys.path.insert(0, os.getcwd()) + os.environ['PYHOCAGUI_DEVELOPMENT'] = '1' + print '### %s running in development mode ###' % self.PROG_NAME + + + def setup_consolelog(self): + if hasattr(sys, 'frozen') and str(sys.frozen) in ("windows_exe", "console_exe", "1", ): + class Win32_Logging(object): + + softspace = 0 + _fname = os.path.join(os.environ['AppData'], self.PROG_NAME, '%s.log' % self.PROG_NAME) + _file = None + + def __init__(self, filemode='a'): + self._filemode = filemode + if os.path.isfile(self._fname) and self._filemode == "w+": + os.remove(self._fname) + + def write(self, text, **kwargs): + if self._file is None: + try: + try: + os.mkdir(os.path.dirname(self._fname)) + except: + pass + self._file = open(self._fname, self._filemode) + except: + pass + else: + self._file.write(text) + self._file.flush() + + def flush(self): + if self._file is not None: + self._file.flush() + + sys.stdout = Win32_Logging(filemode='w+') + sys.stderr = Win32_Logging(filemode='a') + del Win32_Logging + + + def check_running(self): + if X2GOCLIENT_OS in ('Linux', 'Mac'): + + p = subprocess.Popen(['ps', '-U', CURRENT_LOCAL_USER, '-u', CURRENT_LOCAL_USER], stdout=subprocess.PIPE) + psA_out = p.communicate() + if psA_out[0].count(self.PROG_NAME) <= 1: + + if os.path.isdir(os.path.expanduser("~/.x2go/pyhoca-gui/")): + shutil.rmtree(os.path.expanduser("~/.x2go/pyhoca-gui/")) + + my_pid = str(os.getpid()) + if not os.path.exists(os.path.expanduser("~/.x2go/pyhoca-gui/")): + os.makedirs(os.path.expanduser("~/.x2go/pyhoca-gui/")) + my_pidfile = os.path.expanduser("~/.x2go/pyhoca-gui/display.{pid}".format(pid=my_pid)) + + my_display = os.environ['DISPLAY'] + open(my_pidfile, 'w').write(my_display) + + already_running_for_this_display = False + for pidfile in os.listdir(os.path.expanduser("~/.x2go/pyhoca-gui/")): + + # this is our own pid file... + if my_pidfile.endswith(pidfile): + continue + + display = open(os.path.expanduser("~/.x2go/pyhoca-gui/") + pidfile, 'r').read() + + if display.split('.')[0] == my_display.split('.')[0]: + other_pid = pidfile.split('.')[1] + print + print('One instance of PyHoca-GUI (PID: {other_pid}) is already running for this $DISPLAY {display}'.format(other_pid=other_pid, display=my_display)) + + return True + + return False + + elif X2GOCLIENT_OS == 'Windows': + import wmi + w = wmi.WMI() + _p_names = [] + for process in w.Win32_Process(): + _p_names.append(process.Name) + return len([ _p_name for _p_name in _p_names if _p_name == self.PROG_NAME]) > 1 + + + def version(self): + # version information + + # print version text and exit + sys.stderr.write ("%s\n" % self.VERSION_TEXT) + self.remove_pidfile() + + sys.exit(0) + + + # sometimes we have to fail... + def runtime_error(m, parser=None, exitcode=-1): + """\ + STILL UNDOCUMENTED + """ + if parser is not None: + parser.print_usage() + sys.stderr.write ("%s: error: %s\n" % (self.PROG_NAME, m)) + + self.remove_pidfile() + sys.exit(exitcode) + + + def remove_pidfile(self): + + if X2GOCLIENT_OS in ('Linux', 'Mac'): + my_pid = str(os.getpid()) + if os.path.exists(os.path.expanduser("~/.x2go/pyhoca-gui/display.{pid}".format(pid=my_pid))): + os.remove(os.path.expanduser("~/.x2go/pyhoca-gui/display.{pid}".format(pid=my_pid))) + + + def parseargs(self): + + global DEBUG + global print_action_args + + p = argparse.ArgumentParser(description='Graphical X2Go client implemented in (wx)Python.',\ + formatter_class=argparse.RawDescriptionHelpFormatter, \ + add_help=True, argument_default=None) + p_debugopts = p.add_argument_group('Debug options') + p_guiopts = p.add_argument_group('%s options' % self.PROG_NAME) + p_portableopts = p.add_argument_group('Portable application support') + p_backendopts = p.add_argument_group('Python X2Go backend options (for experts only)') + + if X2GOCLIENT_OS == 'Windows': + p_contribopts = p.add_argument_group('XServer options (MS Windows only)') + p_portableopts = p.add_argument_group('File locations for portable setups (MS Windows only)') + _option_groups = ((p_guiopts, x2go_gui_options), (p_debugopts, debug_options), (p_contribopts, contrib_options), (p_portableopts, portable_options), (p_backendopts, backend_options), ) + else: + _option_groups = ((p_guiopts, x2go_gui_options), (p_debugopts, debug_options), (p_portableopts, portable_options), (p_backendopts, backend_options), ) + for (p_group, opts) in _option_groups: + required = False + for opt in opts: + + args = opt['args'] + del opt['args'] + p_group.add_argument(*args, **opt) + + a = p.parse_args() + + logger = X2GoLogger(tag=self.PROG_NAME) + liblogger = X2GoLogger() + + if a.debug: + logger.set_loglevel_debug() + + if a.libdebug: + liblogger.set_loglevel_debug() + + if a.quiet: + logger.set_loglevel_quiet() + liblogger.set_loglevel_quiet() + + if a.libdebug_sftpxfer: + liblogger.enable_debug_sftpxfer() + + if a.version: + self.version() + + if a.single_session_profile and a.session_profile is None: + self.runtime_error('The --single-session-profile option requires naming of a specific session profile!', parser=p) + + if a.non_interactive: + if a.session_profile is None: + self.runtime_error('In non-interactive mode you have to use the --session-profile option (or -P) to specify a certain session profile name!', parser=p) + a.restricted_trayicon = True + a.auto_connect = True + a.start_on_connect = True + a.resume_all_on_connect = True + a.exit_on_disconnect = True + a.disconnect_on_suspend = True + a.disconnect_on_terminate = True + a.single_session_profile = True + + if a.non_interactive and (a.resume_newest_on_connect or a.resume_oldest_on_connect): + # allow override... + a.resume_all_on_connect = False + + if X2GOCLIENT_OS == 'Windows' and a.preferred_xserver: + if a.preferred_xserver not in _installed_xservers: + self.runtime_error('Xserver ,,%s\'\' is not installed on your Windows system' % a.preferred_xserver, parser=p) + a.start_xserver = a.preferred_xserver + + if X2GOCLIENT_OS == 'Windows' and a.start_xserver and a.display: + self.runtime_error('You can tell %s to handle XServer startup and then specify a DISPLAY environment variable!' % self.PROG_NAME, parser=p) + + if a.display: + os.environ.update({'DISPLAY': a.display}) + else: + if X2GOCLIENT_OS == 'Windows' and not a.start_xserver: + os.environ.update({'DISPLAY': 'localhost:0'}) + + if a.client_rootdir: + a.client_rootdir = os.path.expanduser(a.client_rootdir) + + if a.sessions_rootdir: + a.sessions_rootdir = os.path.expanduser(a.sessions_rootdir) + + if a.ssh_rootdir: + a.ssh_rootdir = os.path.expanduser(a.ssh_rootdir) + + if a.client_rootdir: + a.backend_sessionprofiles='FILE' + a.backend_clientsettings='FILE' + a.backend_clientprinting='FILE' + + return a, logger, liblogger + + + def main(self): + args, logger, liblogger = self.parseargs() + if X2GOCLIENT_OS == 'Windows': + if args.lang: + lang = gettext.translation('PyHoca-GUI', localedir=locale_basepath, languages=[args.lang], ) + else: + lang = gettext.translation('PyHoca-GUI', localedir=locale_basepath, languages=['en'], ) + lang.install(unicode=True) + else: + gettext.install('PyHoca-GUI', localedir=locale_basepath, unicode=True) + + if self.check_running(): + sys.stderr.write("\n###############################\n### %s: already running for user %s\n###############################\n" % (self.PROG_NAME, CURRENT_LOCAL_USER)) + m = PyHoca_MessageWindow_Ok(wx.App(), shortmsg='ALREADY_RUNNING', title=u'%s (%s)...' % (self.PROG_NAME, self.VERSION), icon='pyhoca-trayicon') + m.ShowModal() + version() + + thisPyHocaGUI = None + try: + thisPyHocaGUI = PyHocaGUI(args, logger, liblogger, appname=self.PROG_NAME, version=self.VERSION) + thisPyHocaGUI.MainLoop() + except KeyboardInterrupt: + if thisPyHocaGUI is not None: + thisPyHocaGUI.WakeUpIdle() + thisPyHocaGUI.ExitMainLoop() + except SystemExit: + if thisPyHocaGUI is not None: + thisPyHocaGUI.WakeUpIdle() + thisPyHocaGUI.ExitMainLoop() + + self.remove_pidfile() diff --git a/pyhoca/wxgui/options.py b/pyhoca/wxgui/options.py new file mode 100644 index 0000000..3a79cce --- /dev/null +++ b/pyhoca/wxgui/options.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (C) 2010-2013 by Mike Gabriel <mike.gabriel@das-netzwerkteam.de> +# Copyright (C) 2010-2013 by Dick Kniep <dick.kniep@lindix.nl> +# +# PyHoca GUI is free software; you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# PyHoca GUI 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program; if not, write to the +# Free Software Foundation, Inc., +# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +from x2go import X2GOCLIENT_OS +from x2go import BACKENDS + +_profiles_backend_default = BACKENDS['X2GoSessionProfiles']['default'] +_settings_backend_default = BACKENDS['X2GoClientSettings']['default'] +_printing_backend_default = BACKENDS['X2GoClientPrinting']['default'] + +if X2GOCLIENT_OS == 'Windows': + from x2go import X2GoClientXConfig + _x = X2GoClientXConfig() + _known_xservers = _x.known_xservers + _installed_xservers = _x.installed_xservers + +if X2GOCLIENT_OS == 'Windows': + _config_backends = ('FILE', 'WINREG') +elif X2GOCLIENT_OS == 'Linux': + _config_backends = ('FILE', 'GCONF') +else: + _config_backends = ('FILE') + + +# debug options... +debug_options = [ + {'args':['-d','--debug'], 'default': False, 'action': 'store_true', 'help': 'enable application debugging code', }, + {'args':['--quiet'], 'default': False, 'action': 'store_true', 'help': 'disable any kind of log output', }, + {'args':['--libdebug'], 'default': False, 'action': 'store_true', 'help': 'enable debugging code of the underlying Python X2Go module', }, + {'args':['--libdebug-sftpxfer'], 'default': False, 'action': 'store_true', 'help': 'enable debugging code of Python X2Go\'s sFTP server code (very verbose, and even promiscuous)', }, + {'args':['-V', '--version'], 'default': False, 'action': 'store_true', 'help': 'print version number and exit', }, + ] +x2go_gui_options = [ + {'args':['-P','--session-profile'], 'default': None, 'metavar': '<profile-name>', 'help': 'directly connect to a session profile', }, + {'args':['--remember-username'], 'default': False, 'action': 'store_true', 'help': 'for profiles with interactive authentication, remember the last-used username', }, + {'args':['--non-interactive'], 'default': False, 'action': 'store_true', 'help': 'run the session manager in non-interactive mode, this option sets the following options to true: --restricted-trayicon, --single_session_profile, --start-on-connect, --resume-all-on-connect, --exit-on-disconnect, --disconnect-on-suspend and --disconnect-on-terminate', }, + {'args':['--auto-connect'], 'default': False, 'action': 'store_true', 'help': 'connect sessions via SSH pubkey authentication if possible', }, + {'args':['--show-profile-metatypes'], 'default': False, 'action': 'store_true', 'help': 'show descriptive meta information on session profiles in menus (NOTE: this makes menus appear a bit more sluggish, use it mostly for debugging)', }, + {'args':['--single-session-profile'], 'default': False, 'action': 'store_true', 'help': 'disable support of handling multiple session profiles', }, + {'args':['--tray-icon'], 'default': None, 'metavar': '<your-logo>', 'help': 'define an alternative system tray icon file (PNG files only, leave out file extension here, size 22x22 on Linux, 16x16 on Windows)', }, + {'args':['--tray-icon-connecting'], 'default': None, 'metavar': '<your-logo-while-connecting>', 'help': 'define an alternative system tray icon file while connecting to a server (PNG files only, leave out file extension here, size 22x22 on Linux, 16x16 on Windows)', }, + {'args':['--restricted-trayicon'], 'default': False, 'action': 'store_true', 'help': 'restricts session manager\'s main icon functionality to information window and application exit; on left-click only a minimal session menu is shown', }, + {'args':['--add-to-known-hosts'], 'default': False, 'action': 'store_true', 'help': 'automatically add SSH host keys to the known_hosts files of the client-side user', }, + {'args':['--start-on-connect'], 'default': False, 'action': 'store_true', 'help': 'This is now the hard-coded default. start a session directly after authentication if no session is currently running/suspended', }, + {'args':['--exit-on-disconnect'], 'default': False, 'action': 'store_true', 'help': 'exit the session manager after a server connection has died', }, + {'args':['--resume-newest-on-connect', '--resume-on-connect'], 'default': False, 'action': 'store_true', 'help': 'This is now the hard-coded default. On connect auto-resume the newest suspended session', }, + {'args':['--resume-oldest-on-connect'], 'default': False, 'action': 'store_true', 'help': 'on connect auto-resume the oldest suspended session', }, + {'args':['--resume-all-on-connect'], 'default': False, 'action': 'store_true', 'help': 'auto-resume all suspended sessions on connect', }, + {'args':['--disconnect-on-suspend'], 'default': False, 'action': 'store_true', 'help': 'disconnect a server if a session has been suspended', }, + {'args':['--disconnect-on-terminate'], 'default': False, 'action': 'store_true', 'help': 'disconnect a server if a session has been terminated', }, + {'args':['--splash-image'], 'default': None, 'metavar': '<your-splash-image>', 'help': 'define an alternative splash image that gets shown on application startup (PNG files only, full path or filename as found in <share>/img)', }, + {'args':['--about-image'], 'default': None, 'metavar': '<your-about-window-image>', 'help': 'define an alternative image for the application\'s ,,About\'\' window (PNG files only, full path or filename as found in <share>/img)', }, + {'args':['--disable-splash'], 'default': False, 'action': 'store_true', 'help': 'disable the applications splash screen', }, + {'args':['--disable-options'], 'default': False, 'action': 'store_true', 'help': 'disable the client options configuration window', }, + {'args':['--disable-printingprefs'], 'default': False, 'action': 'store_true', 'help': 'disable the client\'s printing preferences window', }, + {'args':['--disable-profilemanager'], 'default': False, 'action': 'store_true', 'help': 'disable the session profile manager window', }, + {'args':['--disable-notifications'], 'default': False, 'action': 'store_true', 'help': 'disable all applet notifications', }, + {'args':['--display'], 'default': None, 'metavar': '<hostname>:<screennumber>', 'help': 'set the DISPLAY environment variable to <hostname>:<screennumber>', }, + {'args':['--logon-window-position'], 'default': None, 'metavar': '<x-pos>x<y-pos>', 'help': 'give a custom position for the logon window, use negative values to position relative to right/bottom border', }, + {'args':['--published-applications-no-submenus'], 'default': 10, 'metavar': '<number>', 'help': 'the number of published applications that will be rendered without submenus', }, + ] +if X2GOCLIENT_OS == 'Windows': + x2go_gui_options.append( + {'args':['--lang'], 'default': None, 'metavar': 'LANGUAGE', 'help': 'set the GUI language (currently available: en, de, nl, es)', }, + ) + +backend_options = [ + {'args':['--backend-controlsession'], 'default': None, 'metavar': '<CONTROLSESSION_BACKEND>', 'choices': BACKENDS['X2GoControlSession'].keys(), 'help': 'force usage of a certain CONTROLSESSION_BACKEND (do not use this unless you know exactly what you are doing)', }, + {'args':['--backend-terminalsession'], 'default': None, 'metavar': '<TERMINALSESSION_BACKEND>', 'choices': BACKENDS['X2GoTerminalSession'].keys(), 'help': 'force usage of a certain TERMINALSESSION_BACKEND (do not use this unless you know exactly what you are doing)', }, + {'args':['--backend-serversessioninfo'], 'default': None, 'metavar': '<SERVERSESSIONINFO_BACKEND>', 'choices': BACKENDS['X2GoServerSessionInfo'].keys(), 'help': 'force usage of a certain SERVERSESSIONINFO_BACKEND (do not use this unless you know exactly what you are doing)', }, + {'args':['--backend-serversessionlist'], 'default': None, 'metavar': '<SERVERSESSIONLIST_BACKEND>', 'choices': BACKENDS['X2GoServerSessionList'].keys(), 'help': 'force usage of a certain SERVERSESSIONLIST_BACKEND (do not use this unless you know exactly what you are doing)', }, + {'args':['--backend-proxy'], 'default': None, 'metavar': '<PROXY_BACKEND>', 'choices': BACKENDS['X2GoProxy'].keys(), 'help': 'force usage of a certain PROXY_BACKEND (do not use this unless you know exactly what you are doing)', }, + {'args':['--backend-sessionprofiles'], 'default': None, 'metavar': '<SESSIONPROFILES_BACKEND>', 'choices': _config_backends, 'help': 'use given backend for accessing session profiles, available backends on your system: %s (default: %s)' % (', '.join(_config_backends), _profiles_backend_default), }, + {'args':['--backend-clientsettings'], 'default': None, 'metavar': '<CLIENTSETTINGS_BACKEND>', 'choices': _config_backends, 'help': 'use given backend for accessing the client settings configuration, available backends on your system: %s (default: %s)' % (', '.join(_config_backends), _settings_backend_default), }, + {'args':['--backend-clientprinting'], 'default': None, 'metavar': '<CLIENTPRINTING_BACKEND>', 'choices': _config_backends, 'help': 'use given backend for accessing the client printing configuration, available backends on your system: %s (default: %s)' % (', '.join(_config_backends), _printing_backend_default), }, + ] + +if X2GOCLIENT_OS == 'Windows': + contrib_options = [ + {'args':['--start-xserver'], 'default': False, 'action': 'store_true', 'help': 'start the XServer before starting the session manager application, detect best XServer automatically, if more than one XServer is installed on your system', }, + {'args':['-X', '--preferred-xserver'], 'default': None, 'metavar': '<XSERVER>', 'choices': _known_xservers, 'help': 'start either of the currently supported XServers: %s -- make sure your preferred XServer is installed on your system' % _known_xservers, }, + {'args':['--start-pulseaudio'], 'default': False, 'action': 'store_true', 'help': 'start the PulseAudio server before starting the session manager application', }, + ] + +portable_options = [ + {'args':['--client-rootdir'], 'default': None, 'metavar': '</path/to/.x2goclient/dir>', 'help': 'define an alternative location where to find plain text config files (default: <HOME>/.x2goclient). This option will set ,,--backend-profiles FILE\'\', ,,--backend-clientsettings FILE\'\' and ,,--backend-clientprinting FILE\'\'', }, + {'args':['--sessions-rootdir'], 'default': None, 'metavar': '</path/to/.x2go/dir>', 'help': 'define an alternative location for session runtime files'}, + {'args':['--ssh-rootdir'], 'default': None, 'metavar': '</path/to/.ssh/dir>', 'help': 'define an alternative location for SSH files', }, + ] + + -- Alioth's /srv/git/_hooks_/post-receive-email on /srv/git/code.x2go.org/pyhoca-gui.git