Commit b51c620d authored by nextime's avatar nextime

Added 0.1 branch

parent de40190a
- change platform module calls with skylive.genutils.platform()
platform.system():
Solaris: 'SunOS'
Linux: 'Linux'
OSX: 'Darwin'
FreeBSD: 'FreeBSD'
Windows: 'Windows' or 'Microsoft'
OpenBSD: 'OpenBSD'
NetBSD: 'NetBSD'
#!/usr/bin/env python
#######################################
####### CONFIGURATION OPTIONS #########
#######################################
# main binary Name
NAME="skylive-ng"
# list of main python scripts (use python list!)
# WARNING: only the first one will be taken for OSX!!!
BASESCRIPTS=["skylive-ng.py", "fitsopener.py", "proxyconf.py"]
# version
VERSION="0.1.5"
# package description
DESCRIPTION="Skylive Client"
# Produce an optimized python bytecode (0,1,2)
OPTIMIZE=0
# Append all modules to the binary created (bool)
APPEND_TO_EXE=False
# Compression (bool)
COMPRESSION=True
# Compile as service for windows
# Use False for no services, a list ['Name', 'Name'] without extension
WINSERVICES=False
# Use windows console option instead of windows. Valid only if WINSERVICES is
# False and WX_GUI_PROGRAM is True
WINCONSOLE=False
# Use False for no daemons, a list ['Name', 'Name'] without extension
# This is cause if you need Windows Services, you can't specify
# it in basescripts, so, it need to be separated also for Unixes
UNIXDAEMONS=False
# build also MSI installer under windows platforms
WIN_BUILD_MSI=False
# Have this program a pycard/wxpython gui?
WX_GUI_PROGRAM=True
ICON="ICONA.ico"
# Can be False!
OSX_ICON="ICONA.icns"
# Run before to create the dmg, path relative to root of the tree
OSX_PRE_EXECUTE=['scripts/osx_createwrapper.sh']
# Run before makeself on linux
LINUX_PRE_EXECUTE=['scripts/linux_copygstreamer.sh']
# Files to be added to the root of the package (python list)
ADD_FILES = ['LICENSE.txt','README.txt', ICON,
'skyliveng.desktop', 'skylive-science.directory',
'skylive-ng.exe.manifest', 'VERSION.txt']
AUTHOR="Skylive Staff"
EMAIL="skylive@skylive.it"
URL="http://www.skylive.it"
LICENSE_TYPE="GPLv3"
# Modules that we need to exclude from our executable
EXCLUDES=['Tkinter']
#######################################
# Don't edit below this line #
#######################################
#
# TODO:
#
# Verificare la presenza dei requisiti
# per la creazione dell'installer ed in generale
# migliorare l'error management, magari anche con
# un log file
#
# TODO:
#
# Aggiungere la gestione di installer multilingua
#
# TODO:
#
# Gestire sotto Linux anche eventuale creazione di device
# per i chroot?
#
#
# XXX TODO:
#
# Verificare come si comporta sotto altri sistemi,
# come ad esempio BSD e/o Solaris
#
# XXX TODO:
#
# Gestire anche la creazione di pacchetti python classici?
#
# TODO:
#
# Creazione diretta anche di rpm e deb?
#
# TODO:
#
# gestione .app per OSX
#
# TODO:
#
# gestione 32/64bit e diverse architetture
#
# TODO:
#
# Cython support
#
########################################
# FUTURE IMPROVEMENTS
########################################
#
# - Use msilib to generate the MSI installer
#
# - Avoid the usage of ISS, implement an EXE generator
# based on the bdist_wininst distutils command?
#
# - under Linux, reimplement makeself in pure python
#
# - under Linux, reimplement ldd ans strip in pure python
#
# - reimplement whole things as a python module
#
# - use a config file to set variables and/or package
# description
#
########################################
########################################
# basic imports #
########################################
import platform
import os
from distutils.core import Command
from distutils.command import clean as distutils_clean
import sys, subprocess
########################################
# Setting variables and various things #
########################################
# This way we can run just ./setup.py to build
# the installer
if len(sys.argv) == 1:
sys.argv.append('create')
# Setting usefull paths
curdir = os.path.abspath(os.path.dirname(__file__))
srcdir = os.path.join(curdir, 'src')
distdir = os.path.join(curdir, 'dist')
scriptdir = os.path.join(curdir, 'scripts')
sys.path.append(srcdir)
# Change current dir to the root of the sources
os.chdir(curdir)
print 'Working in dir %s' % curdir
# Settings some lists of needed python packages to be included in our
# package
includes = ['encodings.ascii', 'encodings.utf_8', 'encodings.idna', 'encodings.iso8859_16']
includes += ['encodings.string_escape','Crypto.Hash.SHA', 'numpy', 'appcomponents.infohtmlwindow']
includes += ['appcomponents.ulist', 'appcomponents.image', 'encodings.latin_1', 'twisted.web.resource']
includes += ['appcomponents.container', 'pkg_resources']
languages = ['it', 'en']
for lang in languages:
includes.append('skylive.lang.'+lang)
# Put wx and pycard things in includes
if WX_GUI_PROGRAM:
pycardcomponents = [
'button',
'staticbox',
'statictext',
'textarea',
'textfield',
'passwordfield',
'list',
'notebook',
'combobox',
'spinner',
'checkbox',
'bitmapcanvas',
'slider',
'gauge'
]
pycardincludes = []
for component in pycardcomponents:
pycardincludes.append('Pycard.components.'+component)
includes += pycardincludes
wxincludes = []
wxcomponents = [
'_core'
]
for component in wxcomponents:
wxincludes.append('wx.'+component)
includes += wxincludes
# assure that our source dir is included in the search path of included modules
sys.path.append(srcdir)
########################################
# Utility functions #
########################################
def unix_shellcmd(cmd):
"""
Launch a subprocess in the unix shell
and return stdout of the command
(blocking!)
"""
ret = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
close_fds=True).communicate()[0]
return ret.split("\n")
def win_shellcmd(cmd):
"""
Launch a subprocess in win32
(blocking!)
"""
ret = subprocess.Popen(cmd)
ret.wait()
return
def cxf_guipackagedata(base):
"""
Collect GUI resource files and gui Images
to be copied in the package in the right format
for the include_files option in cx_freeze
Input:
str(base) - base (absolute) path of the package
Output:
a list of tuples with (src, target) files
where src is the absolute path of the source file,
target is the relative path inside the package
"""
ret = []
imgpath = os.path.join(base, 'gui', 'img')
guipath = os.path.join(base, 'gui')
for root, dirs, files in os.walk(imgpath):
if not '.svn' in root:
for file in files:
src = os.path.join(root, file)
target = os.path.join(root.replace(base, '')[1:], file)
ret.append((src, target))
for root, dirs, files in os.walk(guipath):
if not '.svn' in root:
for file in files:
if file[-8:] == '.rsrc.py':
src = os.path.join(root, file)
target = os.path.join(root.replace(base, '')[1:], file)
ret.append((src, target))
return ret
def add_dataFiles(base, compiler='cx_freeze'):
ret = []
if compiler == 'cx_freeze':
for file in ADD_FILES:
src = os.path.join(base, file)
target = file
ret.append((src, target))
elif compiler == 'py2exe' or compiler == 'py2app':
srcs = []
for file in ADD_FILES:
srcs.append(os.path.join(base, file))
ret.append(('.', srcs))
return ret
def p2exe_guipackagedata(base):
"""
Collect GUI resource files and gui images
to be copied in the package in the right
format for the data_files option in py2exe
"""
files = cxf_guipackagedata(base)
tdict = {}
for src, target in files:
if os.path.dirname(target) in tdict.keys():
tdict[os.path.dirname(target)].append(src)
else:
tdict[os.path.dirname(target)] = [src]
ret = []
for target in tdict.keys():
ret.append((target, tdict[target]))
return ret
########################################
# distutils commands #
########################################
class makeDmg(Command):
"""
Distutils command that take a .app
application and make a DMG compressed
image with the app and optionally
a README, INSTALL and LICENSE files.
"""
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
import shutil
print 'Test if we have license, readme or install files'
for name in os.listdir(srcdir):
if os.path.isfile(os.path.join(srcdir, name)) \
and (name[:6].upper() == 'README' or name[:7].upper() == 'LICENSE'
or name[:7].upper() == 'INSTALL'):
dst = os.path.join(distdir, name)
if not os.path.exists(dst):
print 'Copying ', name
shutil.copy(os.path.join(srcdir, name), os.path.join(distdir, name))
dmg = os.path.join(curdir, 'builds', 'osx', NAME+"-"+VERSION+"_OSX_universal.dmg")
if os.path.exists(dmg):
print 'Removing old dmg image'
os.remove(dmg)
print 'Creating new dmg image'
volname = NAME+"-"+VERSION
if len(OSX_PRE_EXECUTE) > 0:
for ex in OSX_PRE_EXECUTE:
unix_shellcmd(curdir+'/'+ex)
cmd = "hdiutil create -srcfolder %s -format UDZO -imagekey zlib-level=9 -volname %s %s" \
% (distdir, volname, dmg)
print unix_shellcmd(cmd)[0]
print 'Installer ready in '+os.path.join(curdir, 'builds', 'osx')+' directory'
class makeself(Command):
"""
Distutils command that take an open package directory
created by cx_freeze and create a .run self extracting
Linux/Posix executable installer with all
libraryes and dependencies inside the package using
standard tools like strip, ldd, makeself
"""
# TODO: Manage differencies between 32bit and 64bit systems
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
import shutil
libdir=os.path.join(distdir, 'lib')
os.mkdir(libdir)
if LINUX_PRE_EXECUTE and len(LINUX_PRE_EXECUTE) > 0:
print 'execute pre-installer script'
for lcommand in LINUX_PRE_EXECUTE:
print 'Executing '+lcommand+'...'
unix_shellcmd(lcommand+" "+distdir)
print 'OK'
print 'Finding all needed dynamic libraries and stripping binaryes'
bins = unix_shellcmd('find '+distdir+' -type f -name "*.so"')
bins.append(os.path.join(distdir, NAME))
libs = []
for bin in bins:
if bin:
ldd = unix_shellcmd("ldd "+bin)
if os.path.basename(bin) != NAME:
# If we strip our binary we lose zipped content!
unix_shellcmd("strip "+bin)
for lib in ldd:
if len(lib.split()) > 3:
libs.append(lib.split()[2])
elif len(lib.split()) == 3:
libs.append(os.path.join('/lib', lib.split()[0]))
elif len(lib.split()) == 2:
libs.append(lib.split()[0])
libs.sort()
libs = list(set(libs))
print 'copying needed libraries'
for lib in libs:
try:
shutil.copy(lib, libdir)
unix_shellcmd("strip "+os.path.join(libdir, os.path.basename(lib)))
except:
pass
print 'creating installer'
shutil.copy(os.path.join(scriptdir, 'linux_install.sh'), distdir)
os.chmod(os.path.join(distdir, 'linux_install.sh'), 0755)
runname = NAME+"-"+VERSION+"_"+platform.system()+"_i386-x86_64_install.run"
cmd = "makeself "+distdir+" "+runname
cmd += ' "'+NAME+' for '+platform.system()+' '+VERSION+'" ./linux_install.sh'
unix_shellcmd(cmd)
shutil.move(os.path.join(curdir, runname), os.path.join(curdir, 'builds', 'linux32'))
print 'remove dist directory'
shutil.rmtree(distdir)
print 'Installer ready in '+os.path.join(curdir, 'builds', 'linux32')+' directory'
class makeWininstall(Command):
"""
Distutils command that
get an open package created by py2exe and
make an exe and an optional msi windows
installer using InnoSetup
"""
# TODO: Manage differencies between 32bit and 64bit systems
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
print 'Creating .exe installer'
destpath = os.path.join(curdir, 'builds', 'win32')
fname = NAME+"-"+VERSION+"_Win32_install"
inopath = os.path.join(curdir, 'scripts', 'ino.iss')
win_shellcmd("ISCC /O%s /F%s %s" % (destpath, fname, inopath))
print '.exe installer ready in %s' % destpath
if WIN_BUILD_MSI:
licensefilertf = False
print 'a .msi installer is requested. Try to build it'
wixpath = os.getenv('WIX')
if not wixpath:
print 'WIX environment variable not set. Try to find the WIX path from the PATH environment variable'
for path in os.getenv('PATH').split(';'):
if os.path.exists(os.path.join(path, 'candle.exe')):
wixpath = path
break
if not wixpath:
print 'I can\'t find an usable WIX path. please set the WIX environment variable and re-execute '+sys.argv[0]
else:
print 'Checking for license file...'
if os.path.exists(os.path.join(curdir, 'dist', 'license.rtf')):
licensefilertf = True
else:
print 'RTF license file not found. Trying to generate it from the txt one'
try:
licensefile = LICENSE_FILE
except:
print 'LICENSE_FILE variable not set. Trying to autodetect one'
for file in ['LICENSE', 'LICENSE.txt', 'license.txt']:
if os.path.exists(os.path.join(curdir, 'dist', file)):
licensefile = file
break
if not licensefile:
print 'I can\'t find a suitable license file txt. Please supply one!'
else:
try:
import PyRTF
tfile = open(os.path.join(curdir, 'dist', licensefile), 'r')
tfilecont = tfile.read()
tfile.close()
doc = PyRTF.Document()
ss = doc.StyleSheet
section = PyRTF.Section()
doc.Sections.append(section)
section.append(tfilecont)
dr = PyRTF.Renderer()
fout = open(os.path.join(curdir, 'dist', 'license.rtf'), 'wb')
dr.Write(doc, fout)
fout.close()
licensefilertf = True
print 'RTF License file successfuly generated'
except:
print 'PyRTF not installed. I can\'t generate the license file!'
if licensefilertf:
fname = NAME+"-"+VERSION+"_Win32_install.msi"
wxspath = os.path.join(curdir, 'scripts', 'wix.wxs')
candlepath = os.path.join(wixpath, 'candle.exe')
print 'Compiling wxs with candle.exe'
win_shellcmd("%s %s" % (candlepath, wxspath))
print 'Linking with light.exe'
win_shellcmd("light.exe -out %s %s %s\wixui.wixlib -loc %s\WixUI_en-us.wxl"
% ( os.path.join(destpath, fname), os.path.join(curdir, 'wix.wixobj'),
wixpath, wixpath))
os.remove(os.path.join(curdir, 'wix.wixobj'))
print '.msi installer ready in %s' % destpath
class create(Command):
"""
Distutils command
detecting the platform and run
the right command sequence to produce
installers.
"""
user_options = []
def get_sub_commands(self):
plat = platform.system()
print 'Platform detected: ', plat
if plat == 'Linux':
return ['build', 'makeself']
elif plat == 'Darwin':
return ['py2app', 'makeDmg']
elif plat == 'Windows' or plat == 'Microsoft':
return ['py2exe', 'makeWininstall']
return False
# XXX Fare anche osx
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
print 'Creating right installer for this platform'
commands = self.get_sub_commands()
if commands:
self.run_command('clean')
for command in commands:
self.run_command(command)
else:
print 'i don\'t know what to do, sorry!'
class clean(distutils_clean.clean):
"""
Distutils command that override the default
clean command performing more clean actions
on the root path of the sources
"""
# XXX Deve rimuovere anche eventuali .c e .so/pyd da cython
paths = [
'MANIFEST',
'build',
'dist',
'wix.wixobj'
]
def run(self):
distutils_clean.clean.run(self)
for path in self.paths:
p = os.path.join(curdir, path)
if os.path.exists(p):
if os.path.isdir(p):
for root, dirs, files in os.walk(p, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
os.rmdir(root)
else:
os.remove(p)
########################################
# Setting different dicts for #
# distutils dependently of the #
# platform #
########################################
# Options for all systems
cmdclass = {
'clean': clean,
'create': create
}
# Options for Windows systems (with py2exe)
if platform.system() == 'Windows' or platform.system() == 'Microsoft':
from distutils.core import setup
import py2exe
if APPEND_TO_EXE:
ZIPFILE=None
includes+=['lxml._elementpath','lxml.ElementInclude']
setup_options = { 'py2exe': {
'includes':includes,
'excludes': EXCLUDES,
'optimize': OPTIMIZE,
'compressed': COMPRESSION
}
}
extra_options = {
'data_files': p2exe_guipackagedata(srcdir)+add_dataFiles(srcdir, 'py2exe')
}
if APPEND_TO_EXE:
extra_options['zipfile'] = None
#extra_options['bundle_files'] = 1
setup_options['py2exe']['bundle_files'] = 1
service = []
console = []
# XXX gestire meglio le icone
for bscript in BASESCRIPTS:
console.append({
'script': os.path.join(srcdir, bscript),
'icon_resource': [(1, os.path.join(srcdir, ICON))]
})
if WINSERVICES:
for bscript in WINSERVICES:
service.append({
'modules': 'src.'+bscript.replace('.py', ''),
'cmdline_style': 'pywin32'
})
if len(service) > 0:
extra_options['service'] = service
if len(console) > 0:
if WX_GUI_PROGRAM:
if WINCONSOLE:
extra_options['console'] = console
else:
extra_options['windows'] = console
else:
extra_options['console'] = console
# Override build_exe command to get some DLL included
origIsSytemDLL = py2exe.build_exe.isSystemDLL
def isSystemDLL(path):
if os.path.basename(path).lower() in ('gdiplus.dll', 'msvcp71.dll', 'msvcp90.dll', 'gdi32.dll') or \
os.path.basename(path).lower()[:5] in ('msvcp', 'msvcr') or \
os.path.basename(path).lower().endswith('pyd'):
print str(path)+" INCLUDED"
return 0
return origIsSytemDLL(path)
py2exe.build_exe.isSystemDLL = isSystemDLL
# Add specific command for windows installer
cmdclass['makeWininstall'] = makeWininstall
# Options for Mac OSX systems (with py2app)
elif platform.system() == 'Darwin':
from distutils.core import setup
import py2app
#cmdclass['makedmg'] = makedmg
executables = []
for bscript in BASESCRIPTS:
executables.append(os.path.join(srcdir, bscript))
if UNIXDAEMONS:
for bscript in UNIXDAEMONS:
executables.append(os.path.join(srcdir, bscript))
# py2app require the same format of py2exe
py2app_guipackagedata = p2exe_guipackagedata
# Multiple targets not (yet) supported by py2app
# get only the first one!
extra_options = {
'app': [executables[0]],
'setup_requires': ["py2app"],
'data_files': p2exe_guipackagedata(srcdir)+add_dataFiles(srcdir, 'py2app'),
}
setup_options = {
'py2app': {
'includes':includes,
'excludes': EXCLUDES,
'optimize': OPTIMIZE,
'plist': {},
'compressed': COMPRESSION,
'strip': True,
'dist_dir': distdir,
'site_packages': True,
'semi_standalone': False
}
}
if OSX_ICON:
setup_options['py2app']['iconfile'] = os.path.join(srcdir, OSX_ICON)
# Add specific command for creating a DMG Image
cmdclass['makeDmg'] = makeDmg
# Options for Linux (and maybe other posix?) systems (with cx_freeze)
else:
from cx_Freeze import setup, Executable
cmdclass['makeself'] = makeself
executables = []
for bscript in BASESCRIPTS:
executables.append(Executable(os.path.join(srcdir, bscript)))
if UNIXDAEMONS:
for bscript in UNIXDAEMONS:
executables.append(Executable(os.path.join(srcdir, bscript)))
extra_options = {
'executables': executables,
}
CREATE_SHARED_LIB=True
if APPEND_TO_EXE:
CREATE_SHARED_LIB=False
setup_options = {
'build': {
'build_exe': distdir
},
'build_exe': {
'optimize': OPTIMIZE,
'includes': includes,
'excludes': EXCLUDES,
'compressed': COMPRESSION,
'create_shared_zip': CREATE_SHARED_LIB,
'append_script_to_exe': APPEND_TO_EXE,
'icon': os.path.join(srcdir, ICON),
'include_files': cxf_guipackagedata(srcdir)+add_dataFiles(srcdir),
}
}
########################################
# Cython setup() declarations #
########################################
#if sys.argv[1] == 'create':
#
# XXX Qui inserire un controllo che verifica l'esistenza
# di file .pyx e nel caso usa cython per compilare
#
#try:
# from distutils.core import setup, Extension
# from Cython.Distutils import build_ext
#except:
# print 'Cython compilation required, but Cython not installed!'
# sys.exit(0)
########################################
# Distutils setup() declaration #
########################################
# TODO: Far configurare anche i classifiers
setup(
name = NAME,
version = VERSION,
description = DESCRIPTION,
author = AUTHOR,
author_email = EMAIL,
url = URL,
options = setup_options,
classifiers = [
'Developement Status :: 0.1.1 - Unstable',
'Environment :: Desktop GUI',
'Intended Audience :: Developers',
'Intended Audience :: End Users/Desktop',
'License :: '+LICENSE_TYPE,
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX :: GNU/Linux',
'Programming Language :: Python',
'Topic :: Communications',
],
cmdclass = cmdclass,
**extra_options
)
#!/bin/bash
find . -name '*~' -exec rm {} \;
find . -name '*.pyc' -exec rm {} \;
skyliveng (0.1.5-1) unstable; urgency=low
* New Release
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Tue, 26 May 2009 17:14:33 +0200
skyliveng (0.1.3-1) unstable; urgency=low
* New release
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Thu, 12 Feb 2009 14:48:51 +0100
skyliveng (0.1.2-2) unstable; urgency=low
* New release.
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Thu, 29 Jan 2009 15:15:37 +0100
skyliveng (0.1.2-1) unstable; urgency=low
* New release
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Thu, 11 Dec 2008 21:03:38 +0100
skyliveng (0.1-7) unstable; urgency=low
* Renumbering version
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Sun, 29 Jun 2008 18:14:25 +0200
skyliveng (0.1rc6-1) unstable; urgency=low
* new Release
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Sun, 29 Jun 2008 18:11:49 +0200
skyliveng (0.1rc5-3) unstable; urgency=low
* Menus!
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Sun, 29 Jun 2008 18:02:59 +0200
skyliveng (0.1rc5-2) unstable; urgency=low
* Bugfix
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Sun, 29 Jun 2008 17:16:58 +0200
skyliveng (0.1RC5-1) unstable; urgency=low
* New upstream release
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Sun, 29 Jun 2008 17:06:33 +0200
skyliveng (0.1b-1) unstable; urgency=low
* New upstream release
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Mon, 18 Feb 2008 02:00:23 +0100
skyliveng (0.1-6) unstable; urgency=low
* Added python-imaging dependency
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Tue, 18 Dec 2007 15:07:44 +0100
skyliveng (0.1-5) unstable; urgency=low
* Nocomment.
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Mon, 17 Dec 2007 22:48:50 +0100
skyliveng (0.1-4) unstable; urgency=low
* I hope this is the latest bug
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Mon, 17 Dec 2007 22:40:51 +0100
skyliveng (0.1-3) unstable; urgency=low
* Another one
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Mon, 17 Dec 2007 22:34:28 +0100
skyliveng (0.1-2) unstable; urgency=low
* Fix dependency bug
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Mon, 17 Dec 2007 22:26:52 +0100
skyliveng (0.1-1) unstable; urgency=low
* Initial release
-- Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it> Mon, 17 Dec 2007 22:04:32 +0100
Source: skyliveng
Section: astronomy
Priority: extra
Maintainer: Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it>
Build-Depends: debhelper (>= 5)
Standards-Version: 3.7.2
Package: skyliveng
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, python, python-wxgtk2.6|python-wxgtk2.8, python-crypto, python-pycard, python-pyfits, python-imaging, python-numpy, python-twisted, python-openssl|python-pyopenssl, python-lxml, python-gst0.10, gstreamer0.10-fluendo-mp3, liboggz1, libgnomevfs2-extra
Suggests: python-psyco
Description: Skylive client (www.skylive.it)
Skylive project client to administer remote telescopes
of skylive (www.skylive.it)
This package was debianized by unknown <Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it>> on
Mon, 17 Dec 2007 22:04:32 +0100.
It was downloaded from http://www.astronomix.org/trac/wiki/SkyliveNG
Upstream Author(s):
Franco Lanza <nextime@nexlab.it>
Sandro Aliano <ita595@hotmail.com>
Copyright:
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
License:
GPLv3: read the file /usr/share/doc/skyliveng/LICENSE.txt
The Debian packaging is (C) 2007, unknown <Unixmedia S.r.l. (Medianix Devel) <devel@unixmedia.it>> and
is licensed under the GPL, see `/usr/share/common-licenses/GPL'.
# Please also look if there are files or directories which have a
# different copyright/license attached and list them here.
usr/bin
usr/share
usr/share/applications
src/LICENSE.txt
src/README.txt
#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
touch configure-stamp
build: build-stamp
build-stamp: configure-stamp
dh_testdir
# Add here commands to compile the package.
#$(MAKE)
#docbook-to-man debian/skyliveng.sgml > skyliveng.1
touch $@
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
# Add here commands to clean up after the build process.
#-$(MAKE) clean
dh_clean
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
# Add here commands to install the package into debian/skyliveng.
#$(MAKE) DESTDIR=$(CURDIR)/debian/skyliveng install
mkdir -p $(CURDIR)/debian/skyliveng/usr/share/skylive
cp -ap $(CURDIR)/src/appcomponents $(CURDIR)/src/gui $(CURDIR)/src/ICONA.ico \
$(CURDIR)/src/proxyconf.py $(CURDIR)/src/skylive-ng.py $(CURDIR)/src/fitsopener.py \
$(CURDIR)/debian/skyliveng/usr/share/skylive/
cp -ap $(CURDIR)/src/gui $(CURDIR)/src/skylive \
$(CURDIR)/debian/skyliveng/usr/share/skylive/
cp -ap $(CURDIR)/debian/skylive.sh $(CURDIR)/debian/skyliveng/usr/bin/skylive
chmod +x $(CURDIR)/debian/skyliveng/usr/bin/skylive
cp -ap $(CURDIR)/src/skyliveng.desktop $(CURDIR)/debian/skyliveng/usr/share/applications
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
dh_installchangelogs
dh_installdocs
dh_installexamples
# dh_install
dh_installmenu
dh_desktop
# dh_installdebconf
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_python
# dh_installinit
# dh_installcron
# dh_installinfo
dh_installman
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_perl
# dh_makeshlibs
dh_installdeb
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure
#!/bin/sh
cd /usr/share/skylive
./skylive-ng.py $@ > /dev/null 2>&1
?package(skyliveng):needs="X11" section="Applications/Science/Astronomy"\
title="SkyLive NG" command="/usr/bin/skylive"
HTTP Transport for the Skylive Protocol overview:
-------------------------------------------------
CLIENT SERVER
=================================================================|
_________________________________________ |
| |
------ GET /new -------> | Initialization new |
<----- TOKEN ------------ | connection | Request for a new
_________________________________________| | Connection
|
_________________________________________ |
| |
------ POST /auth -------> | Authentication |
<-------- OK|kO ---------- | phase |
_________________________________________| |
|
============================================================================================
_________________________________________ |
| |
------ POST /client -----> | Client -> Server |
<-------- OK|KO -------- | communication channel | Connection established
_________________________________________| | data channels
|
_________________________________________ |
| |
------ POST /server -----> | Server -> Client |
<-------- DATA ----------- | communication channel |
_________________________________________| |
|
=================================================================|
Description:
All the requests are encapsulated in a XML protocol to be definied.
Now we will use some example tags, they are not stable now.
Note: we use an authentication mechanism to establish our tunnel not for the real
communication of user credential, but only to get a way to generate a key for
encrypt the data inside the tunnel with a know key for both the peers without
passing it on in clear text on the tunnel layer.
To do this we need to have something that both parts know before they
try to establish a connection, and the only secrets things they know
are the username ( that can't be used alone cause it pass over the protocol
in clear text) and the hash of the password ( that never pass in clear ).
Other transport (like the SSL/TLS one) can't need to pass
user/password information, so, the encapsulated protocol
will need another and indipendent authentication mechanism.
Maybe we will try to find another solution in future.
Note 2: we try to use HTTP/1.1 to get more probability to
have a working Keep-Alive HTTP support by our proxy.
------------------------------
Initialization new connection:
------------------------------
* Client Request:
---------------
GET /new HTTP/1.1
- Only to start a new connection.
* Server response:
----------------
<response><token>TOKEN</token></response>
- TOKEN is an unique id generated by the server and used by the client
to identify a unique "connection". it is generated
---------------------
Authentication phase:
---------------------
* Client Request:
---------------
POST /auth HTTP/1.1
- Data:
o token=TOKEN (the one generated by the server in initialization)
o user=USERNAME
o hash=HASH (where HASH is the md5sum of a string composed
by the TOKEN, USERNAME and the storated hash of the password)
* Server Response:
----------------
<response><auth>OK|KO</auth></response>
------------------------------
Data channel Client -> Server:
------------------------------
The client make a request that emulate a POST of a file with a fixed size.
When the size of the transfer will reach the size limit or if the upload in any way
blocked and the connection goes down, it will re-establish a new one
in a loop.
Also, we will maybe need to have a sort of keep-alive "ping-pong" system, but it can be
demanded on the encapsulated protocol, like a sort of error correction and/or
checksum for every bit of real communication in the encapsulated protocol.
* Client Request:
---------------
POST /client HTTP/1.1
- Data:
o token=TOKEN
o data=DATA (where DATA is our encapsulated protocol encrypted with AES256 and encryption key
generated by md5sum of token+hash of the password, packetized(1) and in base64)
* Server Response:
----------------
<response><client>OK|NO</client></response>
------------------------------
Data channel Server -> Client:
------------------------------
The client make a request that emulate the download of a big file. It is the exact
opposite with the client->server data channel, but with the same checksum, ping and other
considerations.
* Client Request:
---------------
POST /server HTTP/1.1
- Data:
o token=TOKEN
o data=DATA (where DATA is used to check the identity of the client and is
the token+the hash of the password encrypted in aes256 using the md5sum of
the token+username+the hash of the password as key for encryption
in base64)
* Server Response:
----------------
an emulated file download stream of the data encrypted with aes256 with the md5sum of
token+hash of the password as key, packetized(1) and in base64
--------------------
NOTE #1. Packetized:
--------------------
We choose to encrypt our data cause is the best way to be sure that noone can takeover our tunnel.
If we want to bypass at leas any proxy, we can't simply use SSL/TLS, cause
we need to appears to the proxy like a normal http request in clear text, at least
more close to a normal http stream that we can.
every splice of data is encrypted in AES256. As we don't know the exact lenght of any
splice of data, and aes256 can't decrypted dinamically, we need another way to
know when to decrypt our data.
So, we will "packetize" it in our data stream by converting every packet to
base64, and we insert a separator to let's both client and server recognize where a packet
is complete and need to be decrypted.
TODO: Choose a separator!
ISSUE: won't this way to transport data add too many overhead? Isn't better to simply
use connectSSL on the client and listenSSL on the server, and encapsulate the
stream a clear text simple http tunnel? But this way, how we can have the client ip
on the server side?
just a TCP connection over SSL
using listenSSL and connectSSL
twisted reactor methods instead of
listenTCP and connectTCP.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>XiphQT</string>
<key>CFBundleGetInfoString</key>
<string>Xiph QuickTime Components 0.1.8, Copyright © 2005-2007 Arek Korbik</string>
<key>CFBundleIdentifier</key>
<string>org.xiph.xiph-qt.xiphqt</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>0.1.8</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.1.8</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Xiph QuickTime Components 0.1.8, Copyright © 2005-2007 Arek Korbik</string>
</dict>
</plist>
B/* Localized versions of Info.plist keys */ B/* Localized versions of Info.plist keys */
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Vorbis-to-MD</key>
<dict>
<key>ALBUM=</key>
<string>albm</string>
<key>ARTIST=</key>
<string>arts</string>
<key>COMMENT=</key>
<string>cmmt</string>
<key>COPYRIGHT=</key>
<string>cprt</string>
<key>DATE=</key>
<string>©day</string>
<key>DESCRIPTION=</key>
<string>desc</string>
<key>ENCODEDBY=</key>
<string>soft</string>
<key>GENRE=</key>
<string>genr</string>
<key>ORGANIZATION=</key>
<string>prod</string>
<key>PERFORMER=</key>
<string>perf</string>
<key>TITLE=</key>
<string>name</string>
<key>TRANSCODEDFROM=</key>
<string>orif</string>
<key>YEAR=</key>
<string>©day</string>
<key>LICENSE=</key>
<string>info</string>
<key>CONTACT=</key>
<string>info</string>
<key>ISRC=</key>
<string>info</string>
</dict>
<key>Vorbis-to-UD</key>
<dict>
<key>ALBUM=</key>
<string>©alb</string>
<key>ARTIST=</key>
<string>©ART</string>
<key>COMMENT=</key>
<string>©cmt</string>
<key>COPYRIGHT=</key>
<string>©cpy</string>
<key>DATE=</key>
<string>©day</string>
<key>DESCRIPTION=</key>
<string>©des</string>
<key>ENCODEDBY=</key>
<string>©enc</string>
<key>GENRE=</key>
<string>©gen</string>
<key>LICENSE=</key>
<string>©dis</string>
<key>ORGANIZATION=</key>
<string>©prd</string>
<key>PERFORMER=</key>
<string>©prf</string>
<key>TITLE=</key>
<string>©nam</string>
<key>TRACKNUMBER=</key>
<string>©trk</string>
<key>TRANSCODEDFROM=</key>
<string>©fmt</string>
<key>YEAR=</key>
<string>©day</string>
<key>CONTACT=</key>
<string>©inf</string>
<key>ISRC=</key>
<string>©inf</string>
</dict>
<key>other--or--not-used-a_t_m_</key>
<dict>
<key>TRACKNUMBER=</key>
<string>????</string>
<key>LICENSE=</key>
<string>????</string>
<key>CONTACT=</key>
<string>????</string>
<key>ISRC=</key>
<string>????</string>
<key>VERSION=</key>
<string>????</string>
<key>LOCATION=</key>
<string>????</string>
</dict>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>69 63 356 240 0 0 1280 832 </string>
<key>IBFramework Version</key>
<string>446.1</string>
<key>IBOldestOS</key>
<integer>4</integer>
<key>IBOpenObjects</key>
<array>
<integer>166</integer>
</array>
<key>IBSystem Version</key>
<string>8L127</string>
<key>IBUserGuides</key>
<dict>
<key>166</key>
<dict>
<key>guideLocations</key>
<array>
<string>Vertical:90.000000</string>
</array>
<key>guidesLocked</key>
<false/>
</dict>
</dict>
<key>targetFramework</key>
<string>IBCarbonFramework</string>
</dict>
</plist>
<?xml version="1.0" standalone="yes"?>
<object class="NSIBObjectData">
<string name="targetFramework">IBCarbonFramework</string>
<object name="rootObject" class="NSCustomObject" id="1">
<string name="customClass">NSApplication</string>
</object>
<array count="8" name="allObjects">
<object class="IBCarbonWindow" id="166">
<string name="windowRect">166 334 288 756 </string>
<string name="title">Ogg Exporter Settings</string>
<object name="rootControl" class="IBCarbonRootControl" id="167">
<string name="bounds">0 0 122 422 </string>
<string name="viewFrame">0 0 422 122 </string>
<array count="6" name="subviews">
<object class="IBCarbonButton" id="182">
<string name="bounds">21 90 41 182 </string>
<string name="viewFrame">90 21 92 20 </string>
<ostype name="controlSignature">XiOE</ostype>
<int name="controlID">3</int>
<string name="title">Settings…</string>
<ostype name="command">OEcv</ostype>
<object name="layoutInfo" class="IBCarbonHILayoutInfo">
<int name="bindingLeftKind">1</int>
</object>
</object>
<object class="IBCarbonButton" id="183">
<string name="bounds">53 90 73 182 </string>
<string name="viewFrame">90 53 92 20 </string>
<ostype name="controlSignature">XiOE</ostype>
<int name="controlID">4</int>
<string name="title">Settings…</string>
<ostype name="command">OEca</ostype>
<object name="layoutInfo" class="IBCarbonHILayoutInfo">
<int name="bindingLeftKind">1</int>
</object>
</object>
<object class="IBCarbonButton" id="181">
<string name="bounds">82 252 102 321 </string>
<string name="viewFrame">252 82 69 20 </string>
<int name="controlID">2</int>
<string name="title">Cancel</string>
<ostype name="command">not!</ostype>
<object name="layoutInfo" class="IBCarbonHILayoutInfo">
<int name="bindingBottomKind">2</int>
<int name="bindingRightKind">2</int>
</object>
<int name="buttonType">2</int>
</object>
<object class="IBCarbonButton" id="180">
<string name="bounds">82 333 102 402 </string>
<string name="viewFrame">333 82 69 20 </string>
<int name="controlID">1</int>
<string name="title">OK</string>
<ostype name="command">ok </ostype>
<object name="layoutInfo" class="IBCarbonHILayoutInfo">
<int name="bindingBottomKind">2</int>
<int name="bindingRightKind">2</int>
</object>
<int name="buttonType">1</int>
</object>
<object class="IBCarbonCheckBox" id="184">
<string name="bounds">22 20 40 79 </string>
<string name="viewFrame">20 22 59 18 </string>
<ostype name="controlSignature">XiOE</ostype>
<int name="controlID">5</int>
<string name="title">Video</string>
<ostype name="command">OEev</ostype>
<int name="initialState">1</int>
<boolean name="autoToggle">FALSE</boolean>
</object>
<object class="IBCarbonCheckBox" id="185">
<string name="bounds">54 20 72 79 </string>
<string name="viewFrame">20 54 59 18 </string>
<ostype name="controlSignature">XiOE</ostype>
<int name="controlID">6</int>
<string name="title">Audio</string>
<ostype name="command">OEea</ostype>
<int name="initialState">1</int>
<boolean name="autoToggle">FALSE</boolean>
</object>
</array>
</object>
<boolean name="receiveUpdates">FALSE</boolean>
<boolean name="isResizable">FALSE</boolean>
<boolean name="compositing">TRUE</boolean>
<int name="carbonWindowClass">4</int>
<int name="windowPosition">7</int>
</object>
<reference idRef="167"/>
<reference idRef="180"/>
<reference idRef="181"/>
<reference idRef="182"/>
<reference idRef="183"/>
<reference idRef="184"/>
<reference idRef="185"/>
</array>
<array count="8" name="allParents">
<reference idRef="1"/>
<reference idRef="166"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
<reference idRef="167"/>
</array>
<dictionary count="2" name="nameTable">
<string>File&apos;s Owner</string>
<reference idRef="1"/>
<string>Settings</string>
<reference idRef="166"/>
</dictionary>
<unsigned_int name="nextObjectID">186</unsigned_int>
</object>
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
[Setup]
AppName=Skylive-NG
AppVerName=Skylive-NG 0.1.5
AppPublisher=Skylive
AppPublisherURL=http://www.skylive.it/
AppSupportURL=http://www.skylive.it/
AppUpdatesURL=http://www.skylive.it/
DefaultDirName={pf}\Skylive-NG
DefaultGroupName=Skylive-NG
LicenseFile=..\dist\LICENSE.txt
OutputBaseFilename=SkyliveNG-0.1.5_Win32_install
SetupIconFile=..\dist\ICONA.ico
Compression=lzma/ultra
VersionInfoVersion=0.1.5.5
SolidCompression=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}";
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}";
; Temporaneo
[InstallDelete]
Type: filesandordirs; Name: "{app}\skylive"
Type: files; Name: "{app}\skylive*"
Type: files; Name: "{app}\*rsrc.py"
[Files]
Source: "..\scripts\kill.exe"; DestDir: "{tmp}"; AfterInstall: killProc
Source: "..\scripts\oggcodecs.exe"; DestDir: "{tmp}"; AfterInstall: InstallVorbis
Source: "..\dist\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons]
Name: "{group}\Skylive-NG"; Filename: "{app}\skylive-ng.exe"; WorkingDir: "{app}"; IconFilename: "{app}\ICONA.ico"
Name: "{group}\{cm:ProgramOnTheWeb,Skylive-NG}"; Filename: "http://www.skylive.it/"
Name: "{group}\{cm:UninstallProgram,Skylive-NG}"; Filename: "{uninstallexe}"
Name: "{commondesktop}\Skylive-NG"; Filename: "{app}\skylive-ng.exe"; Tasks: desktopicon; WorkingDir: "{app}"; IconFilename: "{app}\ICONA.ico"
Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\Skylive-NG"; Filename: "{app}\skylive-ng.exe"; Tasks: quicklaunchicon; WorkingDir: "{app}"; IconFilename: "{app}\ICONA.ico"
[Run]
Filename: "{app}\README.txt"; Description: "Read README.txt"; Flags: shellexec nowait skipifsilent unchecked
Filename: "{app}\skylive-ng.exe"; Description: "{cm:LaunchProgram,Skylive-NG}"; Flags: nowait postinstall
[Code]
procedure killProc();
var
ReturnCode: Integer;
begin
Exec(ExpandConstant('{tmp}\kill.exe'), 'skylive-ng.exe', '', SW_HIDE, ewWaitUntilTerminated, ReturnCode);
end;
procedure InstallVorbis();
var
ReturnCode: Integer;
begin
Exec(ExpandConstant('{tmp}\oggcodecs.exe'), '/S', '', SW_HIDE, ewWaitUntilTerminated, ReturnCode);
end;
#!/bin/bash
cp -rp /usr/lib/libgst* $1/lib/
cp -rp /usr/lib/gstreamer* $1/lib/
rm $1/lib/gstreamer*/libgstgconfelements.so
cp -rp /usr/lib/libgnomevfs-2.so* $1/lib/
mkdir -p $1/usr/share
cp -rp /usr/share/gstreamer* $1/usr/share/
mkdir -p $1/lib/gnome-vfs-2.0/
cp -rp /usr/lib/gnome-vfs-2.0/modules/ $1/lib/gnome-vfs-2.0/modules/
cp -rp /lib/libnss* $1/lib/
#!/bin/sh
up="NO"
root="NO"
if [ "$UID" = "0" ] ; then
root="SI"
fi
if [ "$1" = "UPGRADE" ] ; then
root="NO"
up="SI"
fi
if [ "$up" = "NO" ] ; then
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
echo
echo " SkyliveNG V 0.1.4 Installer"
echo
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
echo
fi
ask_yn()
{
if [ -n "$1" ] ; then
question=$1
if [ -n "$2" ] ; then
def="$2"
else
def="N"
fi
don=""
resp="$def"
while [ x"$don" = x"" ] ; do
read -p "$question ($def) " userinput
if [ x"$userinput" != x"" ] ; then
resp=$userinput
else
resp=$def
fi
case "$resp" in
y|Y|yes|Yes)
ret=0
don="Y"
;;
n|N|no|No)
don="Y"
ret=1
;;
esac
done
return $ret
fi
}
cancel()
{
if [ -n $1 ] ; then
echo "$1"
fi
exit 0
}
if [ "$up" = "NO" ] ; then
question="Do you want to install SkyliveNG client?"
ask_yn "$question" "N" || cancel "Cancelling."
if [ -f LICENSE.txt ] ; then
cat LICENSE.txt | more
question="Do you accept the License?"
ask_yn "$question" "N" || cancel "Cancelling."
fi
fi
if [ "$root" = "SI" ] ; then
skpath="/usr/share/skylive"
if [ -d /usr/bin ] ; then
d="/usr/bin"
else
d="/bin"
fi
else
skpath="$HOME/.SkyLIVE"
fi
if [ -d "${skpath}" ] ; then
if [ "$up" = "NO" ] ; then
echo "The installer has detected another skyliveng installation."
question="Would you like to override the old install?"
ask_yn "$question" "N" || cancel "Cancelling."
fi
rm -rf ${skpath}
if [ "$root" = "SI" ] ; then
rm -f $d/skylive
fi
fi
if [ "$up" = "NO" ] ; then
echo -n "Copying files... "
fi
mkdir -p ${skpath}
cp -r ./* ${skpath}
if [ "$up" = "NO" ] ; then
echo "OK"
fi
if [ "$up" = "NO" ] ; then
echo -n "Fixing permission... "
fi
chmod +x ${skpath}/skylive-ng
if [ "$up" = "NO" ] ; then
echo "OK"
fi
if [ "$up" = "NO" ] ; then
echo -n "Generating launcher wrapper... "
fi
if [ "$root" = "SI" ] ; then
cat > $d/skylive << EOF
#!/bin/sh
if [ -f "\$HOME/.SkyLIVE/skylivengWrap" ] ; then
u="NO"
if [ -f "\$HOME/.SkyLIVE/VERSION.txt" ] ; then
if [ -f "/usr/share/skylive/VERSION.txt" ] ; then
rv=\$(cat /usr/share/skylive/VERSION.txt)
uv=\$(cat "\$HOME/.SkyLIVE/VERSION.txt")
if [ "\$uv" -gt "\$rv" ] ; then
u="OK"
fi
else
u="OK"
fi
fi
else
u="NO"
fi
if [ "\$u" = "OK" ] ; then
. \$HOME/.SkyLIVE/skylivengWrap
else
if [ ! -h "\$HOME/Desktop/skyliveng.desktop" ] ; then
ln -s /usr/share/skylive/skyliveng.desktop \$HOME/Desktop/skyliveng.desktop
fi
SKYPATH=/usr/share/skylive
SKYLINKER=\$SKYPATH/lib/ld-linux.so.2
cd "\$SKYPATH"
export GSTREAMER_PLUGIN_SYSTEM_PATH="\$SKYPATH/lib/gstreamer-0.10"
export GST_PLUGIN_SYSTEM_PATH="\${GSTREAMER_PLUGIN_SYSTEM_PATH}"
export GNOME_VFS_MODULE_PATH="\$SKYPATH/lib/gnome-vfs-2.0/modules/"
LD_LIBRARY_PATH=\$SKYPATH:\$SKYPATH/lib \$SKYLINKER ./skylive-ng \$@ >/dev/null 2>&1
fi
EOF
chmod +x $d/skylive
else
cat > ${skpath}/skylivengWrap << EOF
#!/bin/sh
SKYPATH=${skpath}
SKYLINKER=\$SKYPATH/lib/ld-linux.so.2
cd "\$SKYPATH"
export GSTREAMER_PLUGIN_SYSTEM_PATH="\$SKYPATH/lib/gstreamer-0.10"
export GST_PLUGIN_SYSTEM_PATH="\${GSTREAMER_PLUGIN_SYSTEM_PATH}"
export GNOME_VFS_MODULE_PATH="\$SKYPATH/lib/gnome-vfs-2.0/modules/"
LD_LIBRARY_PATH=\$SKYPATH:\$SKYPATH/lib \$SKYLINKER ./skylive-ng \$@ >/dev/null 2>&1
EOF
chmod +x ${skpath}/skylivengWrap
fi
if [ "$up" = "NO" ] ; then
echo "OK"
fi
if [ "$up" = "NO" ] ; then
echo -n "Trying to install .desktop file..."
fi
desk="NO"
if [ "$root" = "SI" ] ; then
if [ -d "/usr/share/applications" ] ; then
rm -f /usr/share/applications/skyliveng.desktop
ln -s /usr/share/skylive/skyliveng.desktop /usr/share/applications/skyliveng.desktop
desk="SI"
fi
else
cat > ${skpath}/skyliveng.desktop << EOF
[Desktop Entry]
Name=SkyLiveNG
Exec=${skpath}/skylivengWrap
Icon=${skpath}/ICONA.ico
Categories=Science;Astronomy;Education;
EOF
if [ -d $HOME/Desktop/ ] ; then
rm -f $HOME/Desktop/skyliveng.desktop
ln -s ${skpath}/skyliveng.desktop $HOME/Desktop/skyliveng.desktop
desk="SI"
fi
if [ "$desk" != "SI" ] ; then
xdg=`which xdg-desktop-icon`
if [ x"$xdg" != x"" ] ; then
xdg-desktop-icon install --novendor ${skpath}/skyliveng.desktop
desk="SI"
fi
fi
fi
if [ "$up" = "NO" ] ; then
if [ "$desk" = "SI" ] ; then
echo "OK"
else
echo "No. I can't."
fi
fi
if [ "$up" = "NO" ] ; then
echo -n "Trying to install menu entry..."
fi
me="NO"
if [ "$root" = "SI" ] ; then
xdg=`which xdg-desktop-menu`
if [ x"$xdg" != x"" ] ; then
export XDG_UTILS_INSTALL_MODE="system"
xdg-desktop-menu install --novendor --mode system ${skpath}/skylive-science.directory ${skpath}/skyliveng.desktop
me="SI"
fi
else
xdg=`which xdg-desktop-menu`
if [ x"$xdg" != x"" ] ; then
export XDG_UTILS_INSTALL_MODE="user"
xdg-desktop-menu install --novendor --mode user ${skpath}/skylive-science.directory ${skpath}/skyliveng.desktop
me="SI"
fi
fi
if [ "$up" = "NO" ] ; then
if [ "$me" = "SI" ] ; then
echo "OK"
else
echo "No. I can't."
fi
fi
if [ "$up" = "NO" ] ; then
echo -n "Cleaning installer..."
fi
rm -f ${skpath}/linux_install.sh
if [ "$up" = "NO" ] ; then
echo "OK"
echo
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
echo " "
if [ "$root" = "SI" ] ; then
echo " Installation finished. Launch \"$d/skylive\" to run the client. "
else
echo " Installation finished. Launch \"${skpath}/skylivengWrap\" to run the client "
fi
echo " For more informations, look at the \"$skpath/README.txt\" file. "
echo " "
echo "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
echo
else
setsid ${skpath}/skylivengWrap
fi
#!/bin/sh
base=$(dirname ${0})
cp ${base}/osx_upgrade.sh ${base}/../dist/UPGRADE.sh
#mv ${base}/../dist/skylive-ng.app/Contents/MacOS/skylive-ng ${base}/../dist/skylive-ng.app/Contents/MacOS/skylive-ng.bin
#cp ${base}/osx_wrapper.sh ${base}/../dist/skylive-ng.app/Contents/MacOS/skylive-ng
cp ${base}/../src/VERSION.txt ${base}/../dist/skylive-ng.app/Contents/MacOS/VERSION.txt
cp -R ${base}/XiphQT.component ${base}/../dist/skylive-ng.app/
#!/bin/bash
cd /
sleep 5
volname=${1}
base=${volname}
echo "start ${base}, ${HOME}" > /tmp/SkyliveUpgrade.log
if [ -f "${HOME}/.SkyLIVE.app" ] ; then
echo "Removing Old client" >> /tmp/SkyliveUpgrade.log
rm -rf "${HOME}/.SkyLIVE.app" >> /tmp/SkyliveUpgrade.log 2>&1
fi
cp -r ${base}/skylive-ng.app "${HOME}/.SkyLIVE.app" >> /tmp/SkyliveUpgrade.log 2>&1
#mv "${HOME}/.SkyLIVE.app/Contents/MacOS/skylive-ng.bin" "${HOME}/.SkyLIVE.app/Contents/MacOS/skylive-ng" >> /tmp/SkyliveUpgrade.log 2>&1
hdiutil detach ${volname} >> /tmp/SkyliveUpgrade.log 2>&1
${HOME}/.SkyLIVE.app/Contents/MacOS/skylive-ng &
echo "Launched" >> /tmp/SkyliveUpgrade.log
disown %1
#!/bin/bash
u="NO"
ME=$(dirname ${0})
if [ -f "${HOME}/.SkyLIVE.app/Contents/MacOS/skylive-ng" ] ; then
if [ -f "${HOME}/.SkyLIVE.app/Contents/MacOS/VERSION.txt" ] ; then
if [ -f "${ME}/VERSION.txt" ] ; then
rv=$(cat "${ME}/VERSION.txt")
uv=$(cat "${HOME}/.SkyLIVE.app/Contents/MacOS/VERSION.txt")
if [ "$uv" -gt "$rv" ] ; then
u="OK"
fi
else
u="OK"
fi
fi
fi
if [ "$u" = "OK" ] ; then
${HOME}/.SkyLIVE/Contents/MacOS/skylive-ng $@ &
disown %1
else
${ME}/skylive-ng.bin $@ &
disown %1
fi
<?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2003/01/wi'>
<Product Name='SkyliveNG' Id='B601BDB8-FF67-4337-8D64-C6F043C92F90' UpgradeCode='A7B57310-7B87-43D1-95AD-611E7A900EE4' Language='1033' Codepage='1252' Version='0.1.2.0' Manufacturer='SkyliveStaff'>
<Package Id='????????-????-????-????-????????????' Keywords='Installer' Description='SkyliveNG' Comments='Skylive Client' Manufacturer='SkyliveStaff' InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' />
<Property Id='INSTALLLEVEL' Value='999' />
<Directory Id='TARGETDIR' Name='SourceDir'>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<Directory Id='id2' Name='id3' LongName='Skylive'>
<Directory Id='INSTALLDIR' Name='Skylive'>
<Directory Id='id5' Name='gui'>
<Directory Id='id6' Name='img'>
<Component Id='Main_id7' Guid='97EB1E11-99BC-4C43-B519-63789F7482FE'>
<File Id='id8' Name='ide.jpg' LongName='Guide.jpg' Source='dist\gui\img\Guide.jpg' DiskId='1' />
<File Id='id9' Name='ONA.ico' LongName='ICONA.ico' Source='dist\gui\img\ICONA.ico' DiskId='1' />
<File Id='id10' Name='ive.jpg' LongName='Live.jpg' Source='dist\gui\img\Live.jpg' DiskId='1' />
<File Id='id96' Name='ash.jpg' LongName='Live.jpg' Source='dist\gui\img\splash.jpg' DiskId='1' />
<RemoveFile Id='id11' On='uninstall' Name='*.*' />
<RemoveFolder Id='id6' On='uninstall' />
</Component>
</Directory>
<Directory Id='id12' Name='ettings' LongName='settings'>
<Component Id='ain_id13' Guid='B4FDBB78-7209-497A-825E-1D5AE908F53A'>
<File Id='id14' Name='rsrc.py' LongName='extra.rsrc.py' Source='dist\gui\settings\extra.rsrc.py' DiskId='1' />
<File Id='id15' Name='rsrc.py' LongName='langs.rsrc.py' Source='dist\gui\settings\langs.rsrc.py' DiskId='1' />
<File Id='id16' Name='rsrc.py' LongName='pointer.rsrc.py' Source='dist\gui\settings\pointer.rsrc.py' DiskId='1' />
<File Id='id17' Name='rsrc.py' LongName='proxyconf.rsrc.py' Source='dist\gui\settings\proxyconf.rsrc.py' DiskId='1' />
<File Id='id18' Name='rsrc.py' LongName='pvt.rsrc.py' Source='dist\gui\settings\pvt.rsrc.py' DiskId='1' />
<File Id='id19' Name='rsrc.py' LongName='settings.rsrc.py' Source='dist\gui\settings\settings.rsrc.py' DiskId='1' />
<File Id='id20' Name='rsrc.py' LongName='textsize.rsrc.py' Source='dist\gui\settings\textsize.rsrc.py' DiskId='1' />
<RemoveFile Id='id21' On='uninstall' Name='*.*' />
<RemoveFolder Id='id12' On='uninstall' />
</Component>
</Directory>
<Component Id='ain_id22' Guid='20C645B5-6ACD-410E-BF2B-E016DFB6E1FA'>
<File Id='id23' Name='rsrc.py' LongName='chatpriv.rsrc.py' Source='dist\gui\chatpriv.rsrc.py' DiskId='1' />
<File Id='id24' Name='rsrc.py' LongName='downprog.rsrc.py' Source='dist\gui\downprog.rsrc.py' DiskId='1' />
<File Id='id25' Name='rsrc.py' LongName='fitsopener.rsrc.py' Source='dist\gui\fitsopener.rsrc.py' DiskId='1' />
<File Id='id26' Name='rsrc.py' LongName='imageadj.Windows.rsrc.py' Source='dist\gui\imageadj.Windows.rsrc.py' DiskId='1' />
<File Id='id27' Name='rsrc.py' LongName='imager.Windows.rsrc.py' Source='dist\gui\imager.Windows.rsrc.py' DiskId='1' />
<File Id='id28' Name='rsrc.py' LongName='info.rsrc.py' Source='dist\gui\info.rsrc.py' DiskId='1' />
<File Id='id29' Name='rsrc.py' LongName='main.EeePC.rsrc.py' Source='dist\gui\main.EeePC.rsrc.py' DiskId='1' />
<File Id='id30' Name='rsrc.py' LongName='main.Windows.rsrc.py' Source='dist\gui\main.Windows.rsrc.py' DiskId='1' />
<File Id='id31' Name='rsrc.py' LongName='scriptsgui.Windows.rsrc.py' Source='dist\gui\scriptsgui.Windows.rsrc.py' DiskId='1' />
<RemoveFile Id='id32' On='uninstall' Name='*.*' />
<RemoveFolder Id='id5' On='uninstall' />
</Component>
</Directory>
<Component Id='ain_id33' Guid='84088D85-D9FC-4782-BB26-A8155199BC65'>
<Registry Id='id34' Root='HKLM' Key='Software\SkyliveStaff\SkyliveNG 0.1.2.0' Name='InstallDir' Action='write' Type='string' Value='[INSTALLDIR]' />
<File Id='id35' Name='AES.pyd' LongName='AES.pyd' Source='dist\AES.pyd' DiskId='1' />
<File Id='id36' Name='bz2.pyd' LongName='bz2.pyd' Source='dist\bz2.pyd' DiskId='1' />
<File Id='id37' Name='ite.pyd' LongName='fftpack_lite.pyd' Source='dist\fftpack_lite.pyd' DiskId='1' />
<File Id='id38' Name='ner.exe' LongName='fitsopener.exe' Source='dist\fitsopener.exe' DiskId='1' />
<File Id='id39' Name='lus.dll' LongName='gdiplus.dll' Source='dist\gdiplus.dll' DiskId='1' />
<File Id='id40' Name='ite.pyd' LongName='lapack_lite.pyd' Source='dist\lapack_lite.pyd' DiskId='1' />
<File Id='id41' Name='ary.zip' LongName='library.zip' Source='dist\library.zip' DiskId='1' />
<File Id='id42' Name='nse.rtf' LongName='license.rtf' Source='dist\license.rtf' DiskId='1' />
<File Id='id43' Name='NSE.txt' LongName='LICENSE.txt' Source='dist\LICENSE.txt' DiskId='1' />
<File Id='id44' Name='P71.dll' LongName='MSVCP71.dll' Source='dist\MSVCP71.dll' DiskId='1' />
<File Id='id45' Name='R71.dll' LongName='MSVCR71.dll' Source='dist\MSVCR71.dll' DiskId='1' />
<File Id='id46' Name='and.pyd' LongName='mtrand.pyd' Source='dist\mtrand.pyd' DiskId='1' />
<File Id='id47' Name='ray.pyd' LongName='multiarray.pyd' Source='dist\multiarray.pyd' DiskId='1' />
<File Id='id48' Name='onf.exe' LongName='proxyconf.exe' Source='dist\proxyconf.exe' DiskId='1' />
<File Id='id49' Name='pat.pyd' LongName='pyexpat.pyd' Source='dist\pyexpat.pyd' DiskId='1' />
<File Id='id50' Name='n25.dll' LongName='python25.dll' Source='dist\python25.dll' DiskId='1' />
<File Id='id51' Name='s25.dll' LongName='pywintypes25.dll' Source='dist\pywintypes25.dll' DiskId='1' />
<File Id='id52' Name='DME.txt' LongName='README.txt' Source='dist\README.txt' DiskId='1' />
<File Id='id53' Name='ath.pyd' LongName='scalarmath.pyd' Source='dist\scalarmath.pyd' DiskId='1' />
<File Id='id54' Name='ect.pyd' LongName='select.pyd' Source='dist\select.pyd' DiskId='1' />
<File Id='id55' Name='lop.pyd' LongName='sgmlop.pyd' Source='dist\sgmlop.pyd' DiskId='1' />
<File Id='id56' Name='-ng.exe' LongName='skylive-ng.exe' Source='dist\skylive-ng.exe' DiskId='1'>
<Shortcut Id='id57' Directory='ProgramMenuDir' Name='yliveNG' LongName='SkyliveNG' WorkingDirectory='INSTALLDIR' Icon='id4.ico' IconIndex='0' />
<Shortcut Id='id58' Directory='DesktopFolder' Name='yliveNG' LongName='SkyliveNG' WorkingDirectory='INSTALLDIR' Icon='id4.ico' IconIndex='0' />
</File>
<File Id='id59' Name='ath.pyd' LongName='umath.pyd' Source='dist\umath.pyd' DiskId='1' />
<File Id='id60' Name='ata.pyd' LongName='unicodedata.pyd' Source='dist\unicodedata.pyd' DiskId='1' />
<File Id='id61' Name='pen.exe' LongName='w9xpopen.exe' Source='dist\w9xpopen.exe' DiskId='1' />
<File Id='id62' Name='api.pyd' LongName='win32api.pyd' Source='dist\win32api.pyd' DiskId='1' />
<File Id='id63' Name='ent.pyd' LongName='win32event.pyd' Source='dist\win32event.pyd' DiskId='1' />
<File Id='id64' Name='ile.pyd' LongName='win32file.pyd' Source='dist\win32file.pyd' DiskId='1' />
<File Id='id65' Name='pdh.pyd' LongName='win32pdh.pyd' Source='dist\win32pdh.pyd' DiskId='1' />
<File Id='id66' Name='ipe.pyd' LongName='win32pipe.pyd' Source='dist\win32pipe.pyd' DiskId='1' />
<File Id='id67' Name='ess.pyd' LongName='win32process.pyd' Source='dist\win32process.pyd' DiskId='1' />
<File Id='id68' Name='ity.pyd' LongName='win32security.pyd' Source='dist\win32security.pyd' DiskId='1' />
<File Id='id69' Name='_vc.dll' LongName='wxbase28uh_net_vc.dll' Source='dist\wxbase28uh_net_vc.dll' DiskId='1' />
<File Id='id70' Name='_vc.dll' LongName='wxbase28uh_vc.dll' Source='dist\wxbase28uh_vc.dll' DiskId='1' />
<File Id='id71' Name='_vc.dll' LongName='wxmsw28uh_adv_vc.dll' Source='dist\wxmsw28uh_adv_vc.dll' DiskId='1' />
<File Id='id72' Name='_vc.dll' LongName='wxmsw28uh_core_vc.dll' Source='dist\wxmsw28uh_core_vc.dll' DiskId='1' />
<File Id='id73' Name='_vc.dll' LongName='wxmsw28uh_html_vc.dll' Source='dist\wxmsw28uh_html_vc.dll' DiskId='1' />
<File Id='id74' Name='_vc.dll' LongName='wxmsw28uh_stc_vc.dll' Source='dist\wxmsw28uh_stc_vc.dll' DiskId='1' />
<File Id='id75' Name='ase.pyd' LongName='_compiled_base.pyd' Source='dist\_compiled_base.pyd' DiskId='1' />
<File Id='id76' Name='ls_.pyd' LongName='_controls_.pyd' Source='dist\_controls_.pyd' DiskId='1' />
<File Id='id77' Name='re_.pyd' LongName='_core_.pyd' Source='dist\_core_.pyd' DiskId='1' />
<File Id='id78' Name='pes.pyd' LongName='_ctypes.pyd' Source='dist\_ctypes.pyd' DiskId='1' />
<File Id='id79' Name='las.pyd' LongName='_dotblas.pyd' Source='dist\_dotblas.pyd' DiskId='1' />
<File Id='id80' Name='di_.pyd' LongName='_gdi_.pyd' Source='dist\_gdi_.pyd' DiskId='1' />
<File Id='id81' Name='lib.pyd' LongName='_hashlib.pyd' Source='dist\_hashlib.pyd' DiskId='1' />
<File Id='id82' Name='tml.pyd' LongName='_html.pyd' Source='dist\_html.pyd' DiskId='1' />
<File Id='id83' Name='ing.pyd' LongName='_imaging.pyd' Source='dist\_imaging.pyd' DiskId='1' />
<File Id='id84' Name='gft.pyd' LongName='_imagingft.pyd' Source='dist\_imagingft.pyd' DiskId='1' />
<File Id='id85' Name='sc_.pyd' LongName='_misc_.pyd' Source='dist\_misc_.pyd' DiskId='1' />
<File Id='id86' Name='yco.pyd' LongName='_psyco.pyd' Source='dist\_psyco.pyd' DiskId='1' />
<File Id='id87' Name='ket.pyd' LongName='_socket.pyd' Source='dist\_socket.pyd' DiskId='1' />
<File Id='id88' Name='ort.pyd' LongName='_sort.pyd' Source='dist\_sort.pyd' DiskId='1' />
<File Id='id89' Name='ssl.pyd' LongName='_ssl.pyd' Source='dist\_ssl.pyd' DiskId='1' />
<File Id='id90' Name='stc.pyd' LongName='_stc.pyd' Source='dist\_stc.pyd' DiskId='1' />
<File Id='id91' Name='der.pyd' LongName='_win32sysloader.pyd' Source='dist\_win32sysloader.pyd' DiskId='1' />
<File Id='id92' Name='ws_.pyd' LongName='_windows_.pyd' Source='dist\_windows_.pyd' DiskId='1' />
<File Id='id93' Name='ons.pyd' LongName='_zope_interface_coptimizations.pyd' Source='dist\_zope_interface_coptimizations.pyd' DiskId='1' />
<File Id='id94' Name='ONA.ico' LongName='ICONA.ico' Source='dist\ICONA.ico' DiskId='1' />
<RemoveFile Id='id95' On='uninstall' Name='*.*' />
<RemoveFolder Id='ProgramMenuDir' On='uninstall' />
</Component>
</Directory>
</Directory>
</Directory>
<Directory Id='ProgramMenuFolder' Name='PMenu' LongName='Programs'>
<Directory Id='ProgramMenuDir' Name='Skylive' />
</Directory>
<Directory Id='DesktopFolder' Name='Desktop' />
</Directory>
<Feature Id='Complete' Title='SkyliveNG 0.1.2.0' Description='The complete package.' Display='expand' Level='1' ConfigurableDirectory='INSTALLDIR'>
<Feature Id='Main' Title='Main' Description='Required Files' Display='expand' Level='1'>
<ComponentRef Id='Main_id7' />
<ComponentRef Id='ain_id13' />
<ComponentRef Id='ain_id22' />
<ComponentRef Id='ain_id33' />
</Feature>
</Feature>
<Property Id='WIXUI_INSTALLDIR' Value='INSTALLDIR' /> <UIRef Id='WixUI_InstallDir' />
<Icon Id='id4.ico' SourceFile='dist\ICONA.ico' />
</Product>
</Wix>
"""
Copyright (C) 2007,2008 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007,2008 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007,2008 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
print 'DON\'T WORK FOR NOW!!!'
print 'USE build.py OR MANUAL INSTALL!'
import sys
sys.exit(0)
File added
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright (c) Microsoft Corporation. All rights reserved. -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<noInheritable/>
<assemblyIdentity
type="win32"
name="Microsoft.VC90.CRT"
version="9.0.21022.8"
processorArchitecture="x86"
publicKeyToken="1fc8b3b9a1e18e3b"
/>
<file name="msvcr90.dll" /> <file name="msvcp90.dll" /> <file name="msvcm90.dll" />
</assembly>
____ _ _ _ _ _ ____
/ ___|| | ___ _| (_)_ _____ | \ | |/ ___|
\___ \| |/ / | | | | \ \ / / _ \_____| \| | | _
___) | <| |_| | | |\ V / __/_____| |\ | |_| |
|____/|_|\_\\__, |_|_| \_/ \___| |_| \_|\____|
|___/ Version 0.1.4
--------------------------------------------------
I really shuld write something here...
"""
Copyright (C) 2007 Franco Lanza <nextime@nexlab.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
__version__ = "$Revision:$"
__date__ = "$Date:$"
"""
import wx
from Pycard import event, widget, model
class ContainerSpec( widget.WidgetSpec ) :
def __init__( self ) :
events = [ event.MouseClickEvent ]
attributes = {}
widget.WidgetSpec.__init__( self, 'Container', 'Widget', events, attributes )
class Container( widget.Widget, model.Scriptable, wx.Panel ) :
"""
A container panel for composite components.
"""
_spec = ContainerSpec()
def __init__( self, aParent, aResource ) :
model.Scriptable.__init__( self, aParent )
wx.Panel.__init__(
self, aParent, widget.makeNewId(aResource.id),
aResource.position,
aResource.size,
style = wx.CLIP_SIBLINGS,
name = aResource.name
)
widget.Widget.__init__( self, aParent, aResource )
import sys
from Pycard import registry
registry.Registry.getInstance().register(sys.modules[__name__].Container)
"""
__version__ = "$Revision: 1.24 $"
__date__ = "$Date: 2004/08/11 01:58:03 $"
"""
import wx
from Pycard import event, graphic, widget
USE_GENERIC = wx.Platform == '__WXGTK__' or wx.Platform == '__WXMSW__'
if USE_GENERIC:
from wx.lib.statbmp import GenStaticBitmap as StaticBitmap
else:
StaticBitmap = wx.StaticBitmap
class ImageSpec(widget.WidgetSpec):
def __init__(self):
events = []
attributes = {
'file' : { 'presence' : 'optional', 'default':'' },
# KEA shouldn't there be a 'file' attribute here
# could call it 'image' to match background above
# but it is mandatory
#'bitmap' : { 'presence' : 'optional', 'default' : None },
# KEA kill border for now, until variations of what is possible are worked out
# use ImageButton if you want images with transparent border
#'border' : { 'presence' : 'optional', 'default' : '3d', 'values' : [ '3d', 'transparent', 'none' ] },
'size' : { 'presence' : 'optional', 'default' : [ -1, -1 ] },
}
widget.WidgetSpec.__init__( self, 'Image', 'Widget', events, attributes )
class Image(widget.Widget, StaticBitmap):
"""
A static image.
"""
_spec = ImageSpec()
def __init__(self, aParent, aResource):
self._bitmap = graphic.Bitmap(aResource.file, aResource.size)
self._file = aResource.file
self._size = tuple(aResource.size)
w = aResource.size[0]
if w == -2:
w = self._bitmap.getWidth()
h = aResource.size[1]
if h == -2:
h = self._bitmap.getHeight()
size = (w, h)
#size = wx.Size( self._bitmap.GetWidth(), self._bitmap.GetHeight() )
##if aResource.border == 'transparent':
## mask = wx.MaskColour(self._bitmap, wxBLACK)
## self._bitmap.SetMask(mask)
StaticBitmap.__init__(
self,
aParent,
widget.makeNewId(aResource.id),
self._bitmap.getBits(),
aResource.position,
size,
style = wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_SIBLINGS,
name = aResource.name
)
widget.Widget.__init__( self, aParent, aResource )
wx.EVT_WINDOW_DESTROY(self, self._OnDestroy)
# Try to remove flickering on windows.
#wx.EVT_ERASE_BACKGROUND( self, lambda evt: None)
self._bindEvents(event.WIDGET_EVENTS)
def _OnDestroy(self, event):
# memory leak cleanup
self._bitmap = None
event.Skip()
# KEA added getBitmap, setBitmap
def _getBitmap( self ) :
return self._bitmap
def _setBitmap( self, aValue ) :
self._bitmap = aValue
self.SetBitmap( aValue.getBits() )
# may actually need to refresh the panel as well
# depending on the size of the new bitmap compared
# to the old one
# in addition, the size of the image or imagebutton needs
# to be set appropriately after changing the bitmap so
# there are still a few issues to work out
self.Refresh()
"""
# KEA do we query the Bitmap to find the actual dimensions
# _size can contain -1, and -2
# or provide a special getBitmapSize method?
# this getSize is actually the same as its parent
def _getSize( self ) :
return self.GetSizeTuple() # get the actual size, not (-1, -1)
"""
# KEA special handling for -2 size option
def _setSize(self, aSize):
self._size = tuple(aSize)
w = aSize[0]
if w == -2:
w = self._bitmap.getWidth()
h = aSize[1]
if h == -2:
h = self._bitmap.getHeight()
self.SetSize((w, h))
# KEA 2001-08-02
# right now the image is loaded from a filename
# during initialization
# but later these might not make any sense
# if setBitmap is used directly in user code
def _getFile( self ) :
return self._file
# KEA 2001-08-14
# if we're going to support setting the file
# after initialization, then this will need to handle the bitmap loading
# overhead
def _setFile( self, aFile ) :
self._file = aFile
self._setBitmap(graphic.Bitmap(aFile))
def _setBackgroundColor( self, aColor ) :
aColor = self._getDefaultColor( aColor )
if self._file == '':
bmp = self._bitmap.getBits()
dc = wx.MemoryDC()
dc.SelectObject(bmp)
dc.SetBackground(wx.Brush(aColor))
dc.Clear()
dc.SelectObject(wx.NullBitmap)
self.SetBackgroundColour( aColor )
self.Refresh() # KEA wxPython bug?
backgroundColor = property(widget.Widget._getBackgroundColor, _setBackgroundColor)
bitmap = property(_getBitmap, _setBitmap)
file = property(_getFile, _setFile)
size = property(widget.Widget._getSize, _setSize)
import sys
from Pycard import registry
registry.Registry.getInstance().register(sys.modules[__name__].Image)
"""
__version__ = "$Revision: 1.17 $"
__date__ = "$Date: 2004/05/13 02:40:24 $"
"""
import wx
from wx import html
from Pycard import event, log, widget
import webbrowser
class InfoHtmlWindowSpec(widget.WidgetSpec):
def __init__(self):
events = []
attributes = {
'size' : { 'presence' : 'optional', 'default' : [ 50, 50 ] },
'text' : { 'presence' : 'optional', 'default' : '' },
}
widget.WidgetSpec.__init__(self, 'InfoHtmlWindow', 'Widget', events, attributes )
class InfoHtmlWindow(widget.Widget, html.HtmlWindow):
"""
An HTML window.
"""
_spec = InfoHtmlWindowSpec()
def __init__(self, aParent, aResource):
self._addressField = None
html.HtmlWindow.__init__(
self,
aParent,
widget.makeNewId(aResource.id),
aResource.position,
aResource.size,
#style = wx.HW_SCROLLBAR_AUTO | wx.CLIP_SIBLINGS,
name = aResource.name
)
widget.Widget.__init__(self, aParent, aResource)
self._setText(aResource.text)
self._bindEvents(event.WIDGET_EVENTS)
def setAddressField(self, field):
self._addressField = field
def _getText(self) :
return self.GetOpenedPage()
def _setText(self, aString):
if aString == '' or aString[0] == '<':
self.SetPage(aString)
else:
# filename
self.LoadPage(aString)
#self._delegate.Refresh()
def base_LoadPage(self, url):
log.debug("base_LoadPage " + url)
if self._addressField is not None:
self._addressField.text = url
log.debug("loaded")
html.HtmlWindow.base_LoadPage(self, url)
def LoadPage(self, url):
log.debug("LoadPage " + url)
if self._addressField is not None:
self._addressField.text = url
log.debug("loaded")
html.HtmlWindow.LoadPage(self, url)
def SetPage(self, text):
log.debug("SetPage " + text)
#if self._addressField is not None:
# self._addressField.text = text
# log.debug("set")
html.HtmlWindow.SetPage(self, text)
def OnLinkClicked(self, link):
log.debug("OnLinkClicked " + str(link))
webbrowser.open(str(link.GetHref()))
text = property(_getText, _setText)
import sys
from Pycard import registry
registry.Registry.getInstance().register(sys.modules[__name__].InfoHtmlWindow)
"""
Copyright (C) 2007 Franco Lanza <nextime@nexlab.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import wx
from Pycard import event, graphic, widget
USE_GENERIC = wx.Platform == '__WXGTK__'
if USE_GENERIC:
from wx.lib.statbmp import GenStaticBitmap as StaticBitmap
else:
StaticBitmap = wx.StaticBitmap
ScrolledWindow = wx.ScrolledWindow
class ScrolledImageSpec(widget.WidgetSpec):
def __init__(self):
events = []
attributes = {
'file' : { 'presence' : 'optional', 'default':'' },
'size' : { 'presence' : 'optional', 'default' : [ -1, -1 ] },
}
widget.WidgetSpec.__init__( self, 'Image', 'Widget', events, attributes )
class ScrolledImage(widget.Widget, StaticBitmap):
"""
A static image.
"""
_spec = ScrolledImageSpec()
def __init__(self, aParent, aResource):
self._bitmap = graphic.Bitmap(aResource.file, aResource.size)
self._file = aResource.file
self._size = tuple(aResource.size)
w = aResource.size[0]
if w == -2:
w = self._bitmap.getWidth()
h = aResource.size[1]
if h == -2:
h = self._bitmap.getHeight()
size = (w, h)
#size = wx.Size( self._bitmap.GetWidth(), self._bitmap.GetHeight() )
##if aResource.border == 'transparent':
## mask = wx.MaskColour(self._bitmap, wxBLACK)
## self._bitmap.SetMask(mask)
self.sw = ScrolledWindow(self)
StaticBitmap.__init__(self.sw, aParent, widget.makeNewId(aResource.id), self._bitmap.getBits(),
aResource.position, size, style = wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_SIBLINGS,
name = aResource.name )
widget.Widget.__init__( self, aParent, aResource )
wx.EVT_WINDOW_DESTROY(self, self._OnDestroy)
self._bindEvents(event.WIDGET_EVENTS)
def _OnDestroy(self, event):
# memory leak cleanup
self._bitmap = None
event.Skip()
# KEA added getBitmap, setBitmap
def _getBitmap( self ) :
return self._bitmap
def _setBitmap( self, aValue ) :
self._bitmap = aValue
self.SetBitmap( aValue.getBits() )
# may actually need to refresh the panel as well
# depending on the size of the new bitmap compared
# to the old one
# in addition, the size of the image or imagebutton needs
# to be set appropriately after changing the bitmap so
# there are still a few issues to work out
self.Refresh()
"""
# KEA do we query the Bitmap to find the actual dimensions
# _size can contain -1, and -2
# or provide a special getBitmapSize method?
# this getSize is actually the same as its parent
def _getSize( self ) :
return self.GetSizeTuple() # get the actual size, not (-1, -1)
"""
# KEA special handling for -2 size option
def _setSize(self, aSize):
self._size = tuple(aSize)
w = aSize[0]
if w == -2:
w = self._bitmap.getWidth()
h = aSize[1]
if h == -2:
h = self._bitmap.getHeight()
self.SetSize((w, h))
# KEA 2001-08-02
# right now the image is loaded from a filename
# during initialization
# but later these might not make any sense
# if setBitmap is used directly in user code
def _getFile( self ) :
return self._file
# KEA 2001-08-14
# if we're going to support setting the file
# after initialization, then this will need to handle the bitmap loading
# overhead
def _setFile( self, aFile ) :
self._file = aFile
self._setBitmap(graphic.Bitmap(aFile))
def _setBackgroundColor( self, aColor ) :
aColor = self._getDefaultColor( aColor )
if self._file == '':
bmp = self._bitmap.getBits()
dc = wx.MemoryDC()
dc.SelectObject(bmp)
dc.SetBackground(wx.Brush(aColor))
dc.Clear()
dc.SelectObject(wx.NullBitmap)
self.SetBackgroundColour( aColor )
self.Refresh() # KEA wxPython bug?
backgroundColor = property(widget.Widget._getBackgroundColor, _setBackgroundColor)
bitmap = property(_getBitmap, _setBitmap)
file = property(_getFile, _setFile)
size = property(widget.Widget._getSize, _setSize)
import sys
from Pycard import registry
registry.Registry.getInstance().register(sys.modules[__name__].ScrolledImage)
"""
__version__ = "$Revision: 1.29 $"
__date__ = "$Date: 2005/12/25 13:44:50 $"
"""
import wx
from Pycard import event, widget
from Pycard.components import list as orlist
ContainerMixin = orlist.ContainerMixin
ListSelectEvent = orlist.ListSelectEvent
ListMouseDoubleClickEvent = orlist.ListMouseDoubleClickEvent
class UListSpec(widget.WidgetSpec):
def __init__(self):
events = list(orlist.ListEvents)
attributes = {
'items' : { 'presence' : 'optional', 'default' : [] },
'stringSelection' : { 'presence' : 'optional', 'default' : None }
}
widget.WidgetSpec.__init__( self, 'UList', 'Widget', events, attributes )
self._events.remove(event.MouseDoubleClickEvent)
class UList(orlist.List):
"""
A list that only allows a single item to be selected.
"""
_spec = UListSpec()
def __init__(self, aParent, aResource):
wx.ListBox.__init__(
self,
aParent,
widget.makeNewId(aResource.id),
aResource.position,
aResource.size,
aResource.items,
style = wx.LB_SINGLE | wx.LB_ALWAYS_SB | wx.NO_FULL_REPAINT_ON_RESIZE | wx.CLIP_SIBLINGS,
name = aResource.name
)
widget.Widget.__init__(self, aParent, aResource)
if aResource.stringSelection:
self._setStringSelection(aResource.stringSelection)
self._bindEvents(self._spec._events)
import sys
from Pycard import registry
registry.Registry.getInstance().register(sys.modules[__name__].UList)
#!/usr/bin/env python
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
__version__ = "$Revision: 0.1 $"
__date__ = "$Date: 2007/09/25 22:13:23 $"
"""
from gui import fitsopener
if __name__ == "__main__":
fitsopener.run()
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, dialog
from skylive import config
import wx
class AskStream(model.Background):
def on_initialize(self, event):
self.parent = self.getParent()
def on_close(self, event):
self.parent.on_CloseAskStream(event)
event.skip()
def on_exit_command(self, event):
self.close()
def on_size(self, event):
self.panel.SetSize(self.size)
def on_ButtonYes_mouseClick(self, event):
self.parent.on_realStartStream(event)
def on_ButtonNo_mouseClick(self, event):
self.parent.on_realNoStream(event)
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgFocus',
'title':u'AudioVideo',
'size':(285, 126),
'components': [
{'type':'StaticText',
'name':'ask',
'position':(15, 5),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Do you want to listen our audio stream?',
},
{'type':'CheckBox',
'name':'save',
'position':(97, 47),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'label':"don't ask anymore",
'checked': True,
},
{'type':'Button',
'name':'ButtonNo',
'position':(142, 19),
'size':(32, -1),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'label':'No',
},
{'type':'Button',
'name':'ButtonYes',
'position':(97, 18),
'size':(32, -1),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'label':'Yes',
},
] # end components
,
'sizers':
[
{
'name' : 'ALL',
'typ' : 'i',
'children' : [
{
'name' : 'TOP SIZER',
'typ' : 'v',
'horGrowth' : 1,
'verGrowth' : 1,
'children' : [
{
'name' : 'versizer001',
'typ' : 'v',
'children' : [
{
'name' : 'ask' },
{
'name' : 'horsizer000',
'typ' : 'h',
'children' : [
{
'name' : 'ButtonYes' },
{
'name' : 'ButtonNo' },
] # end of horsizer000
},
{
'name' : 'save' },
] # end of versizer001
},
] # end of TOP SIZER
},
{
'name' : 'UNPLACED',
'typ' : 'i' },
] # end of ALL
},
] # end of sizers
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model
class Booking(model.Background):
def on_initialize(self, event):
pass
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':'Standard Template with File->Exit menu',
'size':(441, 289),
'style':['resizeable'],
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
]
},
]
},
'components': [
{'type':'ToggleButton',
'name':'ToggleButton111111111',
'position':(361, 150),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
'label':'ToggleButton111111111',
},
{'type':'ToggleButton',
'name':'ToggleButton11111111',
'position':(361, 132),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
'label':'ToggleButton11111111',
},
{'type':'ToggleButton',
'name':'ToggleButton1111111',
'position':(361, 114),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
'label':'ToggleButton1111111',
},
{'type':'ToggleButton',
'name':'ToggleButton111111',
'position':(361, 95),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
'label':'ToggleButton111111',
},
{'type':'ToggleButton',
'name':'ToggleButton11111',
'position':(361, 77),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
'label':'ToggleButton11111',
},
{'type':'ToggleButton',
'name':'ToggleButton1111',
'position':(361, 58),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
'label':'ToggleButton1111',
},
{'type':'ToggleButton',
'name':'ToggleButton111',
'position':(361, 39),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
'label':'ToggleButton111',
},
{'type':'ToggleButton',
'name':'ToggleButton11',
'position':(361, 20),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
'label':'ToggleButton11',
},
{'type':'ToggleButton',
'name':'ToggleButton1',
'position':(361, 2),
'size':(25, 19),
'backgroundColor':(255, 0, 0, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(255, 0, 0, 255),
},
{'type':'Calendar',
'name':'Calendar1',
'position':(36, 102),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
},
] # end components
,
'sizers':
[
{
'name' : 'ALL',
'typ' : 'i',
'children' : [
{
'name' : 'TOP SIZER',
'typ' : 'v',
'horGrowth' : 1,
'verGrowth' : 1 },
{
'name' : 'UNPLACED',
'typ' : 'i',
'children' : [
{
'name' : 'Calendar1' },
{
'name' : 'ToggleButton1' },
{
'name' : 'ToggleButton11' },
{
'name' : 'ToggleButton111' },
{
'name' : 'ToggleButton1111' },
{
'name' : 'ToggleButton11111' },
{
'name' : 'ToggleButton111111' },
{
'name' : 'ToggleButton1111111' },
{
'name' : 'ToggleButton11111111' },
{
'name' : 'ToggleButton111111111' },
] # end of UNPLACED
},
] # end of ALL
},
] # end of sizers
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, dialog, timer
import os, wx, webbrowser
from skylive import config
from skylive.utils import genutils
import time
from skylive import chatparser as parser
class ChatPrivate(model.Background):
chathtml = []
latest = ''
def on_initialize(self, event):
self.parent = self.getParent()
if self.parent.lang == "it":
self.blinkMsg = "Nuovo messaggio"
else:
self.blinkMsg = "New message"
self.deactiv = False
self.canSelect = False
self.canbeep, self.canpopup = config.get_pvtPref()
self.components.ChatMsg.setFocus()
if genutils.platform() == 'Darwin':
self.blinkTimer = timer.Timer(self.components.ChatArea, -1)
self.origTitle = self.title
self.iconOn = True
self.last_idle = time.time()
self.SetSizeHints(200, 200)
self.resizeAll()
def on_close(self, event):
self.parent.on_PrivChatClose(self.touser)
event.skip()
def on_exit_command(self, event):
self.close()
def on_menuSavePrivChat_select(self, event):
#self.chatPrivText = self.components.ChatArea.text
self.chatPrivText = self.components.ChatArea.text
self.chat_file_path = os.path.expanduser("~")
self.chat_file_save_path = os.path.normpath(self.chat_file_path+"/skylive-ng_chat")
self.usr_file_name = self.tousercomp+".txt"
result = dialog.saveFileDialog(self, "Save Text file as:", self.chat_file_save_path, self.usr_file_name, 'Text Files: (*.txt)|*.txt')
if result.accepted:
self.path = result.paths[0]
self.chat_file = open(self.path,"w")
self.chat_file.write("Start private chat text whit "+self.tousercomp+"\n"+self.chatPrivText)
self.chat_file.close()
dialog.alertDialog(self, "Private chat text saved in "+self.path)
def on_Send_mouseClick(self, event):
txt = self.components.ChatMsg.text
self.components.ChatMsg.text = ''
if len(txt.replace(" ", "")) > 0:
#self.components.ChatArea.appendText("<"+self.parent.config.getUsername()+"> "+txt+"\n")
self.parent.addToPrivChatWindow(self.parent.config.getUsername(), parser.toHtml(txt), str(self.touser), 'red')
#self.parent.callInTwisted('sendNetworkData', self.parent.srvproto.chatSendPrivate(self.tousercomp, txt))
self.parent.TwistedLoop.sendNetworkData(self.parent.srvproto.chatSendPrivate(self.tousercomp, txt))
def on_ChatMsg_keyPress(self, event):
if event.GetKeyCode() == wx.WXK_RETURN:
self.on_Send_mouseClick(event)
event.skip()
else:
event.skip()
def on_ChatArea_gainFocus(self, event):
# Ugly, bad, orrible hack to make
# the fucking windows work with RETURN keypress.
if not self.canSelect:
if os.name == 'nt':
if len(self.components.ChatMsg.text) > 0:
self.on_Send_mouseClick(False)
event.skip()
self.components.ChatMsg.setFocus()
def on_deactivate(self, event):
self.deactiv = True
def on_activate(self, event):
self.deactiv = False
#self.components.ChatMsg.setFocus()
if genutils.platform() == 'Darwin':
self.blinkTimer.Stop()
self.title = self.origTitle
def on_ChatArea_textUpdate(self, event):
print 'PrivChatArea Updated'
if self.canbeep and self.deactiv:
print '\a'
if self.canpopup and self.deactiv:
self.Restore()
if True and self.deactiv:
if genutils.platform() == 'Darwin':
self.blinkTimer.Start(1000)
else:
self.RequestUserAttention()
def on_ChatArea_mouseDown(self, event):
self.canSelect = True
event.skip()
def on_ChatArea_mouseUp(self, event):
self.canSelect = False
event.skip()
#def on_ChatArea_mouseDoubleClick(self, event):
# x = ''
# y = ''
# url = False
# posA = 0
# posB = 0
# noUrl = False
# cpoint = self.components.ChatArea.getSelection()
# while 'http' not in x and '>' not in x:
# x = self.components.ChatArea.getString(cpoint[0]-posA, cpoint[0]-posA+4)
# if '>' in x or '<' in x:
# noUrl = True
# posA+=1
# if not noUrl:
# while y != ' ' and y != '\n':
# y = self.components.ChatArea.getString(cpoint[1]+posB, cpoint[1]+posB+1)
# posB+=1
# A = cpoint[0]-posA+1
# B = cpoint[1]+posB-1
# text = self.components.ChatArea.getString(A, B)
# if len(text.split(' ')) > 1:
# urlTry = text.split(' ')[0]
# else:
# urlTry = text
# if len(urlTry) > 12:
# url = urlTry
# try:
# if url:
# webbrowser.open(url)
# except:
# self.dialog.alertdialog(self, "Default WebBrowser is not defined")
def on_ChatArea_keyPress(self, event):
key = event.GetKeyCode()
if key in range (31, 128):
self.components.ChatMsg.setFocus()
self.components.ChatMsg.appendText(unicode(chr(key)))
else:
self.components.ChatMsg.setFocus()
event.skip()
def on_ChatArea_timer(self, event):
if self.iconOn:
self.title = self.blinkMsg
self.iconOn = False
else:
self.iconOn = True
self.title = self.origTitle
event.skip()
def on_size(self, event):
w, h = self.size
if w >= 200 and h >= 200:
self.resizeAll()
def resizeAll(self):
winW, winH = self.size
areaW=winW-26
areaH=winH-97
self.components.ChatArea.size = (areaW, areaH)
inputW = areaW-78
inputH = 27
self.components.ChatMsg.size = (inputW, inputH)
self.components.ChatMsg.position = (10, areaH+13)
self.components.Send.position = (inputW+15, areaH+15)
self.panel.SetSize(self.size)
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Standard Template with File->Exit menu',
'style': ['resizeable'],
'size':(325, 363),
'icon':'./gui/img/ICONA.ico',
'backgroundColor':(192, 192, 192),
'useSizers':0,
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuSavePrivChat',
'label':'S&ave chat',
},
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
]
},
]
},
'components': [
{'type':'Button',
'name':'Send',
'position':(235, 281),
'size':(73, -1),
'label':'Send',
},
{'type':'TextField',
'name':'ChatMsg',
'position':(10, 279),
#'size':(220, 27),
'size':(-1, -1),
},
#{'type':'TextArea',
# 'name':'ChatArea',
# 'position':(10, 10),
# #'size':(298, 266),
# 'size':(-1, -1),
# 'backgroundColor':(135, 232, 201),
# 'editable':False
# },
{'type':'InfoHtmlWindow',
'name':'ChatArea',
'position':(10, 10),
'size':(-1, -1),
'backgroundColor':(135, 232, 201),
'horGrowth':1,
'userdata':'<html></html>',
'verGrowth':1,
},
] # end components
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, timer
class DownProgr(model.Background):
def on_initialize(self, event):
self.parent = self.getParent()
def on_close(self, event):
event.skip()
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'DownProgr',
'title':u'Download',
'icon':'gui/img/ICONA.ico',
'size':(310, 120),
'backgroundColor':(192, 192, 192),
'components': [
{'type':'StaticBox',
'name':'downBox',
'position':(5, 5),
'size':(300, 105),
'label':'Download Progress',
},
{'type':'StaticText',
'name':'downpr',
'position':(15, 75),
'size':(250, 30),
'text':'Progress:',
},
{'type':'StaticText',
'name':'progPerc',
'position':(270, 43),
'size':(50, 25),
'text':'0%',
},
{'type':'Gauge',
'name':'progBar',
'position':(15, 40),
'size':(250, 25),
'max':100,
'value':0,
},
] # end components
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, dialog, graphic
from Pycard.twistedsupport import twistedModel
from twisted.internet import reactor
import Image, ImageOps, numpy
import wx, os, platform
import imageadj
from skylive.utils import genutils as utils
from skylive.lang import language
from skylive.fits import fitsimage, levels
class FitsOpener(model.Background,):
def on_initialize(self, event):
try:
self._parent = self.getParent()
self.userhome = self._parent.usrDefSavePath
self.lang = self._parent.lang
except:
self.lang = 'en'
self.userhome = os.path.expanduser("~")
self.gui = 'imager'
self.ItemText = language.getItemText
def on_open_command(self, event):
try:
if self._parent.lastPath and os.path.exists(self._parent.lastPath):
lpath = self._parent.lastPath
else:
lpath = self.userhome
except:
lpath = self.userhome
selectFits = dialog.fileDialog(self, "Select Image:", lpath, ' ', 'FITS Image: (*.fit)|*.fit')
if selectFits.accepted:
self.fitsFile = selectFits.paths[0]
try:
self._parent.lastPath = os.path.split(self.fitsFile)[0]
except:
pass
self.loadFits(self.fitsFile)
def on_exit_command(self, event):
self.close()
def on_adjust_command(self, event=False):
sysType = platform.system()
if not os.path.exists(os.path.normpath("./gui/imageadj."+sysType+".rsrc.py")):
sysType = "Linux"
self.adjustImg = model.childWindow(self, imageadj.imageAdj, "./gui/imageadj."+sysType+".rsrc.py")
try:
self.adjustImg._parent = self
except:
pass
self.adjustImg.visible = True
try:
self.adjustImg._parent.origImage = [self.pilImage, self.xsizeBit, self.ysizeBit, self.min, self.max, self.med, self.img2, self.ToResize ]
except:
pass
def loadFits(self, fitsFile):
fitsfile = fitsimage.FitsImage(fitsFile, False)
scidata = fitsfile.image
self.autoMax = fitsfile.autoMaxLevel
self.autoMin = fitsfile.autoMinLevel
self.ToResize = fitsfile.pilResized
self.min = fitsfile.min
self.max = fitsfile.max
self.med = fitsfile.med
self.pilImage = fitsfile.pilOrI
self.img = fitsfile.pilImage
self.img2 = fitsfile.pilRaw
self.xsizeBit = fitsfile.xsizeBit
self.ysizeBit = fitsfile.ysizeBit
image = wx.EmptyImage(fitsfile.xsizeBit, fitsfile.ysizeBit)
image.SetData(fitsfile.pilImage.convert("RGB").tostring())
self.imageBitmap = graphic.Bitmap()
self.imageBitmap.setImageBits(image)
self.components.ImageShow.bitmap = self.imageBitmap
self.size = (fitsfile.xsizeBit+20, fitsfile.ysizeBit+100)
try:
self.MenuBar.setEnabled('menuPhoto', True)
except:
self.menuBar.setEnabled('menuPhoto', True)
if fitsfile.pilResized:
self.title = "Vista al "+str(fitsfile.percresize)+"% delle dimensioni originali"
def getAndSaveImage(self):
try:
imageFromPil = self.pilImage
except:
imageFromPil = False
if imageFromPil:
aStyle = wx.SAVE | wx.HIDE_READONLY | wx.OVERWRITE_PROMPT
result = dialog.saveFileDialog(self, self.getText('SaveDialog_SaveAs'), self.userhome, self._parent.components.FileName.text, 'BMP File: (*.bmp)|*.bmp|JPG File: (*.jpg)|*.jpg', aStyle)
if result.accepted:
path=result.paths[0]
if not os.path.splitext(os.path.split(path)[1])[1]:
dialog.alertDialog(self, self.getText('SaveDialog_alertSaveAs'))
self.getAndSaveImage()
else:
imageFromPil.save(path)
def on_saveas_command(self, event):
self.getAndSaveImage()
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def on_size(self, event):
self.panel.SetSize(self.size)
def run():
#app = model.Application(FitsOpener, './gui/fitsopener.rsrc.py')
app = twistedModel.TwistedModelApplication(FitsOpener, './gui/fitsopener.rsrc.py')
app.MainLoop()
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u"Fits's Opener",
'size':(820, 581),
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileOpen',
'label':u'O&pen..',
'command':'open',
},
{'type':'MenuItem',
'name':'menusaveas',
'label':u'Save as..',
'command':'saveas',
},
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
]
},
{'type':'Menu',
'name':'menuPhoto',
'label':'&Adjust',
'enabled':False,
'items': [
{'type':'MenuItem',
'name':'menuAdjustPhoto',
'label':'A&djust',
'command':'adjust',
},
]
},
]
},
'components': [
{'type':'Image',
'name':'ImageShow',
'position':(10, 10),
'size':(320, 240),
'file':u'./gui/img/Live.jpg',
},
] # end components
} # end background
] # end backgrounds
} }
from Pycard import model, dialog
class FocusDialog(model.Background):
def on_initialize(self, event):
self.parent = self.getParent()
def on_close(self, event):
self.parent.on_CloseFocus(event)
event.skip()
def on_exit_command(self, event):
self.close()
def on_size(self, event):
self.panel.SetSize(self.size)
def on_ButtonLess_mouseClick(self, event):
self.parent.on_FocusLess(event)
def on_ButtonPlus_mouseClick(self, event):
self.parent.on_FocusPlus(event)
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgFocus',
'title':u'Focus',
'size':(84, 71),
#'style':['wx.FRAME_TOOL_WINDOW', 'wx.MINIMIZE_BOX', 'wx.STAY_ON_TOP', 'wx.CLOSE_BOX', 'wx.CAPTION', 'wx.FRAME_SHAPED'],
'components': [
{'type':'Button',
'name':'ButtonLess',
'position':(47, 5),
'size':(32, -1),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'label':'-',
},
{'type':'Button',
'name':'ButtonPlus',
'position':(5, 5),
'size':(32, -1),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'label':'+',
},
] # end components
,
'sizers':
[
{
'name' : 'ALL',
'typ' : 'i',
'children' : [
{
'name' : 'TOP SIZER',
'typ' : 'v',
'horGrowth' : 1,
'verGrowth' : 1,
'children' : [
{
'name' : 'horsizer000',
'typ' : 'h',
'children' : [
{
'name' : 'ButtonPlus' },
{
'name' : 'ButtonLess' },
] # end of horsizer000
},
] # end of TOP SIZER
},
{
'name' : 'UNPLACED',
'typ' : 'i' },
] # end of ALL
},
] # end of sizers
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import wx
import math
from Pycard import model, resource
from skylive.lang import language
ID_OK=10
ID_CANCEL=15
ID_REG=20
ID_LOST=21
ID_NO=11
ID_LATER=12
ItemText = language.getItemText
def getText(item):
from skylive import config
lang = config.get_usrLang()
return ItemText(lang, 'gui', item)
class loginDialog(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self, None, wx.NewId(), "SkyLive Login",
style=wx.DEFAULT_DIALOG_STYLE | wx.STAY_ON_TOP | wx.CAPTION)
self.main_sizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=5)
self.username = wx.TextCtrl(self, 1, size=(150, -1))
self.main_sizer.Add(wx.StaticText(self, -1, "Username"),1, wx.ALIGN_CENTER)
self.main_sizer.Add(self.username, 1, wx.ALIGN_CENTER)
#self.main_sizer.Add(wx.StaticText(self, -1, " "),1, wx.ALIGN_CENTER)
self.password = wx.TextCtrl(self, -1, style=wx.TE_PASSWORD, size=(150, -1))
self.main_sizer.Add(wx.StaticText(self, -1, "Password"),1, wx.ALIGN_CENTER)
self.main_sizer.Add(self.password, 1, wx.ALIGN_CENTER)
#self.main_sizer.Add(wx.StaticText(self, -1, " "),1, wx.ALIGN_CENTER)
self.button_sizer = wx.FlexGridSizer(cols=2, vgap=5, hgap=5)
self.ok_button = wx.Button(self, ID_OK, "OK")
#self.main_sizer.Add(wx.StaticText(self, -1, " "),1, wx.ALIGN_CENTER)
self.button_sizer.Add(self.ok_button,1, wx.ALIGN_CENTER)
#self.main_sizer.Add(wx.StaticText(self, -1, " "),1, wx.ALIGN_CENTER)
wx.EVT_BUTTON(self, ID_OK, self.Ok)
self.cancel_button = wx.Button(self, ID_CANCEL, "CANCEL")
#self.main_sizer.Add(wx.StaticText(self, -1, " "),1, wx.ALIGN_CENTER)
self.button_sizer.Add(self.cancel_button, 1, wx.ALIGN_CENTER)
wx.EVT_BUTTON(self, ID_CANCEL, self.cancel)
# XXX Questo lo rimettiamo!
#self.reg_button = wx.Button(self, ID_REG, "new login")
#self.button_sizer.Add(self.reg_button, 1, wx.ALIGN_CENTER)
#wx.EVT_BUTTON(self, ID_REG, self.register)
# XXX Questo lo rimettiamo!
#self.lost_button = wx.Button(self, ID_LOST, "lost login")
#self.button_sizer.Add(self.lost_button, 1, wx.ALIGN_CENTER)
#wx.EVT_BUTTON(self, ID_LOST, self.lostaccount)
#self.hbox = wx.BoxSizer(wx.HORIZONTAL)
self.hbox = wx.BoxSizer(wx.VERTICAL)
self.hbox.Add(self.main_sizer, 1, wx.ALL | wx.EXPAND, 10)
self.hbox.Add(self.button_sizer, 1, wx.ALIGN_CENTER_HORIZONTAL, 1)
self.SetSizer(self.hbox)
self.SetAutoLayout(1)
self.hbox.Fit(self)
def register(self, event):
self.SetReturnCode( ID_REG )
self.EndModal( ID_REG )
#import register
#self.Pop = model.childWindow(self, register.Register, "./gui/register.rsrc.py")
#self.Pop.title = self.getText('downloadtitle')+size+" kb"
#self.Pop.components.downpr.text = self.getText('downloadtext')+size+" kb"
#self.Pop.visible = True
def lostaccount(self, event):
import lostaccount
self.Pop = model.childWindow(self, lostaccount.LostAccount, "./gui/lostaccount.rsrc.py")
#self.Pop.title = self.getText('downloadtitle')+size+" kb"
#self.Pop.components.downpr.text = self.getText('downloadtext')+size+" kb"
self.Pop.visible = True
def Ok(self, event):
self.SetReturnCode( ID_OK )
self.EndModal( ID_OK )
def cancel(self, event):
self.SetReturnCode( ID_CANCEL )
self.EndModal( ID_CANCEL )
def OldLogin():
dl=loginDialog()
dl.Enable(enable=True)
mainbg = wx.GetApp().getCurrentBackground()
ret = dl.ShowModal()
if ID_OK==ret:
user = dl.username.GetValue()
pwd = dl.password.GetValue()
if len(user) < 1:
user=None
if len(pwd) < 4:
pwd=None
print 'OK'
return [user, pwd]
elif ID_CANCEL==ret:
user = "stoplogin"
pwd = "stoplogin"
print 'CANCEL'
return [user, pwd]
elif ID_REG==ret:
import register,time
Pop = model.childWindow(mainbg, register.Register, "./gui/register.rsrc.py")
Pop.visible = True
Pop.done = False
while not Pop.done:
time.sleep(0.2)
print 'USCITO!'
else:
print 'NONE'
return [None, None]
def Login():
done=False
todo='login'
while not done:
if todo=='login':
dl=loginDialog()
dl.Enable(enable=True)
ret = dl.ShowModal()
if ID_OK==ret:
user = dl.username.GetValue()
pwd = dl.password.GetValue()
if len(user) < 1:
user=None
if len(pwd) < 4:
pwd=None
print 'OK'
done=True
retvar = [user, pwd]
elif ID_CANCEL==ret:
user = "stoplogin"
pwd = "stoplogin"
print 'CANCEL'
done=True
retvar = [user, pwd]
elif ID_REG==ret:
todo='register'
else:
print 'NONE'
done=True
retvar = [None, None]
elif todo=='register':
import register
dl=register.Register(wx.GetApp().getCurrentBackground(),
resource.ResourceFile("./gui/register.rsrc.py").getResource())
dl.visible=True
ret = dl.ShowModal()
print 'USCITO'
return retvar
upgradeText="""
Una nuova versione di SkyliveNG e' disponibile.
Vuoi aggiornare ora?
A new version of the SkyliveNG client is available.
Do you want to upgrade now?
"""
class upgradeDialog(wx.Dialog):
def __init__(self):
wx.Dialog.__init__(self, None, wx.NewId(), "SkyliveNG Upgrade",
style=wx.DEFAULT_DIALOG_STYLE | wx.STAY_ON_TOP | wx.CAPTION)
self.main_sizer = wx.FlexGridSizer(cols=1, vgap=5, hgap=5)
self.main_sizer.Add(wx.StaticText(self, -1, getText("upgradeText")),1, wx.ALIGN_CENTER)
self.button_sizer = wx.FlexGridSizer(cols=3, vgap=5, hgap=5)
self.ok_button = wx.Button(self, ID_OK, "OK")
self.button_sizer.Add(self.ok_button,1, wx.ALIGN_CENTER)
wx.EVT_BUTTON(self, ID_OK, self.Ok)
self.no_button = wx.Button(self, ID_NO, "NO")
self.button_sizer.Add(self.no_button, 1, wx.ALIGN_CENTER)
wx.EVT_BUTTON(self, ID_NO, self.no)
self.later_button = wx.Button(self, ID_LATER, "LATER")
self.button_sizer.Add(self.later_button, 1, wx.ALIGN_CENTER)
wx.EVT_BUTTON(self, ID_LATER, self.later)
self.hbox = wx.BoxSizer(wx.VERTICAL)
self.hbox.Add(self.main_sizer, 1, wx.ALL | wx.EXPAND, 10)
self.hbox.Add(self.button_sizer, 0, wx.ALIGN_CENTER_HORIZONTAL, 1)
self.SetSizer(self.hbox)
self.SetAutoLayout(1)
self.hbox.Fit(self)
def Ok(self, event):
self.SetReturnCode( ID_OK )
self.EndModal( ID_OK )
def later(self, event):
self.SetReturnCode( ID_LATER )
self.EndModal( ID_LATER )
def no(self, event):
self.SetReturnCode( ID_NO )
self.EndModal( ID_NO )
def Upgrade():
du = upgradeDialog()
du.Enable(enable=True)
mainbg = wx.GetApp().getCurrentBackground()
ret = du.ShowModal()
if ID_OK==ret:
return 'UPGRADE'
elif ID_NO==ret:
return 'NOUPGRADE'
return 'LATERUPGRADE'
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Image Adjust',
'size':(446, 255),
'icon':'gui/img/ICONA.ico',
'backgroundColor':(192, 192, 192),
'components': [
{'type':'StaticBox',
'name':'adjustBox',
'position':(7, 10),
'size':(432, 160),
'label':'Image Adjust',
},
{'type':'StaticBox',
'name':'toolsBox',
'position':(7, 180),
'size':(432, 48),
'label':'Tools',
},
{'type':'StaticText',
'name':'luminanceTXT',
'position':(20, 68),
'text':'Luminance',
},
{'type':'Slider',
'name':'Bright',
'position':(95, 65),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':100,
},
{'type':'StaticText',
'name':'contrastTXT',
'position':(20, 33),
'text':'Contrast',
},
{'type':'Slider',
'name':'Contrast',
'position':(95, 30),
'size':(299, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':100,
},
{'type':'StaticText',
'name':'contrShow',
'position':(400, 33),
'text':'1',
},
{'type':'StaticText',
'name':'brightShow',
'position':(400, 68),
'text':'1',
},
{'type':'StaticText',
'name':'StaticText4',
'position':(20, 138),
'text':'Str. Max',
},
{'type':'Slider',
'name':'strMax',
'position':(95, 135),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':200,
},
{'type':'StaticText',
'name':'StaticText3',
'position':(20, 103),
'text':'Str. Min',
},
{'type':'Slider',
'name':'strMin',
'position':(95, 100),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'strMinVal',
'position':(400, 103),
'text':'0',
},
{'type':'StaticText',
'name':'strMaxVal',
'position':(400, 138),
'text':'200',
},
{'type':'Button',
'name':'resetButton',
'position':(20, 199),
'size':(-1, 23),
'label':'Reset Change',
},
{'type':'Button',
'name':'negativeButton',
'position':(130, 199),
'size':(-1, 23),
'label':'Negative',
},
{'type':'Button',
'name':'autoContrastButton',
'position':(240, 199),
'size':(-1, 23),
'label':'AutoContrast',
},
{'type':'Button',
'name':'equalizeButton',
'position':(350, 199),
'size':(-1, 23),
'label':'Equalize',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Image Adjust',
'size':(446, 238),
'icon':'gui/img/ICONA.ico',
'backgroundColor':(192, 192, 192),
'components': [
{'type':'StaticText',
'name':'luminanceTXT',
'position':(20, 68),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Luminance',
},
{'type':'Slider',
'name':'Bright',
'position':(95, 65),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':100,
},
{'type':'StaticText',
'name':'contrastTXT',
'position':(20, 33),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Contrast',
},
{'type':'Slider',
'name':'Contrast',
'position':(95, 30),
'size':(299, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':100,
},
{'type':'StaticText',
'name':'contrShow',
'position':(400, 33),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'1',
},
{'type':'StaticText',
'name':'brightShow',
'position':(400, 68),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'1',
},
{'type':'StaticText',
'name':'maxTXT',
'position':(20, 138),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Str. Max',
},
{'type':'Slider',
'name':'strMax',
'position':(95, 135),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':200,
},
{'type':'StaticText',
'name':'minTXT',
'position':(20, 103),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Str. Min',
},
{'type':'Slider',
'name':'strMin',
'position':(95, 100),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'strMinVal',
'position':(400, 103),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'0',
},
{'type':'StaticText',
'name':'strMaxVal',
'position':(400, 138),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'200',
},
{'type':'StaticBox',
'name':'adjustBox',
'position':(7, 10),
'size':(432, 160),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Image Adjust',
},
{'type':'StaticBox',
'name':'toolsBox',
'position':(7, 180),
'size':(432, 48),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Tools',
},
{'type':'Button',
'name':'resetButton',
'position':(20, 196),
'size':(92, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Reset Change',
},
{'type':'Button',
'name':'negativeButton',
'position':(130, 196),
'size':(-1, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Negative',
},
{'type':'Button',
'name':'autoContrastButton',
'position':(240, 196),
'size':(83, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'AutoContrast',
},
{'type':'Button',
'name':'equalizeButton',
'position':(350, 196),
'size':(-1, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Equalize',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Image Adjust',
'size':(446, 260),
'icon':'gui/img/ICONA.ico',
'backgroundColor':(192, 192, 192),
'components': [
{'type':'StaticText',
'name':'luminanceTXT',
'position':(20, 68),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Luminance',
},
{'type':'Slider',
'name':'Bright',
'position':(95, 65),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':100,
},
{'type':'StaticText',
'name':'contrastTXT',
'position':(20, 33),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Contrast',
},
{'type':'Slider',
'name':'Contrast',
'position':(95, 30),
'size':(299, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':100,
},
{'type':'StaticText',
'name':'contrShow',
'position':(400, 33),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'1',
},
{'type':'StaticText',
'name':'brightShow',
'position':(400, 68),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'1',
},
{'type':'StaticText',
'name':'StaticText4',
'position':(20, 138),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Str. Max',
},
{'type':'Slider',
'name':'strMax',
'position':(95, 135),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':200,
},
{'type':'StaticText',
'name':'StaticText3',
'position':(20, 103),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Str. Min',
},
{'type':'Slider',
'name':'strMin',
'position':(95, 100),
'size':(300, -1),
'labels':False,
'layout':'horizontal',
'max':200,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'strMinVal',
'position':(400, 103),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'0',
},
{'type':'StaticText',
'name':'strMaxVal',
'position':(400, 138),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'200',
},
{'type':'StaticBox',
'name':'adjustBox',
'position':(7, 10),
'size':(432, 160),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Image Adjust',
},
{'type':'StaticBox',
'name':'toolsBox',
'position':(7, 180),
'size':(432, 48),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Tools',
},
{'type':'Button',
'name':'resetButton',
'position':(20, 196),
'size':(92, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Reset Change',
},
{'type':'Button',
'name':'negativeButton',
'position':(130, 196),
'size':(-1, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Negative',
},
{'type':'Button',
'name':'autoContrastButton',
'position':(240, 196),
'size':(83, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'AutoContrast',
},
{'type':'Button',
'name':'equalizeButton',
'position':(350, 196),
'size':(-1, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Equalize',
},
] # end components
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, graphic
import ImageEnhance, wx, ImageOps
try:
from PIL import Image
except:
import Image
from skylive.lang import language
class imageAdj(model.Background):
def on_initialize(self, event):
self.parent = self.getParent()
self.image = self._parent.origImage
self.lang = self.parent.lang
self.gui = 'imageadj'
self.ItemText = language.getItemText
self.setGui()
self.origImage = self.image[0]
self.origImage2 = self.image[6]
self.resetValues()
def resetValues(self):
self.brightedImg = False
self.contrastedImg = False
self.negSel = False
self.components.Contrast.value = 100
self.components.Bright.value = 100
self.contrValue = 1.0
self.brightValue = 1.0
#self.minNewVal = -1 # assigned -1 because min max value are positive when setted
#self.maxNewVal = -1
# hack to put stretch bars to the right levels on open and on reset
self.maxNewVal = self._parent.autoMax
self.minNewVal = self._parent.autoMin
self.components.strMax.value = self.minNewVal
self.components.strMax.value = self.maxNewVal
self.stretchImage()
# end hack
self.components.contrShow.text = str(int(self.contrValue*100))+"%"
self.components.brightShow.text = str(int(self.brightValue*100))+"%"
self.actualModImage = self.origImage
self.getMinMax(self.origImage)
def on_Contrast_select(self, event):
self.contrValue = float(self.components.Contrast.value) / 100
self.components.contrShow.text = str(int(self.contrValue*100))+"%"
if self.brightedImg:
if self.brightedImg != self.actualModImage:
ImageToMod = self.actualModImage
else:
ImageToMod = self.brightedImg
else:
if self.origImage != self.actualModImage:
ImageToMod = self.actualModImage
else:
ImageToMod = self.origImage
modImage = ImageEnhance.Contrast(ImageToMod)
newmodImage = modImage.enhance(self.contrValue)
self.contrastedImg = newmodImage
self.refreshImg(newmodImage)
def on_Bright_select(self, event):
self.brightValue = float(self.components.Bright.value) / 100
self.components.brightShow.text = str(int(self.brightValue*100))+"%"
if self.contrastedImg:
if self.contrastedImg != self.actualModImage:
ImageToMod = self.actualModImage
else:
ImageToMod = self.contrastedImg
else:
if self.origImage != self.actualModImage:
ImageToMod = self.actualModImage
else:
ImageToMod = self.origImage
modImage = ImageEnhance.Brightness(ImageToMod)
newmodImage = modImage.enhance(self.brightValue)
self.brightedImg = newmodImage
self.refreshImg(newmodImage)
def refreshImg(self, imgmod):
self._parent.pilImage = imgmod
if self.image[7]:
imgTomod = imgmod.resize((self.image[1], self.image[2]))
else:
imgTomod = imgmod
image = wx.EmptyImage(self.image[1], self.image[2])
image.SetData(imgTomod.convert("RGB").tostring())
newBitmap = graphic.Bitmap()
newBitmap.setImageBits(image)
self._parent.components.ImageShow.bitmap = newBitmap
if self.contrValue == 1.0:
self.contrastedImg = False
if self.brightValue == 1.0:
self.brightedImg = False
def on_resetButton_mouseClick(self, event):
self.resetValues()
self.origImage = self.image[0]
self.refreshImg(self.origImage)
def on_negativeButton_mouseClick(self, event):
if self.negSel:
self.components.negativeButton.label = u"Negative"
self.negSel = False
else:
self.components.negativeButton.label = u"Positive"
self.negSel = True
newmodImage = ImageOps.invert(self.actualModImage)
self.refreshImg(newmodImage)
self.actualModImage = newmodImage
def on_autoContrastButton_mouseClick(self, event):
newmodImage = ImageOps.autocontrast(self.actualModImage, 0)
self.refreshImg(newmodImage)
self.actualModImage = newmodImage
def on_equalizeButton_mouseClick(self, event):
newmodImage = ImageOps.equalize(self.actualModImage)
self.refreshImg(newmodImage)
self.actualModImage = newmodImage
def stretchImage(self):
if self.minNewVal == -1:
min = self.strMinImg
else:
min = self.minNewVal
if self.maxNewVal == -1:
max = self.strMaxImg
else:
max = self.maxNewVal
if (max - min) != 0:
scale = self.image[5] / (max - min)
offset = -min * scale
newmodImage = self.origImage2.point(lambda i: i * scale + offset)
newmodImage = ImageOps.grayscale(newmodImage)
imgToview = self.applyPrevContrBright(newmodImage)
self.refreshImg(imgToview)
self.actualModImage = imgToview
else:
pass
def getMinMax(self, imgmod):
#min,max = imgmod.getextrema()
min = self.image[3]
max = self.image[4]
self.components.strMin.min = min
self.components.strMin.max = max
self.components.strMin.value = self.minNewVal
self.components.strMinVal.text = str(int(self.minNewVal))
self.components.strMax.min = min
self.components.strMax.max = max
self.components.strMax.value = self.maxNewVal
self.components.strMaxVal.text = str(int(self.maxNewVal))
self.strMinImg = min
self.strMaxImg = max
def on_strMin_select(self, event):
self.minNewVal = self.components.strMin.value
self.components.strMinVal.text = str(self.minNewVal)
self.stretchImage()
def on_strMax_select(self, event):
self.maxNewVal = self.components.strMax.value
self.components.strMaxVal.text = str(self.maxNewVal)
self.stretchImage()
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.components.luminanceTXT.text = self.getText('luminanceTXT')
self.components.contrastTXT.text = self.getText('contrastTXT')
self.components.adjustBox.label = self.getText('adjustBox')
self.components.toolsBox.label = self.getText('toolsBox')
self.components.resetButton.label = self.getText('resetButton')
self.components.negativeButton.label = self.getText('negativeButton')
self.components.autoContrastButton.label = self.getText('autoContrastButton')
self.components.equalizeButton.label = self.getText('equalizeButton')
def applyPrevContrBright(self, img):
brightImage = ImageEnhance.Brightness(img)
brightedIMG = brightImage.enhance(self.brightValue)
contrastImage = ImageEnhance.Contrast(brightedIMG)
contrastedImage = contrastImage.enhance(self.contrValue)
return contrastedImage
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'Imager',
'title':u'SkyliveNG Imager',
'size':(340, 320),
'icon':'gui/img/ICONA.ico',
'style':['resizeable'],
'backgroundColor':(192, 192, 192),
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
]
},
{'type':'Menu',
'name':'menuPhoto',
'label':'&Adjust',
'items': [
{'type':'MenuItem',
'name':'menuAdjustPhoto',
'label':'A&djust',
'command':'adjust',
},
]
},
{'type':'Menu',
'name':'menuInfo',
'label':'&Info',
'enabled':False,
'items': [
{'type':'MenuItem',
'name':'menuInfoPhoto',
'label':'Read H&eader',
'command':'readHeader',
},
]
},
]
},
'components': [
{'type':'Button',
'name':'ButtonDownload',
'position':(50, 260),
'size':(105, 23),
'label':'Download FIT',
'visible':False,
},
{'type':'Button',
'name':'ButtonSave',
'position':(30, 260),
'size':(75, 23),
'label':'Save image',
'visible':False,
},
{'type':'Button',
'name':'ButtonClose',
'position':(200, 260),
'size':(75, 23),
'label':'Close',
'visible':False,
},
{'type':'Button',
'name':'ButtonCompare',
'position':(300, 260),
'size':(190, 30),
'label':'Compare with DSS_SEARCH',
'visible':False,
},
{'type': 'Button',
'name':'ButtonSaveAs',
'position':(110, 260),
'size':(85, 23),
'label':'Save as..',
'visible':False,
},
{'type':'Image',
'name':'ImageShow',
'position':(10, 10),
'size':(320, 240),
'backgroundColor':(255, 255, 255),
'file':'./gui/img/Live.jpg',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'Imager',
'title':u'SkyliveNG Imager',
'size':(340, 320),
'icon':'gui/img/ICONA.ico',
'style':['resizeable'],
'backgroundColor':(192, 192, 192),
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'Exit',
'command':'exit',
},
]
},
{'type':'Menu',
'name':'menuPhoto',
'label':'Adjust',
'enabled':False,
'items': [
{'type':'MenuItem',
'name':'menuAdjustPhoto',
'label':'Adjust',
'command':'adjust',
},
]
},
{'type':'Menu',
'name':'menuInfo',
'label':'Info',
'enabled':False,
'items': [
{'type':'MenuItem',
'name':'menuInfoPhoto',
'label':'Read Header',
'command':'readHeader',
},
]
},
]
},
'components': [
{'type':'Button',
'name':'ButtonDownload',
'position':(50, 260),
'size':(85, 23),
'label':'Download FIT',
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'visible':False,
},
{'type':'Button',
'name':'ButtonSave',
'position':(30, 260),
'size':(75, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Save image',
'visible':False,
},
{'type':'Button',
'name':'ButtonClose',
'position':(200, 260),
'size':(75, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Close',
'visible':False,
},
{'type':'Button',
'name':'ButtonCompare',
'position':(280, 260),
'size':(160, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Compare with DSS_SEARCH',
'visible':False,
},
{'type': 'Button',
'name':'ButtonSaveAs',
'position':(110, 260),
'size':(85, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Save as..',
'visible':False,
},
{'type':'Image',
'name':'ImageShow',
'position':(10, 10),
'size':(320, 240),
'backgroundColor':(255, 255, 255),
'file':'./gui/img/Live.jpg',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'Imager',
'title':u'SkyliveNG Imager',
'size':(348, 343),
'icon':'gui/img/ICONA.ico',
'style':['resizeable'],
'backgroundColor':(192, 192, 192),
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
]
},
{'type':'Menu',
'name':'menuPhoto',
'label':'&Adjust',
'enabled':False,
'items': [
{'type':'MenuItem',
'name':'menuAdjustPhoto',
'label':'A&djust',
'command':'adjust',
},
]
},
{'type':'Menu',
'name':'menuInfo',
'label':'&Info',
'enabled':False,
'items': [
{'type':'MenuItem',
'name':'menuInfoPhoto',
'label':'Read H&eader',
'command':'readHeader',
},
]
},
]
},
'components': [
{'type':'Button',
'name':'ButtonDownload',
'position':(50, 260),
'label':'Download FIT',
'visible':False,
},
{'type':'Button',
'name':'ButtonSave',
'position':(30, 260),
'size':(75, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Save image',
'visible':False,
},
{'type':'Button',
'name':'ButtonClose',
'position':(200, 260),
'size':(-1, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Close',
'visible':False,
},
{'type':'Button',
'name':'ButtonCompare',
'position':(280, 260),
'size':(160, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Compare with DSS_SEARCH',
'visible':False,
},
{'type': 'Button',
'name':'ButtonSaveAs',
'position':(110, 260),
'size':(85, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Save as..',
'visible':False,
},
{'type':'Image',
'name':'ImageShow',
'position':(10, 10),
'size':(320, 240),
'backgroundColor':(255, 255, 255),
'file':'./gui/img/Live.jpg',
},
] # end components
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, dialog, graphic
import os, wx, platform
import gui, imageadj, info
from zipfile import ZipFile as zip
from skylive.lang import language
class SkyliveImager(model.Background):
def on_initialize(self, event):
try:
self.parent = self.getParent()
self.autoMax = self.parent.autoMax
self.autoMin = self.parent.autoMin
self.userhome = self.parent.usrDefSavePath
self.header = self.parent.fitsHeader
except:
pass
#this don't work with wxPython 2.6
self.lang = self.parent.lang
self.gui = 'imager'
self.ItemText = language.getItemText
self.setGui()
try:
self.defineFrom()
except:
pass
def refresh(self):
if self.origImage[7]:
imgTomod = self.origImage[0].resize((self.origImage[1], self.origImage[2]))
else:
imgTomod = self.origImage[0]
image = wx.EmptyImage(self.origImage[1], self.origImage[2])
image.SetData(imgTomod.convert("RGB").tostring())
newBitmap = graphic.Bitmap()
newBitmap.setImageBits(image)
self.components.ImageShow.bitmap = newBitmap
print "FATTO"
def on_exit_command(self, event):
self.close()
def on_ButtonClose_mouseClick(self, event):
self.close()
def on_ButtonDownload_mouseClick(self, event):
try:
#self._parent.callInTwisted('downloadFits', self.telescope)
self._parent.TwistedLoop.downloadFits(self.telescope)
except:
pass
self.close()
def on_ButtonSave_mouseClick(self, event):
# XXX: impostare meglio estensione e filename
# XXX: gestire anche la conversione in bmp/jpg/altro
# XXX: gestire anche il saveimage per lo snapshot
if self.actionSave =="fit":
defaultFN = self._parent.components.FileName.text+".fit"
result = dialog.saveFileDialog(self, self.getText('SaveDialog_FIT'), self.userhome, defaultFN, 'FITS Files: (*.fit)|*.fit')
if result.accepted:
path = result.paths[0]
if os.path.exists(path):
try:
os.unlink(path)
readFile = zip(self.fitfile, 'r')
fitsData = readFile.read("SkyFrame.fit")
readFile.close()
savedFile = open(path, 'wb')
savedFile.write(fitsData)
savedFile.close()
except:
dialog.alertDialog("ERROR: Cannot overwrite "+str(path))
else:
readFile = zip(self.fitfile, 'r')
fitsData = readFile.read("SkyFrame.fit")
readFile.close()
savedFile = open(path, 'wb')
savedFile.write(fitsData)
savedFile.close()
elif self.actionSave == "bmp":
result = dialog.saveFileDialog(self, self.getText('SaveDialog_BMP'), self.userhome, 'snap.bmp', 'BMP Files: (*.bmp)|*.bmp')
if result.accepted:
path=result.paths[0]
if os.path.exists(path):
try:
os.unlink(path)
self.SnapBitmap.saveFile(path)
except:
dialog.alertDialog("ERROR: Cannot overwrite "+str(path))
else:
self.SnapBitmap.saveFile(path)
else:
pass
self.mainPathChange(path)
def on_adjust_command(self, event=None):
if platform.system == "Microsoft":
sysType = "Windows"
else:
sysType = platform.system()
if not os.path.exists(os.path.normpath("./gui/imageadj."+sysType+".rsrc.py")):
sysType = "Linux"
self.adjustImg = model.childWindow(self, imageadj.imageAdj, "./gui/imageadj."+sysType+".rsrc.py")
self.adjustImg._parent = self
self.adjustImg.visible = True
def defineFrom(self):
if self.fromEvent == "photodown":
self.components.ButtonSave.label = self.getText('ButtonSave_FIT')
self.actionSave = "fit"
try:
self.MenuBar.setEnabled('menuPhoto', True)
self.MenuBar.setEnabled('menuInfo', True)
except:
self.menuBar.setEnabled('menuPhoto', True)
self.menuBar.setEnabled('menuInfo', True)
elif self.fromEvent == "snapshot":
self.components.ButtonSave.label = self.getText('ButtonSave_BMP')
self.actionSave = "bmp"
else:
pass
def on_readHeader_command(self, event):
hd = self.header
rsrc = "./gui/info.rsrc.py"
try:
if self.parent.systemType == 'Darwin':
rsrc = "./gui/info.rsrc.Darwin.py"
except:
pass
self.headerPop = model.childWindow(self, info.infoBox, rsrc)
self.headerPop.title = "Fits Header"
self.headerPop.components.infobox.text='FIELD\t\t\tVALUE\n'
fields = self.header.keys()
for x in fields:
try:
txtHeader = str(hd[x])+'\n'
self.headerPop.components.infobox.appendText(txtHeader)
except:
pass
def on_ButtonCompare_mouseClick(self, event):
try:
#self._parent.callInTwisted('downloadDss', self.imageData[0], self.imageData[1],
self._parent.TwistedLoop.downloadDss(self.imageData[0], self.imageData[1],
self.imageData[2], self.imageData[3])
except:
pass
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.components.ButtonDownload.label = self.getText('ButtonDownload')
self.components.ButtonCompare.label = self.getText('ButtonCompare')
self.components.ButtonClose.label = self.getText('ButtonClose')
self.components.ButtonSaveAs.label = self.getText('ButtonSaveAs')
submenu = ['menuFileExit', 'menuAdjustPhoto', 'menuInfoPhoto']
try:
for item in submenu:
idmenuItem = self.menuBar.getMenuId(item)
self.MenuBar.SetLabel(idmenuItem, self.getText(item))
except:
pass
def on_ButtonSaveAs_mouseClick(self, event):
self.getAndSaveImage()
def getAndSaveImage(self):
try:
imageFromPil = self.pilImage
except:
imageFromPil = False
if imageFromPil:
aStyle = wx.SAVE | wx.HIDE_READONLY | wx.OVERWRITE_PROMPT
result = dialog.saveFileDialog(self, self.getText('SaveDialog_SaveAs'), self.userhome, self._parent.components.FileName.text, 'BMP File: (*.bmp)|*.bmp|JPG File: (*.jpg)|*.jpg', aStyle)
if result.accepted:
path=result.paths[0]
if not os.path.splitext(os.path.split(path)[1])[1]:
dialog.alertDialog(self, self.getText('SaveDialog_alertSaveAs'))
self.getAndSaveImage()
else:
imageFromPil.save(path)
self.mainPathChange(path)
def mainPathChange(self, path):
newpath = path
if not os.path.isdir(path):
newpath, file = os.path.split(path)
if newpath != self.userhome and os.path.isdir(newpath):
print 'diverso cambio'
self.parent.components.PathField.text = newpath
self.parent.config.put_usrDefaultPath(newpath)
self.parent.usrDefSavePath = newpath
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model
class infoBox(model.Background):
def on_initialize(self, event):
pass
def on_closeinfo_mouseClick(self, event):
self.close()
def on_size(self, event):
self.SetSizeHints(200, 150)
w, h = self.size
if w > 199 and h > 149:
self.components.htmlbox.size = (w-20, h-35)
self.components.closeinfo.posizion = ((w/2)-25, (h-35)+10)
self.panel.SetSize(self.size)
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':' ',
'icon':'gui/img/ICONA.ico',
'size':(530, 310),
'components': [
{'type':'Button',
'name':'closeinfo',
'position':(230, 285),
'size':(50, 25),
'label':u'Close',
},
{'type':'TextArea',
'name':'infobox',
'position':(10, 10),
'size':(510, 275),
'editable':False,
},
{'type':'InfoHtmlWindow',
'name':'htmlbox',
'position':(10, 10),
'size':(510, 275),
'editable':False,
'visible':False,
},
] # end components
} # end background
] # end backgrounds
} }
from Pycard import model, graphic, dialog
import wx, os
#from cStringIO import StringIO
class LiveDuplicate(model.Background):
def on_initialize(self, event):
self.SetSizeHints(80, 87)
def resizeImage(self, image):
nolog = wx.LogNull()
newBitmap = graphic.Bitmap()
if hasattr(image, 'getBits'):
# on OSX we have a Pycard.image.Bitmap instance!
wximage = wx.ImageFromBitmap(image.getBits())
else:
wximage = wx.ImageFromBitmap(image)
w, h = wximage.GetSize()
ww, wh = self.size
ih = (int(ww-1)*int(h))/int(w)
if ih > int(wh-40):
iw = (int(wh-40)*int(w))/int(h)
ih = (iw*int(h))/int(w)
else:
iw = (int(w)*ih)/int(h)
wximage.Rescale(iw, ih)
newBitmap.setImageBits(wximage)
self.LiveBitmap = newBitmap
self.title="Live Image telescope %s" % str(self._parent.telescopesel)
self.components.Image1.autoRefresh = 0
self.components.Image1.size = (iw, ih)
self.components.Image1.clear()
self.components.Image1.autoRefresh = 1
self.components.Image1.drawBitmapScaled(newBitmap, (0, 0), (iw, ih))
self.panel.SetSize(self.size)
#if self.ignoreSizeEvent == 1:
#self.SetClientSize((iw, ih))
del nolog
def setLiveImage(self, image):
nolog = wx.LogNull()
self.title="Live Image telescope %s" % str(self._parent.telescopesel)
self.originalimage = image
self.resizeImage(image)
del nolog
def on_menuSave_select(self, event):
self.userhome = self._parent.usrDefSavePath
result = dialog.saveFileDialog(self, 'Save BMP', self.userhome, 'snap.bmp', 'BMP Files: (*.bmp)|*.bmp')
path = self.userhome
if result.accepted:
path=result.paths[0]
if os.path.exists(path):
try:
os.unlink(path)
self.LiveBitmap.saveFile(path)
except:
dialog.alertDialog("ERROR: Cannot overwrite "+str(path))
else:
self.LiveBitmap.saveFile(path)
self.mainPathChange(path)
def mainPathChange(self, path):
self.userhome = self._parent.usrDefSavePath
newpath = path
if not os.path.isdir(path):
newpath, file = os.path.split(path)
if newpath != self.userhome and os.path.isdir(newpath):
self._parent.components.PathField.text = newpath
self._parent.config.put_usrDefaultPath(newpath)
self._parent.usrDefSavePath = newpath
def on_size(self, event):
self.resizeImage(self.originalimage)
def on_close(self, event):
self._parent.livedup = False
event.skip()
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgLive',
'title':u'Live image',
'size':(321, 269),
'icon':'./gui/img/ICONA.ico',
'style':['resizeable'],
'useSizers':0,
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
{'type':'MenuItem',
'name':'menuSave',
'label':'Save Image',
},
]
},
]
},
'components': [
{'type':'BitmapCanvas',
'name':'Image1',
'position':(0, 0),
'size':(320, 240),
'file':'./gui/img/Live.jpg',
},
] # end components
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model
class LostAccount(model.Background):
def on_initialize(self, event):
pass
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Recover lost account info',
'size':(400, 300),
'useSizers':0,
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
]
},
]
},
'components': [
] # end components
,
'sizers':
[
{
'name' : 'ALL',
'typ' : 'i',
'children' : [
{
'name' : 'TOP SIZER',
'typ' : 'v',
'horGrowth' : 1,
'verGrowth' : 1 },
{
'name' : 'UNPLACED',
'typ' : 'i' },
] # end of ALL
},
] # end of sizers
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from skylive import config, conn, protocol
from skylive.utils import genutils as utils
import maingui
import wx, time, sys, os, platform
from Pycard import model, resource
class skyLive(model.Background):
mainpanel=False
def __getattribute__(self, name):
try:
selfattr = model.Background.__getattribute__(self, name)
return selfattr
except:
mainpanel = model.Background.__getattribute__(self, 'mainpanel')
if mainpanel:
if hasattr(mainpanel, name):
return getattr(mainpanel, name)
def on_initialize(self, event):
config.initialize()
sysType = utils.platform()
if sysType == "Microsoft":
self.systemType = "Windows"
else:
self.systemType = sysType
if (self.systemType == 'Linux') and (utils.is_eeepc()) or config.get_lowResPref('boot'):
self.systemType = 'EeePC'
if not self.systemType in ['EeePC', 'Linux', 'Windows', 'Darwin']:
self.systemType='Linux'
mainrsrc = resource.ResourceFile("./gui/maingui."+self.systemType+".rsrc.py").getResource()
self.mainpanel = maingui.mainPanel(self, mainrsrc.application.backgrounds[0])
#self.mainpanel.visible = True
{ 'application':{ 'type':'Application',
'name':'Template',
'backgrounds':
[
{ 'type':'Background',
'name':'SkyliveNoTemplate',
'title':'NoTemplate',
'size':( 10, 10 ),
'visible': False,
'components': []
}
]
}
}
{'application':{'type':'Application',
'name':'Skylive NG',
'backgrounds': [
{'type':'Background',
'name':'bgSkyliveNG',
'title':u'Skylive NG 0.1.5r5 For Mac OS X',
'size':(800, 600),
'backgroundColor':(192, 192, 192),
'visible': True,
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuCheckVersion',
'label':u'check updates',
},
{'type':'MenuItem',
'name':'menuSaveChat',
'label':u'Save Chat',
},
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
},
]
},
{'type':'Menu',
'name':'menuSettings',
'label':u'Settings',
'items': [
{'type':'MenuItem',
'name':'menuSettingsLogin',
'label':u'Login info',
},
{'type':'MenuItem',
'name':'menuSettingsPreference',
'label':u'Preference',
},
]
},
{'type':'Menu',
'name':'menuView',
'label':u'View',
'items': [
{'type':'MenuItem',
'name':'menuFitsOpen',
'label':u'F&its',
'command':'menuFitsOpen',
},
{'type':'MenuItem',
'name':'menuMeteoOpen',
'label':u'M&eteo',
'command':'menuMeteoOpen',
},
{'type':'MenuItem',
'name':'menuVideoOpen',
'label':u'AudioVideo',
'command':'menuVideoOpen',
},
{'type':'MenuItem',
'name':'menuAccount',
'label':u'Account',
'command':'menuAccount',
},
{'type':'MenuItem',
'name':'menuBooking',
'label':u'Booking',
'command':'menuBooking',
},
]
},
{'type':'Menu',
'name':'menuHelp',
'label':u'Help',
'items': [
{'type':'MenuItem',
'name':'menuHelpAboutSkyliveNG',
'label':u'About SkyliveNG',
'command':'about_skylive',
},
{'type':'MenuItem',
'name':'menuHelpHelpOnLine',
'label':u'OnLine Help',
'command':'OnLineHelp',
},
]
},
{'type':'Menu',
'name':'menuAdmin',
'label':u'Admin',
'visible': False,
'enabled': False,
'items': [
]
},
]
},
'components': [
{'type':'StaticBox',
'name':'MoveBox',
'position':(330, 48),
'size':(104, 85),
'foregroundColor':(0, 0, 255, 255),
},
{'type':'StaticBox',
'name':'Pointing',
'position':(332, 194),
'size':(468, 101),
'foregroundColor':(0, 0, 255, 255),
'label':u'Telescope Pointing',
},
{'type':'StaticBox',
'name':'PhotoInputs',
'position':(331, 296),
'size':(468, 130),
'foregroundColor':(0, 0, 255, 255),
'label':u'Photo inputs',
},
{'type':'StaticBox',
'name':'CCDBox',
'position':(335, 428),
'size':(468, 120),
'foregroundColor':(0, 0, 255, 255),
'label':u'Scripts GOTO and Photo',
},
{'type':'StaticBox',
'name':'StatusBox',
'position':(464, 132),
'size':(334, 62),
'foregroundColor':(0, 0, 255, 255),
'label':u'Status',
},
{'type':'StaticBox',
'name':'StaticBox4',
'position':(330, 132),
'size':(127, 62),
'foregroundColor':(0, 0, 255, 255),
'label':u'Guide Star',
},
{'type':'StaticBox',
'name':'Telescope',
'position':(440, 22),
'size':(358, 110),
'foregroundColor':(0, 255, 64, 255),
'label':u'Telescope',
},
{'type':'ComboBox',
'name':'TScopeCombo',
'position':(329, 22),
'size':(105, -1),
'items':[],
'text':u'Telescope1',
},
{'type':'TextField',
'name':'ChatField',
'position':(2, 547),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'size':(255, 23),
},
{'type':'Button',
'name':'ChatSend',
'position':(260, 550),
'size':(65, -1),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'label':u'Send',
},
{'type':'List',
'name':'UserlistArea',
'position':(220, 268),
'size':(108, 278),
'backgroundColor':(197, 234, 233, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(25, 0, 153, 255),
'items':[],
},
#{'type':'TextArea',
# 'name':'ChatArea',
# 'position':(2, 268),
# 'size':(220, 276),
# 'backgroundColor':(222, 227, 227, 255),
# 'editable':False,
# 'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
# },
{'type':'InfoHtmlWindow',
'name':'ChatArea',
'position':(2, 268),
'size':(230, 276),
'backgroundColor':(222, 227, 227, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'sansSerif', 'size': 8},
'horGrowth':1,
'userdata':'<html></html>',
'verGrowth':1,
},
{'type':'Button',
'name':'ButtonN',
'position':(367, 58),
'size':(30, -1),
'label':u'N',
},
{'type':'Button',
'name':'ButtonW',
'position':(339, 78),
'size':(30, -1),
'label':u'W',
},
{'type':'Button',
'name':'ButtonE',
'position':(395, 78),
'size':(30, -1),
'label':u'E',
},
{'type':'Button',
'name':'ButtonS',
'position':(367, 100),
'size':(30, -1),
'label':u'S',
},
{'type':'ComboBox',
'name':'ComboPlanets',
'position':(389, 211),
'size':(106, -1),
'items':[],
'text':u'Select',
},
{'type':'StaticText',
'name':'PointPlanets',
'position':(339, 215),
'backgroundColor':(192, 192, 192, 255),
'text':u'Planets',
},
{'type':'ComboBox',
'name':'ComboStars',
'position':(539, 211),
'size':(100, -1),
'items':[],
'text':u'Select',
},
{'type':'StaticText',
'name':'PointStars',
'position':(503, 215),
'backgroundColor':(192, 192, 192, 255),
'text':u'Stars',
},
{'type':'ComboBox',
'name':'ComboDouble',
'position':(689, 211),
'size':(104, -1),
'items':[],
'text':u'Select',
},
{'type':'StaticText',
'name':'PointDouble',
'position':(645, 215),
'backgroundColor':(192, 192, 192, 255),
'text':u'Double',
},
{'type':'ComboBox',
'name':'ComboMessier',
'position':(389, 234),
'size':(106, -1),
'items':[],
'text':u'Select',
},
{'type':'StaticText',
'name':'PointMessier',
'position':(337, 238),
'backgroundColor':(192, 192, 192, 255),
'text':u'Messier',
},
{'type':'Spinner',
'name':'SpinnerNGC',
'position':(539, 234),
'size':(99, -1),
'max':8000,
'min':0,
'value':8000,
},
{'type':'StaticText',
'name':'PointNGC',
'position':(506, 238),
'backgroundColor':(192, 192, 192, 255),
'text':u'NGC',
},
{'type':'Spinner',
'name':'SpinnerIC',
'position':(689, 234),
'size':(104, -1),
'backgroundColor':(255, 255, 255),
'max':5385,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'PointIC',
'position':(673, 238),
'backgroundColor':(192, 192, 192, 255),
'text':u'IC',
},
{'type':'TextField',
'name':'PointRA1',
'position':(358, 263),
'size':(24, -1),
'text':u'00',
},
{'type':'StaticText',
'name':'PointAR1',
'position':(339, 265),
'backgroundColor':(192, 192, 192, 255),
'text':u'RA',
},
{'type':'TextField',
'name':'PointRA2',
'position':(393, 263),
'size':(24, -1),
'text':u'00',
},
{'type':'StaticText',
'name':'PointAR2',
'position':(387, 265),
'backgroundColor':(192, 192, 192, 255),
'text':u':',
},
{'type':'TextField',
'name':'PointRA3',
'position':(426, 263),
'size':(24, -1),
'text':u'0',
},
{'type':'StaticText',
'name':'PointAR3',
'position':(420, 265),
'backgroundColor':(192, 192, 192, 255),
'text':u'.',
},
{'type':'StaticText',
'name':'PointDECtext',
'position':(457, 265),
'backgroundColor':(192, 192, 192, 255),
'text':u'DEC',
},
{'type':'TextField',
'name':'PointDEC1',
'position':(486, 263),
'size':(20, -1),
'text':u'+',
},
{'type':'TextField',
'name':'PointDEC2',
'position':(512, 263),
'size':(24, -1),
'text':u'00',
},
{'type':'StaticText',
'name':'PointDECtext1',
'position':(539, 265),
'backgroundColor':(192, 192, 192, 255),
'text':u':',
},
{'type':'TextField',
'name':'PointDEC3',
'position':(545, 263),
'size':(24, -1),
'text':u'00',
},
{'type':'Button',
'name':'PointGOTO',
'position':(582, 267),
'size':(95, -1),
'foregroundColor':(255, 0, 0, 255),
'label':u'GOTO',
},
{'type':'Button',
'name':'PointSendToScript',
'position':(689, 267),
'size':(105, -1),
'label':u'Send to script',
},
{'type':'Spinner',
'name':'SpinnerExposition',
'position':(370, 312),
'size':(60, -1),
'backgroundColor':(255, 255, 255),
'max':900,
'min':0,
'value':0,
},
{'type':'ComboBox',
'name':'ComboFilters',
'position':(469, 312),
'size':(60, -1),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'items':[],
'text':u'X',
},
{'type':'ComboBox',
'name':'ComboBin',
'position':(567, 312),
'size':(45, -1),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'items':[u'1', u'2', u'3'],
'stringSelection':u'2',
'text':u'2',
},
{'type':'CheckBox',
'name':'CheckBoxGuide',
'position':(779, 328),
'label':u' ',
},
{'type':'CheckBox',
'name':'CheckBoxWeb',
'position':(779, 345),
'checked':True,
'label':u' ',
},
{'type':'CheckBox',
'name':'CheckBoxAutoflat',
'position':(779, 362),
'label':u' ',
},
{'type':'TextField',
'name':'FileName',
'position':(408, 341),
'font':{'style': 'bold','faceName': u'Arial', 'family': 'sansSerif', 'size': 11},
'size':(184, -1),
'text':'SkyliveNG',
'editable':False,
'enabled':False
},
{'type':'Spinner',
'name':'Spinner1',
'position':(680, 335),
'size':(59, -1),
'max':100,
'min':0,
'value':0,
},
{'type':'Spinner',
'name':'SpinnerRepeat',
'position':(661, 312),
'size':(60, -1),
'backgroundColor':(255, 255, 255),
'max':500,
'min':0,
'value':0,
},
{'type':'Button',
'name':'PathChoose',
'position':(341, 370),
'size':(50, -1),
'label':u'Path',
},
{'type':'TextField',
'name':'PathField',
'position':(399, 368),
'size':(295, 23),
'text':u'/',
},
{'type':'CheckBox',
'name':'CheckBoxAutodark',
'position':(779, 379),
'label':u' ',
},
{'type':'Button',
'name':'LastPhoto',
'position':(340, 400),
'size':(89, -1),
'foregroundColor':(30, 144, 255, 255),
'label':u'Last photo',
},
{'type':'Button',
'name':'BigLive',
'position':(430, 400),
'size':(110, -1),
'foregroundColor':(30, 144, 255, 255),
'label':u'Live bigger ',
},
{'type':'Button',
'name':'MakePhoto',
'position':(554, 400),
'size':(108, -1),
'foregroundColor':(232, 19, 19, 255),
'label':u'MAKE PHOTO',
},
{'type':'Button',
'name':'PhotoSendToScript',
'position':(689, 400),
'size':(105, -1),
'label':u'Send to script',
},
{'type':'StaticText',
'name':'PhotoTXTRepeat',
'position':(618, 315),
'backgroundColor':(192, 192, 192, 255),
'text':u'Repeat',
},
{'type':'StaticText',
'name':'PhotoTXTStartnumber',
'position':(595, 343),
'backgroundColor':(192, 192, 192, 255),
'text':u'Start number',
},
{'type':'Button',
'name':'PhotoTXTFilename',
'position':(337, 345),
'size':(65, 25),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 11},
'label':'Filename',
},
{'type':'StaticText',
'name':'PhotoTXTWeb',
'position':(745, 349),
'backgroundColor':(192, 192, 192, 255),
'text':u' Web',
},
{'type':'StaticText',
'name':'PhotoTXTAutodark',
'position':(721, 382),
'backgroundColor':(192, 192, 192, 255),
'text':u'Autodark',
},
{'type':'StaticText',
'name':'PhotoTXTAutoflat',
'position':(728, 365),
'backgroundColor':(192, 192, 192, 255),
'text':u'Autoflat',
},
{'type':'StaticText',
'name':'PhotoTXTGuide',
'position':(740, 331),
'backgroundColor':(192, 192, 192, 255),
'text':u'Guide',
},
{'type':'StaticText',
'name':'PhotoTXTBin',
'position':(538, 315),
'backgroundColor':(192, 192, 192, 255),
'text':u'Bin',
},
{'type':'StaticText',
'name':'PhotoTXTFilter',
'position':(434, 315),
'backgroundColor':(192, 192, 192, 255),
'text':u'Filter',
},
{'type':'StaticText',
'name':'PhotoTXTExp',
'position':(337, 315),
'backgroundColor':(192, 192, 192, 255),
'text':u'Exp.',
},
{'type':'Button',
'name':'ScriptLoad',
'position':(340, 445),
'size':(58, -1),
'foregroundColor':(23, 143, 23, 255),
'label':u'Load',
},
{'type':'Button',
'name':'ScriptSave',
'position':(400, 445),
'size':(50, -1),
'foregroundColor':(165, 42, 42, 255),
'label':u'Save',
},
{'type':'Button',
'name':'ScriptStart',
'position':(455, 445),
'size':(50, -1),
'foregroundColor':(30, 144, 255, 255),
'label':u'Start',
},
{'type':'Button',
'name':'ScriptStop',
'position':(510, 445),
'size':(50, -1),
'label':u'Stop',
},
{'type':'Button',
'name':'ScriptContinue',
'position':(565, 445),
'size':(74, -1),
'foregroundColor':(30, 144, 255, 255),
'label':u'Continue',
},
{'type':'Button',
'name':'ScriptClear',
'position':(646, 445),
'size':(60, -1),
'foregroundColor':(127, 127, 127, 255),
'label':u'Clear',
},
{'type':'Button',
'name':'ScriptReset',
'position':(711, 445),
'size':(53, -1),
'foregroundColor':(127, 127, 127, 255),
'label':u'Reset',
},
{'type':'List',
'name':'ScriptArea',
'position':(336, 470),
'size':(455, 56),
'items':[],
},
{'type':'TextField',
'name':'ScriptStatus',
'position':(336, 528),
'size':(455, 17),
'editable':False,
'text':u'Waiting for commands...',
},
{'type':'StaticText',
'name':'StatusRain',
'position':(643, 172),
'backgroundColor':(192, 192, 192, 255),
'text':u'Weather:',
},
{'type':'StaticText',
'name':'StatusDome',
'position':(472, 173),
'backgroundColor':(192, 192, 192, 255),
'text':u'Observatory Dome:',
},
{'type':'StaticText',
'name':'StatusObject',
'position':(472, 151),
'backgroundColor':(192, 192, 192, 255),
'text':u'Current object:',
},
{'type':'StaticText',
'name':'FWHM',
'position':(674, 100),
'backgroundColor':(192, 192, 192, 255),
'text':'FWHM:',
},
{'type':'StaticText',
'name':'TelescopeCCDTemp',
'position':(640, 80),
'backgroundColor':(192, 192, 192, 255),
'text':u'CCD Temp:',
},
{'type':'StaticText',
'name':'MoveDEC',
'position':(674, 60),
'backgroundColor':(192, 192, 192, 255),
'text':u'DEC:',
},
{'type':'StaticText',
'name':'MoveRA',
'position':(683, 40),
'backgroundColor':(192, 192, 192, 255),
'text':u'RA:',
},
{'type':'StaticText',
'name':'TelescopeFilters',
'position':(427, 110),
'backgroundColor':(192, 192, 192, 255),
'text':u'Filters available:',
},
{'type':'StaticText',
'name':'TelescopeCCD',
'position':(448, 92),
'backgroundColor':(192, 192, 192, 255),
'text':u'CCD:',
},
{'type':'StaticText',
'name':'TelescopeFOW',
'position':(446, 72),
'backgroundColor':(192, 192, 192, 255),
'text':u'Field of view:',
},
{'type':'StaticText',
'name':'TelescopeFocal',
'position':(445, 54),
'backgroundColor':(192, 192, 192, 255),
'text':u'FOCAL:',
},
{'type':'StaticText',
'name':'TelescopeMODEL',
'position':(445, 37),
'backgroundColor':(192, 192, 192, 255),
'text':u'MODEL:',
},
{'type':'StaticText',
'name':'TelescopeModelText',
'position':(504, 39),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'GuideYerr',
'position':(386, 174),
'backgroundColor':(192, 192, 192, 255),
'text':u'Yerr: ',
},
{'type':'StaticText',
'name':'TextXerr',
'position':(384, 153),
'backgroundColor':(192, 192, 192, 255),
'text':u'Xerr: ',
},
{'type':'StaticText',
'name':'RainSensorText',
'position':(729, 175),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'ObservatoryDomeText',
'position':(600, 173),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'CurrentObjectText',
'position':(573, 153),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'YerrText',
'position':(425, 175),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(22, 56, 150, 255),
'text':u'0',
},
{'type':'StaticText',
'name':'XerrText',
'position':(425, 155),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(22, 56, 150, 255),
'text':u'0',
},
{'type':'StaticText',
'name':'FWHMText',
'position':(720, 100),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCDTempText',
'position':(720, 80),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'TelescopeDECText',
'position':(716, 60),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'TelescopeRAText',
'position':(715, 40),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'TelescopeFiltersText',
'position':(557, 111),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'TelescopeGPS',
'position':(600, 100),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 11},
'text':'Telescope Pos: Lat:',
},
{'type':'StaticText',
'name':'TelescopeGPS2',
'position':(670, 112),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 11},
'text':'Lon:',
},
{'type':'StaticText',
'name':'TelescopeGPSPos1',
'position':(700, 100),
'backgroundColor':(192, 192, 192),
'foregroundColor':(0, 0, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 11},
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeGPSPos2',
'position':(700, 112),
'backgroundColor':(192, 192, 192),
'foregroundColor':(0, 0, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 11},
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCDText',
'position':(489, 92),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'TelescopeFOVText',
'position':(524, 73),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'StaticText',
'name':'TelescopeFocalText',
'position':(504, 56),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 11},
'foregroundColor':(0, 0, 255, 255),
'text':u'-',
},
{'type':'Image',
'name':'GuideImage',
'position':(340, 151),
'size':(40, 40),
'backgroundColor':(255, 255, 255, 255),
'file':'gui/img/Guide.jpg',
},
{'type':'Image',
'name':'Live640',
'position':(2, 25),
'size':(320, 240),
'backgroundColor':(255, 255, 255, 255),
'file':'gui/img/Live.jpg',
},
{'type':'BitmapCanvas',
'name':'StatusText',
'position':(2, 2),
'size':(801, 21),
'font':{'faceName': u'Lucida Grande', 'family': 'default', 'size': 10},
'backgroundColor':(255, 255, 255, 255),
},
{'type':'BitmapCanvas',
'name':'SponsorCanvas',
'position':(330, 551),
'size':(333, 23),
'backgroundColor':(255, 255, 255, 255),
},
{'type':'Button',
'name':'Sponsor',
'position':(666, 551),
'size':(132, -1),
'label':u'>> Click HERE <<',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Skylive NG',
'backgrounds': [
{'type':'Background',
'name':'bgSkyliveNG',
'title':u'Skylive NG 0.1.5r5',
'size':(798, 478),
'backgroundColor':(192, 192, 192),
'icon':'gui/img/ICONA.ico',
'visible': True,
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'File',
'items': [
{'type':'MenuItem',
'name':'menuCheckVersion',
'label':u'check updates',
},
{'type':'MenuItem',
'name':'menuSaveChat',
'label':u'Save Chat',
},
{'type':'MenuItem',
'name':'menuFileExit',
'label':'Exit',
},
]
},
{'type':'Menu',
'name':'menuSettings',
'label':u'Settings',
'items': [
{'type':'MenuItem',
'name':'menuSettingsLogin',
'label':u'Login info',
},
{'type':'MenuItem',
'name':'menuSettingsPreference',
'label':u'Preference',
},
]
},
{'type':'Menu',
'name':'menuView',
'label':u'View',
'items': [
{'type':'MenuItem',
'name':'menuFitsOpen',
'label':u'Fits',
'command':'menuFitsOpen',
},
{'type':'MenuItem',
'name':'menuMeteoOpen',
'label':u'Meteo',
'command':'menuMeteoOpen',
},
{'type':'MenuItem',
'name':'menuVideoOpen',
'label':u'AudioVideo',
'command':'menuVideoOpen',
},
{'type':'MenuItem',
'name':'menuAccount',
'label':u'Account',
'command':'menuAccount',
},
{'type':'MenuItem',
'name':'menuBooking',
'label':u'Booking',
'command':'menuBooking',
},
]
},
{'type':'Menu',
'name':'menuHelp',
'label':u'Help',
'items': [
{'type':'MenuItem',
'name':'menuHelpAboutSkyliveNG',
'label':u'About SkyliveNG',
'command':'about_skylive',
},
{'type':'MenuItem',
'name':'menuHelpHelpOnLine',
'label':u'OnLine Help',
'command':'OnLineHelp',
},
]
},
{'type':'Menu',
'name':'menuAdmin',
'label':u'Admin',
'visible': False,
'enabled': False,
'items': [
]
},
]
},
'components': [
{'type':'StaticBox',
'name':'MoveBox',
'position':(328, 46),
'size':(104, 98),
'backgroundColor':(173, 216, 230),
'foregroundColor':(0, 0, 255),
},
{'type':'StaticBox',
'name':'Pointing',
'position':(326, 200),
'size':(468, 99),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'label':'Telescope Pointing',
},
{'type':'StaticBox',
'name':'PhotoInputs',
'position':(327, 295),
'size':(468, 119),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'label':'Photo inputs',
},
{'type':'StaticBox',
'name':'CCDBox',
'position':(324, 411),
'size':(390, 40),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'label':'Scripts GOTO and Photo',
},
{'type':'StaticBox',
'name':'StatusBox',
'position':(457, 140),
'size':(334, 62),
'backgroundColor':(30, 144, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'label':'Status',
},
{'type':'StaticBox',
'name':'StaticBox4',
'position':(329, 141),
'size':(127, 62),
'backgroundColor':(18, 186, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'label':'Guide Star',
},
{'type':'StaticBox',
'name':'Telescope',
'position':(437, 20),
'size':(358, 124),
'backgroundColor':(0, 255, 0),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 255, 64),
'label':'Telescope',
},
{'type':'ComboBox',
'name':'TScopeCombo',
'position':(329, 27),
'items':[],
'text':'Telescope1',
'size':(100, 25),
},
{'type':'TextField',
'name':'ChatField',
'position':(0, 420),
'size':(255, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
},
{'type':'Button',
'name':'ChatSend',
'position':(258, 420),
'size':(65, 26),
'label':'Send',
},
{'type':'UList',
'name':'UserlistArea',
'position':(233, 268),
'size':(89, 150),
'backgroundColor':(197, 234, 233),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 7},
'foregroundColor':(25, 0, 153),
'items':[],
},
#{'type':'TextArea',
# 'name':'ChatArea',
# 'position':(2, 268),
# 'size':(230, 150),
# 'backgroundColor':(222, 227, 227),
# 'editable':False,
# 'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
# },
{'type':'InfoHtmlWindow',
'name':'ChatArea',
'position':(2, 268),
'size':(230, 150),
'backgroundColor':(222, 227, 227, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'horGrowth':1,
'userdata':'<html></html>',
'verGrowth':1,
},
{'type':'Button',
'name':'ButtonN',
'position':(367, 50),
'size':(30, -1),
'label':'N',
},
{'type':'Button',
'name':'ButtonW',
'position':(337, 80),
'size':(30, -1),
'label':'W',
},
{'type':'Button',
'name':'ButtonE',
'position':(397, 80),
'size':(30, -1),
'label':'E',
},
{'type':'Button',
'name':'ButtonS',
'position':(367, 110),
'size':(30, -1),
'label':'S',
},
{'type':'ComboBox',
'name':'ComboPlanets',
'position':(386, 212),
'items':[],
'text':'Select',
'size':(100, 25),
},
{'type':'StaticText',
'name':'PointPlanets',
'position':(338, 216),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Planets',
},
{'type':'ComboBox',
'name':'ComboStars',
'position':(538, 211),
'items':[],
'text':'Select',
'size':(100, 25),
},
{'type':'StaticText',
'name':'PointStars',
'position':(503, 217),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Stars',
},
{'type':'ComboBox',
'name':'ComboDouble',
'position':(687, 211),
'items':[],
'text':'Select',
'size':(100, 25),
},
{'type':'StaticText',
'name':'PointDouble',
'position':(644, 216),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Double',
},
{'type':'ComboBox',
'name':'ComboMessier',
'position':(384, 242),
'items':[],
'text':'Select',
'size':(100, 25),
},
{'type':'StaticText',
'name':'PointMessier',
'position':(338, 247),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Messier',
},
{'type':'Spinner',
'name':'SpinnerNGC',
'position':(538, 241),
'size':(99, -1),
'backgroundColor':(255, 255, 255),
'max':8000,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'PointNGC',
'position':(506, 245),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'NGC',
},
{'type':'Spinner',
'name':'SpinnerIC',
'position':(687, 239),
'size':(104, -1),
'backgroundColor':(255, 255, 255),
'max':5385,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'PointIC',
'position':(673, 245),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'IC',
},
{'type':'TextField',
'name':'PointRA1',
'position':(361, 271),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointAR1',
'position':(339, 276),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'RA',
},
{'type':'TextField',
'name':'PointRA2',
'position':(393, 271),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointAR2',
'position':(389, 275),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':':',
},
{'type':'TextField',
'name':'PointRA3',
'position':(426, 272),
'size':(24, -1),
'text':'0',
},
{'type':'StaticText',
'name':'PointAR3',
'position':(420, 279),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'.',
},
{'type':'StaticText',
'name':'PointDECtext',
'position':(463, 276),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'DEC',
},
{'type':'TextField',
'name':'PointDEC1',
'position':(488, 273),
'size':(20, -1),
'text':'+',
},
{'type':'TextField',
'name':'PointDEC2',
'position':(512, 274),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointDECtext1',
'position':(540, 277),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':':',
},
{'type':'TextField',
'name':'PointDEC3',
'position':(545, 274),
'size':(24, -1),
'text':'00',
},
{'type':'Button',
'name':'PointGOTO',
'position':(578, 273),
'size':(95, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(255, 0, 0),
'label':'GOTO',
},
{'type':'Button',
'name':'PointSendToScript',
'position':(689, 273),
'size':(105, 23),
'backgroundColor':(255, 255, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Send to script',
},
{'type':'Spinner',
'name':'SpinnerExposition',
'position':(363, 310),
'size':(60, -1),
'backgroundColor':(255, 255, 255),
'max':900,
'min':0,
'value':0,
},
{'type':'ComboBox',
'name':'ComboFilters',
'position':(456, 310),
'size':(60, -1),
'items':[],
'text':'X',
},
{'type':'ComboBox',
'name':'ComboBin',
'position':(555, 312),
'size':(45, -1),
'items':[u'1', u'2', u'3'],
'stringSelection':'2',
'text':'X',
},
{'type':'Spinner',
'name':'SpinnerRepeat',
'position':(657, 308),
'size':(60, -1),
'backgroundColor':(255, 255, 255),
'max':500,
'min':0,
'value':0,
},
{'type':'CheckBox',
'name':'CheckBoxGuide',
'position':(779, 313),
'label':' ',
},
{'type':'CheckBox',
'name':'CheckBoxWeb',
'position':(779, 330),
'checked':True,
'label':' ',
},
{'type':'CheckBox',
'name':'CheckBoxAutoflat',
'position':(779, 347),
'label':' ',
},
{'type':'CheckBox',
'name':'CheckBoxAutodark',
'position':(779, 364),
'label':' ',
},
{'type':'TextField',
'name':'FileName',
'position':(400, 336),
'size':(184, 23),
'editable':False,
'enabled':False,
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'SkyliveNG',
},
{'type':'Spinner',
'name':'Spinner1',
'position':(661, 336),
'size':(59, -1),
'backgroundColor':(255, 255, 255),
'max':100,
'min':0,
'value':0,
},
{'type':'Button',
'name':'PathChoose',
'position':(340, 361),
'size':(50, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Path',
},
{'type':'TextField',
'name':'PathField',
'position':(400, 361),
'size':(295, -1),
'text':'/',
},
{'type':'Button',
'name':'LastPhoto',
'position':(340, 385),
'size':(-1, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(30, 144, 255),
'label':'Last photo',
},
{'type':'Button',
'name':'BigLive',
'position':(430, 385),
'size':(110, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(30, 144, 255),
'label':'Live bigger ',
},
{'type':'Button',
'name':'MakePhoto',
'position':(554, 385),
'size':(108, 23),
'backgroundColor':(255, 255, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(232, 19, 19),
'label':'MAKE PHOTO',
},
{'type':'Button',
'name':'PhotoSendToScript',
'position':(689, 385),
'size':(105, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Send to script',
},
{'type':'StaticText',
'name':'PhotoTXTRepeat',
'position':(615, 317),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Repeat',
},
{'type':'StaticText',
'name':'PhotoTXTStartnumber',
'position':(584, 339),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Start number',
},
{'type':'Button',
'name':'PhotoTXTFilename',
'position':(338, 339),
'size':(60, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Filename',
},
{'type':'StaticText',
'name':'PhotoTXTWeb',
'position':(745, 334),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':' Web',
},
{'type':'StaticText',
'name':'PhotoTXTAutodark',
'position':(721, 367),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Autodark',
},
{'type':'StaticText',
'name':'PhotoTXTAutoflat',
'position':(728, 350),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Autoflat',
},
{'type':'StaticText',
'name':'PhotoTXTGuide',
'position':(738, 317),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Guide',
},
{'type':'StaticText',
'name':'PhotoTXTBin',
'position':(529, 316),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Bin',
},
{'type':'StaticText',
'name':'PhotoTXTFilter',
'position':(428, 315),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Filter',
},
{'type':'StaticText',
'name':'PhotoTXTExp',
'position':(335, 314),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Exp.',
},
{'type':'Button',
'name':'ScriptLoad',
'position':(330, 425),
'size':(54, 24),
'foregroundColor':(23, 143, 23),
'label':'Load',
},
{'type':'Button',
'name':'ScriptSave',
'position':(385, 425),
'size':(50, 24),
'foregroundColor':(165, 42, 42),
'label':'Save',
},
{'type':'Button',
'name':'ScriptStart',
'position':(436, 425),
'size':(50, 24),
'foregroundColor':(30, 144, 255),
'label':'Start',
},
{'type':'Button',
'name':'ScriptStop',
'position':(487, 425),
'size':(50, 24),
'label':'Stop',
},
{'type':'Button',
'name':'ScriptContinue',
'position':(538, 425),
'size':(70, 24),
'foregroundColor':(30, 144, 255),
'label':'Continue',
},
{'type':'Button',
'name':'ScriptClear',
'position':(610, 425),
'size':(50, 24),
'foregroundColor':(127, 127, 127),
'label':'Clear',
},
{'type':'Button',
'name':'ScriptReset',
'position':(660, 425),
'size':(50, 24),
'foregroundColor':(127, 127, 127),
'label':'Reset',
},
{'type':'List',
'name':'ScriptArea',
'position':(326, 455),
'size':(455, 10),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'items':[],
},
{'type':'TextField',
'name':'ScriptStatus',
'position':(316, 511),
'size':(455, 10),
'editable':False,
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Waiting for commands...',
},
{'type':'StaticText',
'name':'StatusRain',
'position':(649, 174),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Weather:',
},
{'type':'StaticText',
'name':'StatusDome',
'position':(472, 176),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Observatory Dome:',
},
{'type':'StaticText',
'name':'StatusObject',
'position':(473, 154),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Current object:',
},
{'type':'StaticText',
'name':'FWHM',
'position':(671, 90),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'FWHM:',
},
{'type':'StaticText',
'name':'TelescopeCCDTemp',
'position':(641, 76),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'CCD Temp:',
},
{'type':'StaticText',
'name':'MoveDEC',
'position':(678, 60),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'DEC:',
},
{'type':'StaticText',
'name':'MoveRA',
'position':(685, 45),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'RA:',
},
{'type':'StaticText',
'name':'TelescopeFilters',
'position':(446, 92),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Filters available:',
},
{'type':'StaticText',
'name':'TelescopeGPS',
'position':(446, 110),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Telescope Pos: Lat:',
},
{'type':'StaticText',
'name':'TelescopeGPS2',
'position':(644, 113),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Lon:',
},
{'type':'StaticText',
'name':'TelescopeGPSPos1',
'position':(560, 110),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeGPSPos2',
'position':(672, 113),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCD',
'position':(446, 76),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'CCD:',
},
{'type':'StaticText',
'name':'TelescopeFOW',
'position':(446, 62),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Field of view:',
},
{'type':'StaticText',
'name':'TelescopeFocal',
'position':(446, 48),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'FOCAL:',
},
{'type':'StaticText',
'name':'TelescopeMODEL',
'position':(446, 33),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'MODEL:',
},
{'type':'StaticText',
'name':'TelescopeModelText',
'position':(495, 33),
'backgroundColor':(192, 192, 192),
'font':{'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'GuideYerr',
'position':(383, 173),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Yerr: ',
},
{'type':'StaticText',
'name':'TextXerr',
'position':(385, 151),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Xerr: ',
},
{'type':'StaticText',
'name':'RainSensorText',
'position':(713, 173),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'ObservatoryDomeText',
'position':(581, 175),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'CurrentObjectText',
'position':(563, 154),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'YerrText',
'position':(420, 174),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(22, 56, 150),
'text':'0',
},
{'type':'StaticText',
'name':'XerrText',
'position':(421, 153),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(22, 56, 150),
'text':'0',
},
{'type':'StaticText',
'name':'FWHMText',
'position':(715, 90),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCDTempText',
'position':(715, 76),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeDECText',
'position':(714, 58),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeRAText',
'position':(714, 45),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFiltersText',
'position':(544, 92),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCDText',
'position':(483, 76),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFOVText',
'position':(527, 62),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFocalText',
'position':(495, 48),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'Image',
'name':'GuideImage',
'position':(339, 155),
'size':(40, 40),
'backgroundColor':(255, 255, 255),
'file':'gui/img/Guide.jpg',
},
{'type':'Image',
'name':'Live640',
'position':(2, 25),
'size':(320, 240),
'backgroundColor':(255, 255, 255),
'file':'gui/img/Live.jpg',
},
{'type':'BitmapCanvas',
'name':'StatusText',
'position':(2, 2),
'size':(801, 21),
'backgroundColor':(255, 255, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 0),
},
{'type':'BitmapCanvas',
'name':'SponsorCanvas',
'position':(330, 551),
'size':(333, 23),
'backgroundColor':(255, 255, 255),
'font':{'style': 'italic', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 0),
},
{'type':'Button',
'name':'Sponsor',
'position':(718, 425),
'size':(65, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 6},
'label':'Click HERE',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Skylive NG',
'backgrounds': [
{'type':'Background',
'name':'bgSkyliveNG',
'title':u'Skylive NG 0.1.5r5 For Linux',
'size':(800, 600),
'icon':'gui/img/ICONA.ico',
'backgroundColor':(192, 192, 192),
'visible': True,
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'File',
'items': [
{'type':'MenuItem',
'name':'menuCheckVersion',
'label':u'check updates',
},
{'type':'MenuItem',
'name':'menuSaveChat',
'label':u'Save Chat',
},
{'type':'MenuItem',
'name':'menuFileExit',
'label':'Exit',
},
]
},
{'type':'Menu',
'name':'menuSettings',
'label':u'Settings',
'items': [
{'type':'MenuItem',
'name':'menuSettingsLogin',
'label':u'Login info',
},
{'type':'MenuItem',
'name':'menuSettingsPreference',
'label':u'Preference',
},
]
},
{'type':'Menu',
'name':'menuView',
'label':u'View',
'items': [
{'type':'MenuItem',
'name':'menuFitsOpen',
'label':u'Fits',
'command':'menuFitsOpen',
},
{'type':'MenuItem',
'name':'menuMeteoOpen',
'label':u'Meteo',
'command':'menuMeteoOpen',
},
{'type':'MenuItem',
'name':'menuVideoOpen',
'label':u'AudioVideo',
'command':'menuVideoOpen',
},
{'type':'MenuItem',
'name':'menuAccount',
'label':u'Account',
'command':'menuAccount',
},
{'type':'MenuItem',
'name':'menuBooking',
'label':u'Booking',
'command':'menuBooking',
},
]
},
{'type':'Menu',
'name':'menuHelp',
'label':u'Help',
'items': [
{'type':'MenuItem',
'name':'menuHelpAboutSkyliveNG',
'label':u'About SkyliveNG',
'command':'about_skylive',
},
{'type':'MenuItem',
'name':'menuHelpHelpOnLine',
'label':u'OnLine Help',
'command':'OnLineHelp',
},
]
},
{'type':'Menu',
'name':'menuAdmin',
'label':u'Admin',
'visible': False,
'enabled': False,
'items': [
]
},
]
},
'components': [
{'type':'StaticBox',
'name':'MoveBox',
'position':(330, 48),
'size':(104, 98),
'backgroundColor':(173, 216, 230),
'foregroundColor':(0, 0, 255),
},
{'type':'StaticBox',
'name':'Pointing',
'position':(330, 210),
'size':(468, 99),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'label':'Telescope Pointing',
},
{'type':'StaticBox',
'name':'PhotoInputs',
'position':(330, 309),
'size':(468, 119),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'label':'Photo inputs',
},
{'type':'StaticBox',
'name':'CCDBox',
'position':(330, 428),
'size':(468, 120),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'label':'Scripts GOTO and Photo',
},
{'type':'StaticBox',
'name':'StatusBox',
'position':(464, 146),
'size':(334, 62),
'backgroundColor':(30, 144, 255),
'foregroundColor':(0, 0, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Status',
},
{'type':'StaticBox',
'name':'StaticBox4',
'position':(330, 146),
'size':(127, 62),
'backgroundColor':(18, 186, 23),
'foregroundColor':(0, 0, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Guide Star',
},
{'type':'StaticBox',
'name':'Telescope',
'position':(440, 22),
'size':(358, 124),
'backgroundColor':(0, 255, 0),
'foregroundColor':(0, 255, 64),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Telescope',
},
{'type':'ComboBox',
'name':'TScopeCombo',
'position':(329, 27),
'size':(105, -1),
'items':[],
'text':'Telescope1',
},
{'type':'TextField',
'name':'ChatField',
'position':(2, 547),
'size':(255, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
},
{'type':'Button',
'name':'ChatSend',
'position':(258, 545),
'size':(65, 26),
'label':'Send',
},
{'type':'List',
'name':'UserlistArea',
'position':(233, 268),
'size':(89, 276),
'backgroundColor':(197, 234, 233),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 7},
'foregroundColor':(25, 0, 153),
'items':[],
},
#{'type':'TextArea',
# 'name':'ChatArea',
# 'position':(2, 268),
# 'size':(230, 276),
# 'backgroundColor':(222, 227, 227),
# 'editable':False,
# 'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
# },
{'type':'InfoHtmlWindow',
'name':'ChatArea',
'position':(2, 268),
'size':(230, 276),
'backgroundColor':(222, 227, 227, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(16, 16, 16, 255),
'horGrowth':1,
'userdata':'<html></html>',
'verGrowth':1,
},
{'type':'Button',
'name':'ButtonN',
'position':(367, 58),
'size':(30, -1),
'label':'N',
},
{'type':'Button',
'name':'ButtonW',
'position':(337, 87),
'size':(30, -1),
'label':'W',
},
{'type':'Button',
'name':'ButtonE',
'position':(397, 87),
'size':(30, -1),
'label':'E',
},
{'type':'Button',
'name':'ButtonS',
'position':(367, 117),
'size':(30, -1),
'label':'S',
},
{'type':'ComboBox',
'name':'ComboPlanets',
'position':(389, 226),
'size':(106, -1),
'items':[],
'text':'Select',
},
{'type':'StaticText',
'name':'PointPlanets',
'position':(339, 229),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Planets',
},
{'type':'ComboBox',
'name':'ComboStars',
'position':(539, 225),
'size':(100, -1),
'items':[],
'text':'Select',
},
{'type':'StaticText',
'name':'PointStars',
'position':(504, 227),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Stars',
},
{'type':'ComboBox',
'name':'ComboDouble',
'position':(689, 225),
'size':(104, -1),
'items':[],
'text':'Select',
},
{'type':'StaticText',
'name':'PointDouble',
'position':(645, 229),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Double',
},
{'type':'ComboBox',
'name':'ComboMessier',
'position':(389, 254),
'size':(106, -1),
'items':[],
'text':'Select',
},
{'type':'StaticText',
'name':'PointMessier',
'position':(339, 255),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Messier',
},
{'type':'Spinner',
'name':'SpinnerNGC',
'position':(539, 253),
'size':(99, -1),
'backgroundColor':(255, 255, 255),
'max':8000,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'PointNGC',
'position':(509, 255),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'NGC',
},
{'type':'Spinner',
'name':'SpinnerIC',
'position':(689, 253),
'size':(104, -1),
'backgroundColor':(255, 255, 255),
'max':5385,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'PointIC',
'position':(673, 258),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'IC',
},
{'type':'TextField',
'name':'PointRA1',
'position':(362, 281),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointAR1',
'position':(339, 285),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'RA',
},
{'type':'TextField',
'name':'PointRA2',
'position':(393, 281),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointAR2',
'position':(389, 285),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':':',
},
{'type':'TextField',
'name':'PointRA3',
'position':(424, 281),
'size':(24, -1),
'text':'0',
},
{'type':'StaticText',
'name':'PointAR3',
'position':(420, 286),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'.',
},
{'type':'StaticText',
'name':'PointDECtext',
'position':(462, 285),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'DEC',
},
{'type':'TextField',
'name':'PointDEC1',
'position':(490, 281),
'size':(20, -1),
'text':'+',
},
{'type':'TextField',
'name':'PointDEC2',
'position':(513, 281),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointDECtext1',
'position':(541, 284),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':':',
},
{'type':'TextField',
'name':'PointDEC3',
'position':(546, 281),
'size':(24, -1),
'text':'00',
},
{'type':'Button',
'name':'PointGOTO',
'position':(578, 280),
'size':(95, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(255, 0, 0),
'label':'GOTO',
},
{'type':'Button',
'name':'PointSendToScript',
'position':(689, 280),
'size':(105, 23),
'backgroundColor':(255, 255, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Send to script',
},
{'type':'Spinner',
'name':'SpinnerExposition',
'position':(365, 327),
'size':(60, -1),
'backgroundColor':(255, 255, 255),
'max':900,
'min':0,
'value':0,
},
{'type':'ComboBox',
'name':'ComboFilters',
'position':(463, 327),
'size':(60, -1),
'items':[],
'text':'X',
},
{'type':'ComboBox',
'name':'ComboBin',
'position':(557, 327),
'size':(45, -1),
'items':[u'1', u'2', u'3'],
'stringSelection':'2',
'text':'X',
},
{'type':'Spinner',
'name':'SpinnerRepeat',
'position':(661, 327),
'size':(60, -1),
'backgroundColor':(255, 255, 255),
'max':500,
'min':0,
'value':0,
},
{'type':'CheckBox',
'name':'CheckBoxGuide',
'position':(779, 328),
'label':' ',
},
{'type':'CheckBox',
'name':'CheckBoxWeb',
'position':(779, 345),
'checked':True,
'label':' ',
},
{'type':'CheckBox',
'name':'CheckBoxAutoflat',
'position':(779, 362),
'label':' ',
},
{'type':'CheckBox',
'name':'CheckBoxAutodark',
'position':(779, 379),
'label':' ',
},
{'type':'TextField',
'name':'FileName',
'position':(400, 351),
'font':{'style': 'bold','faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'size':(184, -1),
'text':'SkyliveNG',
'editable':False,
'enabled':False
},
{'type':'Spinner',
'name':'Spinner1',
'position':(661, 351),
'size':(59, -1),
'backgroundColor':(255, 255, 255),
'max':100,
'min':0,
'value':0,
},
{'type':'Button',
'name':'PathChoose',
'position':(340, 376),
'size':(50, 23),
'font':{'style': 'bold','faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Path',
},
{'type':'TextField',
'name':'PathField',
'position':(400, 376),
'size':(295, 23),
'text':'/',
},
{'type':'Button',
'name':'LastPhoto',
'position':(340, 400),
'size':(85, 23),
'font':{'style': 'bold','faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(30, 144, 255),
'label':'Last photo',
},
{'type':'Button',
'name':'BigLive',
'position':(430, 400),
'size':(110, 23),
'font':{'style': 'bold','faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(30, 144, 255),
'label':'Live bigger ',
},
{'type':'Button',
'name':'MakePhoto',
'position':(554, 400),
'size':(108, 23),
'backgroundColor':(255, 255, 255),
'font':{'style': 'bold','faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(232, 19, 19),
'label':'MAKE PHOTO',
},
{'type':'Button',
'name':'PhotoSendToScript',
'position':(689, 400),
'size':(105, 23),
'font':{'style': 'bold','faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Send to script',
},
{'type':'StaticText',
'name':'PhotoTXTRepeat',
'position':(618, 330),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Repeat',
},
{'type':'StaticText',
'name':'PhotoTXTStartnumber',
'position':(584, 354),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Start number',
},
{'type':'Button',
'name':'PhotoTXTFilename',
'position':(338, 354),
'size':(60, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Filename',
},
{'type':'StaticText',
'name':'PhotoTXTWeb',
'position':(745, 349),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':' Web',
},
{'type':'StaticText',
'name':'PhotoTXTAutodark',
'position':(721, 382),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Autodark',
},
{'type':'StaticText',
'name':'PhotoTXTAutoflat',
'position':(728, 365),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Autoflat',
},
{'type':'StaticText',
'name':'PhotoTXTGuide',
'position':(740, 331),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Guide',
},
{'type':'StaticText',
'name':'PhotoTXTBin',
'position':(533, 330),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Bin',
},
{'type':'StaticText',
'name':'PhotoTXTFilter',
'position':(428, 330),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Filter',
},
{'type':'StaticText',
'name':'PhotoTXTExp',
'position':(337, 330),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Exp.',
},
{'type':'Button',
'name':'ScriptLoad',
'position':(340, 445),
'size':(54, 24),
'foregroundColor':(23, 143, 23),
'label':'Load',
},
{'type':'Button',
'name':'ScriptSave',
'position':(400, 445),
'size':(50, 24),
'foregroundColor':(165, 42, 42),
'label':'Save',
},
{'type':'Button',
'name':'ScriptStart',
'position':(455, 445),
'size':(50, 24),
'foregroundColor':(30, 144, 255),
'label':'Start',
},
{'type':'Button',
'name':'ScriptStop',
'position':(510, 445),
'size':(50, 24),
'label':'Stop',
},
{'type':'Button',
'name':'ScriptContinue',
'position':(565, 445),
'size':(70, 24),
'foregroundColor':(30, 144, 255),
'label':'Continue',
},
{'type':'Button',
'name':'ScriptClear',
'position':(640, 445),
'size':(50, 24),
'foregroundColor':(127, 127, 127),
'label':'Clear',
},
{'type':'Button',
'name':'ScriptReset',
'position':(695, 445),
'size':(50, 24),
'foregroundColor':(127, 127, 127),
'label':'Reset',
},
{'type':'List',
'name':'ScriptArea',
'position':(336, 470),
'size':(455, 56),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'items':[],
},
{'type':'TextField',
'name':'ScriptStatus',
'position':(336, 528),
'size':(455, 17),
'editable':False,
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Waiting for commands...',
},
{'type':'StaticText',
'name':'StatusRain',
'position':(650, 184),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Weather:',
},
{'type':'StaticText',
'name':'StatusDome',
'position':(474, 184),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Observatory Dome:',
},
{'type':'StaticText',
'name':'StatusObject',
'position':(473, 161),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Current object:',
},
{'type':'StaticText',
'name':'FWHM',
'position':(671, 90),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'FWHM:',
},
{'type':'StaticText',
'name':'TelescopeCCDTemp',
'position':(650, 74),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'CCD Temp:',
},
{'type':'StaticText',
'name':'MoveDEC',
'position':(678, 60),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'DEC:',
},
{'type':'StaticText',
'name':'MoveRA',
'position':(685, 45),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'RA:',
},
{'type':'StaticText',
'name':'TelescopeFilters',
'position':(446, 92),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Filters available:',
},
{'type':'StaticText',
'name':'TelescopeGPS',
'position':(446, 110),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Telescope Pos: Lat:',
},
{'type':'StaticText',
'name':'TelescopeGPS2',
'position':(520, 122),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Lon:',
},
{'type':'StaticText',
'name':'TelescopeGPSPos1',
'position':(560, 110),
'backgroundColor':(192, 192, 192),
'foregroundColor':(0, 0, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeGPSPos2',
'position':(560, 122),
'backgroundColor':(192, 192, 192),
'foregroundColor':(0, 0, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCD',
'position':(446, 76),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'CCD:',
},
{'type':'StaticText',
'name':'TelescopeFOW',
'position':(446, 62),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Field of view:',
},
{'type':'StaticText',
'name':'TelescopeFocal',
'position':(446, 48),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'FOCAL:',
},
{'type':'StaticText',
'name':'TelescopeMODEL',
'position':(446, 33),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'MODEL:',
},
{'type':'StaticText',
'name':'TelescopeModelText',
'position':(495, 33),
'backgroundColor':(192, 192, 192),
'font':{'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'GuideYerr',
'position':(385, 183),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Yerr: ',
},
{'type':'StaticText',
'name':'TextXerr',
'position':(385, 162),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Xerr: ',
},
{'type':'StaticText',
'name':'RainSensorText',
'position':(715, 184),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'ObservatoryDomeText',
'position':(586, 184),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'CurrentObjectText',
'position':(564, 161),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'YerrText',
'position':(421, 183),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(22, 56, 150),
'text':'0',
},
{'type':'StaticText',
'name':'XerrText',
'position':(421, 162),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(22, 56, 150),
'text':'0',
},
{'type':'StaticText',
'name':'FWHMText',
'position':(715, 90),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCDTempText',
'position':(715, 74),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeDECText',
'position':(714, 58),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeRAText',
'position':(714, 45),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFiltersText',
'position':(544, 92),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCDText',
'position':(483, 76),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFOVText',
'position':(527, 62),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFocalText',
'position':(495, 48),
'backgroundColor':(192, 192, 192),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255),
'text':'-',
},
{'type':'Image',
'name':'GuideImage',
'position':(339, 159),
'size':(40, 40),
'backgroundColor':(255, 255, 255),
'file':'gui/img/Guide.jpg',
},
{'type':'Image',
'name':'Live640',
'position':(2, 25),
'size':(320, 240),
'backgroundColor':(255, 255, 255),
'file':'gui/img/Live.jpg',
},
{'type':'BitmapCanvas',
'name':'StatusText',
'position':(2, 2),
'size':(801, 21),
'backgroundColor':(255, 255, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
},
{'type':'BitmapCanvas',
'name':'SponsorCanvas',
'position':(330, 551),
'size':(333, 23),
'backgroundColor':(255, 255, 255),
'font':{'style': 'italic', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
},
{'type':'Button',
'name':'Sponsor',
'position':(666, 551),
'size':(132, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'>> Click HERE <<',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Skylive NG',
'backgrounds': [
{'type':'Background',
'name':'bgSkyliveNG',
'title':u'Skylive NG 0.1.5r5 For Windows',
'size':(810, 628),
'icon':'gui/img/ICONA.ico',
'backgroundColor':(192, 192, 192),
'visible': True,
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuCheckVersion',
'label':u'check updates',
},
{'type':'MenuItem',
'name':'menuSaveChat',
'label':u'Save Chat',
},
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
},
]
},
{'type':'Menu',
'name':'menuSettings',
'label':u'Settings',
'items': [
{'type':'MenuItem',
'name':'menuSettingsLogin',
'label':u'Login info',
},
{'type':'MenuItem',
'name':'menuSettingsPreference',
'label':u'Preference',
},
]
},
{'type':'Menu',
'name':'menuView',
'label':u'View',
'items': [
{'type':'MenuItem',
'name':'menuFitsOpen',
'label':u'F&its',
'command':'menuFitsOpen',
},
{'type':'MenuItem',
'name':'menuMeteoOpen',
'label':u'M&eteo',
'command':'menuMeteoOpen',
},
{'type':'MenuItem',
'name':'menuVideoOpen',
'label':u'AudioVideo',
'command':'menuVideoOpen',
},
{'type':'MenuItem',
'name':'menuAccount',
'label':u'Account',
'command':'menuAccount',
},
{'type':'MenuItem',
'name':'menuBooking',
'label':u'Booking',
'command':'menuBooking',
},
]
},
{'type':'Menu',
'name':'menuHelp',
'label':u'Help',
'items': [
{'type':'MenuItem',
'name':'menuHelpAboutSkyliveNG',
'label':u'About SkyliveNG',
'command':'about_skylive',
},
{'type':'MenuItem',
'name':'menuHelpHelpOnLine',
'label':u'OnLine Help',
'command':'OnLineHelp',
},
]
},
{'type':'Menu',
'name':'menuAdmin',
'label':u'Admin',
'visible': False,
'enabled': False,
'items': [
]
},
]
},
'components': [
{'type':'StaticBox',
'name':'MoveBox',
'position':(329, 47),
'size':(104, 98),
'backgroundColor':(192, 192, 192, 255),
'foregroundColor':(0, 0, 255, 255),
},
{'type':'StaticBox',
'name':'Pointing',
'position':(330, 210),
'size':(468, 99),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'label':'Telescope Pointing',
},
{'type':'StaticBox',
'name':'PhotoInputs',
'position':(330, 309),
'size':(468, 119),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'label':'Photo inputs',
},
{'type':'StaticBox',
'name':'CCDBox',
'position':(330, 428),
'size':(468, 120),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'label':'Scripts GOTO and Photo',
},
{'type':'StaticBox',
'name':'StatusBox',
'position':(464, 146),
'size':(334, 62),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'label':'Status',
},
{'type':'StaticBox',
'name':'StaticBox4',
'position':(330, 146),
'size':(127, 62),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'label':'Guide Star',
},
{'type':'StaticBox',
'name':'Telescope',
'position':(439, 21),
'size':(358, 124),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'label':'Telescope',
},
{'type':'ComboBox',
'name':'TScopeCombo',
'position':(330, 27),
'size':(105, -1),
'items':[],
'text':'Telescope1',
},
{'type':'TextField',
'name':'ChatField',
'position':(2, 547),
'size':(255, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
},
{'type':'Button',
'name':'ChatSend',
'position':(258, 545),
'size':(65, 26),
'label':'Send',
},
{'type':'UList',
'name':'UserlistArea',
'position':(233, 268),
'size':(89, 276),
'backgroundColor':(197, 234, 233, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 7},
'foregroundColor':(25, 0, 153, 255),
'items':[],
},
#{'type':'TextArea',
# 'name':'ChatArea',
# 'position':(2, 268),
# 'size':(230, 276),
# 'backgroundColor':(222, 227, 227, 255),
# 'editable':False,
# 'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
# },
{'type':'InfoHtmlWindow',
'name':'ChatArea',
'position':(2, 268),
'size':(230, 276),
'backgroundColor':(222, 227, 227, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'horGrowth':1,
'userdata':'<html></html>',
'verGrowth':1,
},
{'type':'Button',
'name':'ButtonN',
'position':(367, 58),
'size':(30, -1),
'label':'N',
},
{'type':'Button',
'name':'ButtonW',
'position':(337, 87),
'size':(30, -1),
'label':'W',
},
{'type':'Button',
'name':'ButtonE',
'position':(397, 87),
'size':(30, -1),
'label':'E',
},
{'type':'Button',
'name':'ButtonS',
'position':(367, 117),
'size':(30, -1),
'label':'S',
},
{'type':'ComboBox',
'name':'ComboPlanets',
'position':(389, 226),
'size':(106, -1),
'items':[],
'text':'Select',
},
{'type':'StaticText',
'name':'PointPlanets',
'position':(339, 229),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Planets',
},
{'type':'ComboBox',
'name':'ComboStars',
'position':(539, 225),
'size':(100, -1),
'items':[],
'text':'Select',
},
{'type':'StaticText',
'name':'PointStars',
'position':(504, 227),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Stars',
},
{'type':'ComboBox',
'name':'ComboDouble',
'position':(689, 225),
'size':(104, -1),
'items':[],
'text':'Select',
},
{'type':'StaticText',
'name':'PointDouble',
'position':(644, 229),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Double',
},
{'type':'ComboBox',
'name':'ComboMessier',
'position':(389, 254),
'size':(106, -1),
'items':[],
'text':'Select',
},
{'type':'StaticText',
'name':'PointMessier',
'position':(339, 256),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Messier',
},
{'type':'Spinner',
'name':'SpinnerNGC',
'position':(539, 253),
'size':(99, -1),
'backgroundColor':(255, 255, 255, 255),
'max':8000,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'PointNGC',
'position':(509, 255),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'NGC',
},
{'type':'Spinner',
'name':'SpinnerIC',
'position':(689, 253),
'size':(104, -1),
'backgroundColor':(255, 255, 255),
'max':5385,
'min':0,
'value':0,
},
{'type':'StaticText',
'name':'PointIC',
'position':(673, 258),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'IC',
},
{'type':'TextField',
'name':'PointRA1',
'position':(362, 281),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointAR1',
'position':(339, 285),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'RA',
},
{'type':'TextField',
'name':'PointRA2',
'position':(393, 281),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointAR2',
'position':(389, 285),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':':',
},
{'type':'TextField',
'name':'PointRA3',
'position':(424, 281),
'size':(24, -1),
'text':'0',
},
{'type':'StaticText',
'name':'PointAR3',
'position':(420, 286),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'.',
},
{'type':'StaticText',
'name':'PointDECtext',
'position':(462, 285),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'DEC',
},
{'type':'TextField',
'name':'PointDEC1',
'position':(490, 281),
'size':(20, -1),
'text':'+',
},
{'type':'TextField',
'name':'PointDEC2',
'position':(513, 281),
'size':(24, -1),
'text':'00',
},
{'type':'StaticText',
'name':'PointDECtext1',
'position':(541, 284),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':':',
},
{'type':'TextField',
'name':'PointDEC3',
'position':(546, 281),
'size':(24, -1),
'text':'00',
},
{'type':'Button',
'name':'PointGOTO',
'position':(578, 280),
'size':(95, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(255, 0, 0, 255),
'label':'GOTO',
},
{'type':'Button',
'name':'PointSendToScript',
'position':(689, 280),
'size':(105, 23),
'backgroundColor':(255, 255, 255, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Send to script',
},
{'type':'Spinner',
'name':'SpinnerExposition',
'position':(370, 327),
'size':(60, -1),
'backgroundColor':(255, 255, 255),
'max':900,
'min':0,
'value':0,
},
{'type':'ComboBox',
'name':'ComboFilters',
'position':(480, 327),
'size':(38, -1),
'items':[],
'text':'X',
},
{'type':'ComboBox',
'name':'ComboBin',
'position':(557, 327),
'size':(45, -1),
'items':[u'1', u'2', u'3'],
'stringSelection':'2',
'text':'X',
},
{'type':'Spinner',
'name':'SpinnerRepeat',
'position':(661, 327),
'size':(60, -1),
'backgroundColor':(255, 255, 255),
'max':500,
'min':0,
'value':0,
},
{'type':'CheckBox',
'name':'CheckBoxGuide',
'position':(779, 328),
'size':(15, -1),
'label':' ',
},
{'type':'CheckBox',
'name':'CheckBoxWeb',
'position':(779, 345),
'size':(13, -1),
'checked':True,
'label':' ',
},
{'type':'CheckBox',
'name':'CheckBoxAutoflat',
'position':(779, 362),
'size':(14, -1),
'label':' ',
},
{'type':'TextField',
'name':'FileName',
'position':(400, 351),
'size':(178, 21),
'editable':False,
'enabled':False,
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'SkyliveNG',
},
{'type':'Spinner',
'name':'Spinner1',
'position':(661, 351),
'size':(59, -1),
'backgroundColor':(255, 255, 255, 255),
'max':100,
'min':0,
'value':0,
},
{'type':'Button',
'name':'PathChoose',
'position':(338, 375),
'size':(50, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Path',
},
{'type':'TextField',
'name':'PathField',
'position':(400, 375),
'size':(320, 23),
'text':'/',
},
{'type':'CheckBox',
'name':'CheckBoxAutodark',
'position':(779, 379),
'size':(13, -1),
'label':' ',
},
{'type':'Button',
'name':'LastPhoto',
'position':(338, 400),
'size':(85, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(30, 144, 255, 255),
'label':'Last photo',
},
{'type':'Button',
'name':'BigLive',
'position':(430, 400),
'size':(110, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(30, 144, 255, 255),
'label':'Live bigger ',
},
{'type':'Button',
'name':'MakePhoto',
'position':(554, 400),
'size':(108, 23),
'backgroundColor':(255, 255, 255, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(232, 19, 19, 255),
'label':'MAKE PHOTO',
},
{'type':'Button',
'name':'PhotoSendToScript',
'position':(689, 400),
'size':(105, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Send to script',
},
{'type':'StaticText',
'name':'PhotoTXTRepeat',
'position':(618, 330),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Repeat',
},
{'type':'StaticText',
'name':'PhotoTXTStartnumber',
'position':(584, 354),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Start number',
},
{'type':'Button',
'name':'PhotoTXTFilename',
'position':(338, 350),
'size':(60, 23),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Filename',
},
{'type':'StaticText',
'name':'PhotoTXTWeb',
'position':(748, 345),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':' Web',
},
{'type':'StaticText',
'name':'PhotoTXTAutodark',
'position':(724, 379),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Autodark',
},
{'type':'StaticText',
'name':'PhotoTXTAutoflat',
'position':(731, 361),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Autoflat',
},
{'type':'StaticText',
'name':'PhotoTXTGuide',
'position':(743, 328),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Guide',
},
{'type':'StaticText',
'name':'PhotoTXTBin',
'position':(533, 330),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Bin',
},
{'type':'StaticText',
'name':'PhotoTXTFilter',
'position':(450, 330),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Filter',
},
{'type':'StaticText',
'name':'PhotoTXTExp',
'position':(340, 330),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Exp.',
},
{'type':'Button',
'name':'ScriptLoad',
'position':(340, 445),
'size':(54, 24),
'foregroundColor':(23, 143, 23, 255),
'label':'Load',
},
{'type':'Button',
'name':'ScriptSave',
'position':(400, 445),
'size':(50, 24),
'foregroundColor':(165, 42, 42, 255),
'label':'Save',
},
{'type':'Button',
'name':'ScriptStart',
'position':(455, 445),
'size':(50, 24),
'foregroundColor':(30, 144, 255, 255),
'label':'Start',
},
{'type':'Button',
'name':'ScriptStop',
'position':(510, 445),
'size':(50, 24),
'label':'Stop',
},
{'type':'Button',
'name':'ScriptContinue',
'position':(565, 445),
'size':(70, 24),
'foregroundColor':(30, 144, 255, 255),
'label':'Continue',
},
{'type':'Button',
'name':'ScriptClear',
'position':(640, 445),
'size':(50, 24),
'foregroundColor':(127, 127, 127, 255),
'label':'Clear',
},
{'type':'Button',
'name':'ScriptReset',
'position':(695, 445),
'size':(50, 24),
'foregroundColor':(127, 127, 127, 255),
'label':'Reset',
},
{'type':'List',
'name':'ScriptArea',
'position':(336, 470),
'size':(455, 56),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'items':[],
},
{'type':'TextField',
'name':'ScriptStatus',
'position':(336, 528),
'size':(455, 17),
'editable':False,
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Waiting for commands...',
},
{'type':'StaticText',
'name':'StatusRain',
'position':(653, 184),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Weather:',
},
{'type':'StaticText',
'name':'StatusDome',
'position':(474, 184),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Observatory Dome:',
},
{'type':'StaticText',
'name':'StatusObject',
'position':(473, 161),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Current object:',
},
{'type':'StaticText',
'name':'FWHM',
'position':(673, 125),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'FWHM:',
},
{'type':'StaticText',
'name':'TelescopeCCDTemp',
'position':(649, 76),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'CCD Temp:',
},
{'type':'StaticText',
'name':'MoveDEC',
'position':(679, 58),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'DEC:',
},
{'type':'StaticText',
'name':'MoveRA',
'position':(685, 39),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'RA:',
},
{'type':'StaticText',
'name':'TelescopeFilters',
'position':(446, 111),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Filters available:',
},
{'type':'StaticText',
'name':'TelescopeGPS',
'position':(607, 95),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Telescope Pos: Lat:',
},
{'type':'StaticText',
'name':'TelescopeGPS2',
'position':(679, 112),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Lon:',
},
{'type':'StaticText',
'name':'TelescopeGPSPos1',
'position':(714, 94),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeGPSPos2',
'position':(714, 112),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCD',
'position':(446, 94),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'CCD:',
},
{'type':'StaticText',
'name':'TelescopeFOW',
'position':(446, 75),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Field of view:',
},
{'type':'StaticText',
'name':'TelescopeFocal',
'position':(446, 58),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'FOCAL:',
},
{'type':'StaticText',
'name':'TelescopeMODEL',
'position':(446, 40),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'MODEL:',
},
{'type':'StaticText',
'name':'TelescopeModelText',
'position':(492, 38),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'GuideYerr',
'position':(385, 183),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Yerr: ',
},
{'type':'StaticText',
'name':'TextXerr',
'position':(385, 162),
'backgroundColor':(192, 192, 192, 255),
'font':{'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Xerr: ',
},
{'type':'StaticText',
'name':'RainSensorText',
'position':(715, 184),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'ObservatoryDomeText',
'position':(586, 184),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'CurrentObjectText',
'position':(564, 161),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'YerrText',
'position':(421, 183),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(22, 56, 150, 255),
'text':'0',
},
{'type':'StaticText',
'name':'XerrText',
'position':(421, 162),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(22, 56, 150, 255),
'text':'0',
},
{'type':'StaticText',
'name':'FWHMText',
'position':(714, 125),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCDTempText',
'position':(714, 76),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeDECText',
'position':(714, 57),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeRAText',
'position':(714, 39),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFiltersText',
'position':(526, 110),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeCCDText',
'position':(477, 94),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFOVText',
'position':(516, 74),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'StaticText',
'name':'TelescopeFocalText',
'position':(492, 57),
'backgroundColor':(192, 192, 192, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'foregroundColor':(0, 0, 255, 255),
'text':'-',
},
{'type':'Image',
'name':'GuideImage',
'position':(339, 161),
'size':(40, 40),
'file':'gui/img/Guide.jpg',
},
{'type':'Image',
'name':'Live640',
'position':(2, 25),
'size':(320, 240),
'file':'gui/img/Live.jpg',
},
{'type':'BitmapCanvas',
'name':'StatusText',
'position':(2, 2),
'size':(801, 21),
'backgroundColor':(255, 255, 255, 255),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
},
{'type':'BitmapCanvas',
'name':'SponsorCanvas',
'position':(330, 549),
'size':(333, 23),
'backgroundColor':(255, 255, 255, 255),
'font':{'style': 'italic', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
},
{'type':'Button',
'name':'Sponsor',
'position':(666, 551),
'size':(132, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'>> Click HERE <<',
},
] # end components
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from skylive import config, conn, protocol
from skylive.utils import genutils as utils
import gui, imager, chatpriv, scriptsgui, liveduplicate, userinfo, booking
import downprog, fitsopener, info, focus
from skylive.lang import language
from settings import settings
from Pycard import model, dialog, timer, graphic
import wx, time, sys, os, platform
from cStringIO import StringIO
import Image, ImageOps, ImageDraw, ImageFile
import askstream, stream
import webbrowser, thread
from skylive.fits import fitsimage, levels
from twisted.internet import reactor
from skylive import chatparser as parser
class mainPanel(model.Background):
photo = {'bin': False,
'filter': False,
'exp': False,
'guide': "0",
'web': "1",
'aflat': "0",
'adark': "0",
'repeat': "0",
'startn': "0"
}
chathtml = []
photorun = False
no_check_messier = False
oldstatustext = ''
inuserlist = False
userlistbusy = False
vercheckman = False
closingclient = False
username = 'unknown'
focusdialog = False
Streaming = False
askStreaming = False
StreamUri="http://skylive3.astronomix.org:8000/skylive.ogg"
streamingIndex = 0
latest = ''
chatfontsize="1"
def __init__(self, parent, rsrc):
self.TwistedLoop = parent.TwistedLoop
self.callInTwisted = parent.callInTwisted
self.config = parent.config
model.Background.__init__(self, parent, rsrc)
def on_initialize(self, event):
self.username = config.getUsername()
#self.startSplash()
sysType = utils.platform()
if sysType == "Microsoft":
#to fix some sVista
self.systemType = "Windows"
else:
self.systemType = sysType
if self.systemType == 'Linux':
if platform.system() != 'Linux':
self.title = self.title.replace("Linux", platform.system())
#config.initialize()
self.privchats={}
self.teleOn = False
self.downPop = {}
self.scriptguiStarted = False
self.livedup = False
self.initialized=False
self.useExtProgram='False'
self.useINDIProgram='False'
self.StatusTextFormat("Inizializzazione in corso... / Initalizing...")
self.ItemText = language.getItemText
self.lang = config.get_usrLang()
self.gui = 'skylive'
self.setGui()
self.SponsorCanvasFormat(self.getText('textHelpSkylive'))
self.domeisopen=False
self.resetARTargetReq = False
self.lastPath = self.usrDefSavePath = config.get_usrDefaultPath()
self.charSizes = config.get_usrCharSizes()
self.useExtProgram = config.get_extProgram()
self.useINDIProgram = config.get_extINDIProgram()
self.enableStream, self.askStream=config.get_streamingPref()
self.streamingIndex=config.get_streamingIndex()
self.defaultPointerColor = config.get_usrPointerColor()
self.forcedLowRes = config.get_lowResPref()
print 'Forced lowRes : ',self.forcedLowRes
self.setCharSizes()
self.resetPhotos()
self.custom_fn=False
self.starsSetted=False
self.doubleSetted=False
self.TscopeComboSetted=False
self.adminPrivilege = False
self.telescopesel=1
self.srvproto = protocol.ServerComm(self)
self.srvproto.AuthString(str(config.getUsername()), str(config.getPassword()))
self.serveraddr = "skylive.astronomix.org"
self.setGUImenus()
self.TwistedLoop.imgDownloader('start')
self.setStatus()
self.scriptReset()
self.scriptSep = "*"
self.components.PathField.text = self.usrDefSavePath
self.on_SelectTarget()
self.StatusTextFormat("Connessione al server in corso... / Connecting to server...")
self.connLoose = False
self.connect(self.serveraddr)
self.resetCiceroneMode()
self.canSelect = False
self.downloadedBits = []
self.config = config
self.initialized = True
if self.systemType == "Windows" and self.useExtProgram == 'True':
self.startFake()
if self.useINDIProgram == 'True':
self.startINDI()
#self.stopSplash()
self.eventTimer = timer.Timer(self.components.StatusText, -1)
self.eventTimer.Start(1000)
self.visible=True
self.TwistedLoop.checkUpgrade()
# Temporanei!
self.MenuBar.setEnabled('menuBooking', False)
self.MenuBar.setEnabled('menuAccount', False)
def scriptReset(self):
self.scripts=[]
self.scripts_count=0
def on_setStreamIdx(self, idx):
config.set_streamingIndex(idx)
def on_setMyUsername(self, username):
self.username = username
def on_menuCheckVersion_select(self, event):
try:
self.TwistedLoop.checkUpgrade(False)
self.vercheckman = True
except:
pass
def upgradeDownloadFailed(self):
self.alertDialog(self.getText("upgradeFailed"))
def on_versionCheck(self, mver, nver, upuri, nvermd5):
if int(mver) < int(nver):
import gui
res = gui.Upgrade()
if res == 'UPGRADE':
if utils.is_frozen():
if platform.system() in ['Windows', 'Microsoft']:
self.TwistedLoop.downloadUpgrade(upuri, nvermd5)
elif platform.system() == 'Linux':
self.TwistedLoop.downloadUpgrade(upuri, nvermd5)
elif platform.system() == 'Darwin':
self.TwistedLoop.downloadUpgrade(upuri, nvermd5)
else:
self.alertDialog(self.getText("clientVerSources"))
else:
self.alertDialog(self.getText("clientVerSources"))
#self.TwistedLoop.downloadUpgrade(upuri, nvermd5)
elif res == 'LATERUPGRADE':
pass
elif res == 'NOUPGRADE':
if not self.vercheckman:
self.TwistedLoop.stopCheckUpgrade()
self.vercheckman = False
else:
if self.vercheckman:
self.vercheckman = False
self.alertDialog(self.getText("clientUpdated"))
def on_StatusText_timer(self, event):
if self.photorun:
try:
rem = int(self.photorun['data'][4])
nick = self.photorun['data'][0]
filter = self.photorun['data'][1]
bin = self.photorun['data'][2]
exp = int(self.photorun['data'][3])
p = self.getText('statusPhoto')
f = self.getText('statusFilter')
e = self.getText('statusRemain')
u = self.getText('statusUpload')
if self.photorun['status'] == 'up':
status = u+" *"+str(nick)+"* tot exp: "+str(exp)+" sec., "+f+": "+str(filter)
status += ", bin: "+str(bin)+", "+e+": "+str(rem)+" sec."
self.StatusTextFormat(status, photo=True)
elif self.photorun['status'] == 'run':
status = p+" *"+str(nick)+"* tot exp: "+str(exp)+" sec., "+f+": "+str(filter)
status += ", bin: "+str(bin)+", "+e+": "+str(rem)+" sec."
self.StatusTextFormat(status, photo=True)
if int(rem) > 0:
self.photorun['data'][4] = int(rem)-1
except:
pass
def on_setExposureUpload(self, data):
#print 'on_setExposureUpload'
self.photorun = {
'status': 'up',
'data': data
}
def on_setExposureRunning(self, data):
#print 'on_setExposureRunning'
self.photorun = {
'status': 'run',
'data': data
}
def on_setExposureNone(self, event=None):
#print 'on_setExposureNone'
self.photorun = False
ra = self.components.TelescopeRAText.text
dec = self.components.TelescopeDECText.text
status = self.oldstatustext
self.StatusTextFormat(status, ra, dec)
def on_idle(self, event):
# Save CPU load
if self.systemType == "Windows":
time.sleep(.03)
def on_menuFileExit_select(self, event):
self.on_close(event)
def on_close(self, event):
try:
self.eventTimer.Stop()
except:
pass
try:
event.skip()
except:
pass
self.StatusTextFormat("Chiusura in corso... / Closing...")
if not self.connLoose and not self.closingclient:
self.closingclient = True
try:
self.TwistedLoop.imgDownloader('stop')
self.TwistedLoop.serverDisconnect()
except:
pass
# XXX Shuld exit also from the twisted loop, but, in effect,
# sometimes this won't happen. As we are a GUI only app,
# temporarely the work around for this issue is to simply call
# sys.exit() here. Sometime in a future release we will fix this in a
# better way.
#if self.closingclient:
# import sys
# sys.exit(0)
if self.closingclient:
self.TwistedLoop.forcedExit()
reactor.pycard_is_stopping = True
# XXX Sometime windows won't close cleany. Fuck.
if platform.system() in ['Windows', 'Microsoft']:
sys.exit(0)
def on_StopClient(self, event=True):
self.connLoose = False
self.on_close(event)
def connect(self, ip, timeout=0):
#XXX bisogna specificare il tipo di connessione!
#print 'CONNECT'
self.TwistedLoop.serverConnect(ip, timeout)
def startFake(self):
print 'avvio fakedriver'
self.TwistedLoop.startFakeDriver()
def stopFake(self):
print 'fermo fakedriver'
self.TwistedLoop.stopFakeDriver()
def startINDI(self):
self.TwistedLoop.startINDIDriver()
def stopINDI(self):
self.TwistedLoop.stopINDIDriver()
def on_LoseConnection(self, reconnect=False):
# XXX gestire una chiamata qui quando ci disconnettiamo!
self.connLoose = True
self.ciceroneMode = False
try:
self.StatusTextFormat("Disconnesso dal server in corso.../Disconnected from the server...")
except:
pass
if reconnect:
try:
self.StatusTextFormat("Riconnessione al server in corso.../Reconnecting to server...")
except:
pass
self.connect(self.serveraddr, 2)
else:
try:
self.close()
except:
pass
def on_callback(self, cmd):
for key in cmd:
f=getattr(self, 'on_'+key, None)
if f and callable(f):
f(cmd[key])
def notImplemented(self):
self.alertDialog("Not yet implemented, sorry!")
def alertDialog(self, msg):
dialog.alertDialog(self, msg)
def setStatus(self, tscope=1):
self.TwistedLoop.changeTelescope(tscope)
def setGUImenus(self):
self.setPlanetsList()
self.setMessierList()
self.setNGCList()
self.setICList()
self.resetARTarget()
def on_MakePhoto_mouseClick(self, event):
if self.photo['bin'] and self.photo['filter'] and self.photo['exp']:
# XXX popups etc
# XXX gestire il repeat
# XXX gestire lo stop photo ( cambiare il text sul tasto? )
photostring = self.srvproto.makePhoto(self.photo['exp'], self.photo['filter'],
self.photo['guide'], self.photo['bin'],
self.photo['aflat'], self.photo['adark'],
self.photo['web'])
if photostring:
#self.callInTwisted('sendNetworkData', photostring)
self.TwistedLoop.sendNetworkData(photostring)
if self.components.CheckBoxWeb.checked:
self.photoKeyClick = True
else:
# XXX mettere un avviso
pass
def resetPhotos(self):
self.photo = {'bin': False,
'filter': False,
'exp': False,
'guide': "0",
'web': "1",
'aflat': "0",
'adark': "0",
'repeat': "0",
'startn': "0"
}
self.components.SpinnerExposition.value=0
self.components.ComboBin.text="X"
self.components.ComboFilters.text="X"
self.components.CheckBoxAutoflat.checked=False
self.components.CheckBoxWeb.checked=True
self.components.CheckBoxGuide.checked=False
self.components.CheckBoxAutodark.checked=False
self.components.SpinnerRepeat.value=0
self.photoKeyClick = False
self.photoInUpload = False
def on_SpinnerExposition_textUpdate(self, event):
if self.initialized:
exp = self.components.SpinnerExposition.value
try:
if int(exp) in range(0, 901):
exptime = exp
#print "EXP: "+str(exp)
elif int(exp) > 900:
exptime = 900
self.components.SpinnerExposition.value = 900
else:
exptime = 0
except:
exptime = 0
self.components.SpinnerExposition.value = 0
self.photo['exp'] = str(exptime)
self.createFileName()
def on_SpinnerExposition_loseFocus(self, event):
if not self.components.SpinnerExposition.value:
self.components.SpinnerExposition.value = 0
self.photo['exp'] = False
self.createFileName()
event.skip()
def on_ComboBin_textUpdate(self, event):
if self.initialized:
bin = self.components.ComboBin.text
bins = "123"
if bin in bins and len(bin) == 1:
binsel = bin
self.components.ComboBin.text = str(bin)
else:
binsel = "X"
self.components.ComboBin.text = ""
self.photo['bin'] = str(binsel)
self.createFileName()
def on_ComboBin_loseFocus(self, event):
if not self.components.ComboBin.text:
self.components.ComboBin.text = 'X'
self.photo['bin'] = False
self.createFileName()
event.skip()
def on_ComboFilters_textUpdate(self, event):
filt = self.components.ComboFilters.text
filters = str(self.components.TelescopeFiltersText.text)
if filt in filters:# and len(filt) == 1:
selfilt = filt
else:
selfilt = "X"
self.components.ComboFilters.text = "X"
self.photo['filter'] = selfilt
self.createFileName()
def on_ComboFilters_loseFocus(self, event):
if not self.components.ComboFilters.text:
self.components.ComboFilters.text = "X"
self.photo['filter'] = False
self.createFileName()
event.skip()
def on_SpinnerRepeat_textUpdate(self, event):
if self.initialized:
rep = self.components.SpinnerRepeat.value
try:
if int(rep) > 0 and int(rep) < 501:
reptime = rep
elif int(rep) > 501:
reptime = 500
self.components.SpinnerRepeat.value = 500
else:
reptime = 0
except:
reptime = 0
self.components.SpinnerRepeat.value=0
self.photo['repeat'] = str(reptime)
def on_SpinnerRepeat_loseFocus(self, event):
if not self.components.SpinnerRepeat.value:
self.components.SpinnerRepeat.value = 0
self.photo['repeat'] = '0'
event.skip()
def on_Spinner1_textUpdate(self, event):
self.photo['startn'] = self.components.Spinner1.value
def on_CheckBoxAutoflat_mouseClick(self, event):
if self.components.CheckBoxAutoflat.checked:
self.photo['aflat'] = "1"
else:
self.photo['aflat'] = "0"
def on_CheckBoxWeb_mouseClick(self, event):
if self.components.CheckBoxWeb.checked:
self.photo['web'] = "1"
else:
self.photo['web'] = "0"
def on_CheckBoxGuide_mouseClick(self, event):
if self.components.CheckBoxGuide.checked:
self.photo['guide'] = "1"
else:
self.photo['guide'] = "0"
def on_CheckBoxAutodark_mouseClick(self, event):
if self.components.CheckBoxAutodark.checked:
self.photo['adark'] = "1"
else:
self.photo['adark'] = "0"
def setStarsList(self):
x = self.starlist.keys()
x.sort()
for item in x:
if len(item) > 0:
self.components.ComboStars.append(item)
self.components.ComboStars.text="Select"
def setDoublesList(self):
x = self.doublelist.keys()
x.sort()
for item in x:
if len(item) > 0:
self.components.ComboDouble.append(item)
self.components.ComboDouble.text="Select"
def setPlanetsList(self):
for item in ["Mercury", "Venus", "Moon", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune", "Pluto" ]:
self.components.ComboPlanets.append(item)
self.components.ComboPlanets.text="Select"
def setMessierList(self):
for m in xrange(1, 111):
self.components.ComboMessier.append("M%d" % m)
self.components.ComboMessier.text="Select"
def setNGCList(self):
self.components.SpinnerNGC.value=0
def setICList(self):
self.components.SpinnerIC.value=0
def on_ComboPlanets_textUpdate(self, event):
#This is a bad hack to prevent text writed into combo field
CPlanets = self.components.ComboPlanets.text.replace('Select', '')
if not CPlanets in self.components.ComboPlanets.items:
self.components.ComboPlanets.text = "Select"
self.on_SelectTarget('Planets', False)
else:
self.on_SelectTarget('Planets', CPlanets)
self.components.ComboPlanets.text = CPlanets
def on_ComboMessier_textUpdate(self, event):
if self.initialized:
mt = str(self.components.ComboMessier.text)
if mt != "Select" and not self.no_check_messier:
m = mt.replace('M', '').replace('m', '')
try:
if int(m) > 0 and int(m) < 111:
messier = "M"+str(m)
elif int(m) > 111:
messier = "M110"
self.no_check_messier = True
self.components.ComboMessier.text = str(messier)
else:
self.components.ComboMessier.text = ''
messier = 0
except:
self.components.ComboMessier.text = ''
messier = 0
if messier != 0:
self.on_SelectTarget('Messier', str(messier))
else:
self.no_check_messier = False
def on_ComboMessier_loseFocus(self, event):
if not self.components.ComboMessier.text:
self.components.ComboMessier.text = 'Select'
else:
if 'M' not in self.components.ComboMessier.text:
text = self.components.ComboMessier.text
if text != 'Select':
newtext = 'M'+text
self.components.ComboMessier.text = newtext
else:
self.components.ComboMessier.text = 'Select'
event.skip()
def on_ComboStars_textUpdate(self, event):
CStars = self.components.ComboStars.text.replace('Select', '')
if not CStars in self.components.ComboStars.items:
self.components.ComboStars.text = "Select"
self.on_SelectTarget('Stars', False)
else:
self.on_SelectTarget('Stars', CStars)
self.components.ComboStars.text = CStars
def on_SpinnerNGC_loseFocus(self, event):
ngc = str(self.components.SpinnerNGC.value)
if ngc != '0':
self.on_SelectTarget('NGC', ngc)
else:
pass
event.skip()
def on_ComboDouble_textUpdate(self, event):
CDStars = self.components.ComboDouble.text.replace('Select', '')
if not CDStars in self.components.ComboDouble.items:
self.components.ComboDouble.text = "Select"
self.on_SelectTarget('Double', False)
else:
self.on_SelectTarget('Double', CDStars)
self.components.ComboDouble.text = CDStars
def on_SpinnerIC_loseFocus(self, event):
ic = str(self.components.SpinnerIC.value)
if ic != '0':
self.on_SelectTarget('IC', ic)
else:
pass
event.skip()
def on_SelectTarget(self, type=None, which=None):
self.selectedTarget=[None, None]
done=False
for t in ['Planets', 'Messier', 'Stars', 'Double']:
if t != type:
f=getattr(self.components, 'Combo'+t, None)
if f:
f.text = 'Select'
else:
if type:
self.selectedTarget=[type, which]
done=True
if not done:
if type and type == 'NGC' and which != '0':
self.selectedTarget=['NGC', which]
self.resetARTarget()
self.setICList()
elif type and type == 'IC' and which != '0':
self.selectedTarget=['IC', which]
self.resetARTarget()
self.setNGCList()
elif type and type == 'AR':
self.selectedTarget=['AR', which]
self.setICList()
self.setNGCList()
else:
self.setICList()
self.resetARTarget()
self.setNGCList()
else:
self.resetARTarget()
self.setNGCList()
self.setICList()
def resetARTarget(self):
self.resetARTargetReq = True
self.components.PointRA1.text='00'
self.components.PointRA2.text='00'
self.components.PointRA3.text='0'
self.components.PointDEC1.text='+'
self.components.PointDEC2.text='00'
self.components.PointDEC3.text='00'
self.resetARTargetReq = False
def on_PointRA1_keyPress(self, event):
key = event.GetKeyCode()
chars = [wx.WXK_TAB,wx.WXK_ESCAPE,wx.WXK_DELETE,wx.WXK_CANCEL,wx.WXK_BACK,wx.WXK_RETURN]
if (((key >= 48) and (key <= 57)) or (key in chars)):
event.skip()
def on_PointRA1_loseFocus(self, event):
if not self.resetARTargetReq:
maxlen = 2
text = self.components.PointRA1.text
if len(text) > maxlen:
text = text[:maxlen]
if text != "" and int(text) > 23:
text = "23"
text = text.zfill(maxlen)
self.resetARTargetReq = True
self.components.PointRA1.text=str(text)
self.resetARTargetReq = False
self.on_setARDECTarget()
def on_PointRA2_keyPress(self, event):
key = event.GetKeyCode()
chars = [wx.WXK_TAB,wx.WXK_ESCAPE,wx.WXK_DELETE,wx.WXK_CANCEL,wx.WXK_BACK,wx.WXK_RETURN]
if (((key >= 48) and (key <= 57)) or (key in chars)):
event.skip()
def on_PointRA2_loseFocus(self, event):
if not self.resetARTargetReq:
maxlen = 2
text = self.components.PointRA2.text
if len(text) > maxlen:
text = text[:maxlen]
if text != "" and int(text) > 59:
text = "59"
text = text.zfill(maxlen)
self.resetARTargetReq = True
self.components.PointRA2.text=str(text)
self.resetARTargetReq = False
self.on_setARDECTarget()
def on_PointRA3_keyPress(self, event):
key = event.GetKeyCode()
chars = [wx.WXK_TAB,wx.WXK_ESCAPE,wx.WXK_DELETE,wx.WXK_CANCEL,wx.WXK_BACK,wx.WXK_RETURN]
if (((key >= 48) and (key <= 57)) or (key in chars)):
event.skip()
def on_PointRA3_loseFocus(self, event):
if not self.resetARTargetReq:
maxlen = 1
text = self.components.PointRA3.text
if len(text) > maxlen:
text = text[:maxlen]
if text != "" and int(text) > 9:
text = "9"
text = text.zfill(maxlen)
self.resetARTargetReq = True
self.components.PointRA3.text=str(text)
self.resetARTargetReq = False
self.on_setARDECTarget()
def on_PointDEC1_keyPress(self, event):
key = event.GetKeyCode()
chars = [wx.WXK_TAB,wx.WXK_ESCAPE,wx.WXK_DELETE,wx.WXK_CANCEL,wx.WXK_BACK,wx.WXK_RETURN,43,45]
if key in chars:
event.skip()
def on_PointDEC1_loseFocus(self, event):
if not self.resetARTargetReq:
maxlen = 1
text = self.components.PointDEC1.text
if len(text) > maxlen:
text = text[:maxlen]
if text == "":
text = "+"
self.resetARTargetReq = True
self.components.PointDEC1.text=str(text)
self.resetARTargetReq = False
self.on_setARDECTarget()
def on_PointDEC2_keyPress(self, event):
key = event.GetKeyCode()
chars = [wx.WXK_TAB,wx.WXK_ESCAPE,wx.WXK_DELETE,wx.WXK_CANCEL,wx.WXK_BACK,wx.WXK_RETURN]
if (((key >= 48) and (key <= 57)) or (key in chars)):
event.skip()
def on_PointDEC2_loseFocus(self, event):
if not self.resetARTargetReq:
maxlen = 2
text = self.components.PointDEC2.text
if len(text) > maxlen:
text = text[:maxlen]
if text != "" and int(text) > 89:
text = "89"
text = text.zfill(maxlen)
self.resetARTargetReq = True
self.components.PointDEC2.text=str(text)
self.resetARTargetReq = False
self.on_setARDECTarget()
def on_PointDEC3_keyPress(self, event):
key = event.GetKeyCode()
chars = [wx.WXK_TAB,wx.WXK_ESCAPE,wx.WXK_DELETE,wx.WXK_CANCEL,wx.WXK_BACK,wx.WXK_RETURN]
if (((key >= 48) and (key <= 57)) or (key in chars)):
event.skip()
def on_PointDEC3_loseFocus(self, event):
if not self.resetARTargetReq:
maxlen = 2
text = self.components.PointDEC3.text
if len(text) > maxlen:
text = text[:maxlen]
if text != "" and int(text) > 99:
text = "99"
text = text.zfill(maxlen)
self.resetARTargetReq = True
self.components.PointDEC3.text=str(text)
self.resetARTargetReq = False
self.on_setARDECTarget()
def on_setARDECTarget(self):
ra1=self.components.PointRA1.text
ra2=self.components.PointRA2.text
ra3=self.components.PointRA3.text
dec1=self.components.PointDEC1.text
dec2=self.components.PointDEC2.text
dec3=self.components.PointDEC3.text
if ra1!="00" or ra2!="00" or ra3!="0" or dec2!="00" or dec3!="00":
artarget=ra1+":"+ra2+"."+ra3+dec1+dec2+":"+dec3
self.on_SelectTarget('AR', artarget)
#print artarget
def on_PointGOTO_mouseClick(self, event):
try:
pointstring = self.srvproto.moveToTarget(self.selectedTarget)
except:
pointstring = False
if pointstring:
self.TwistedLoop.sendNetworkData(pointstring)
def on_LastPhoto_mouseClick(self, event):
self.TwistedLoop.getLastPhoto()
def on_LastPhotoDone(self, photo):
nolog = wx.LogNull()
sysType = self.systemType
if not os.path.exists(os.path.normpath("./gui/imager."+sysType+".rsrc.py")):
sysType = "Linux"
self.LastPhotoImager = model.childWindow(self, imager.SkyliveImager, "./gui/imager."+sysType+".rsrc.py")
lfsize= self.LastPhotoImager.size
self.LastPhotoImager.SetMaxSize(lfsize)
self.LastPhotoImager.SetMinSize((lfsize))
self.LastPhotoImager._parent = self
self.LastPhotoImager.parent = self
posX = self.position[0]+(self.size[0]/2)-(self.LastPhotoImager.size[0]/2)
posY = self.position[1]+(self.size[1]/2)-(self.LastPhotoImager.size[1]/2)
self.LastPhotoImager.position = (posX, posY)
self.LastPhotoImager.visible = True
self.LastPhotoImager.title = self.getText('lastphototitle')+str(self.telescopesel)
newBitmap = graphic.Bitmap()
newBitmap.setImageBits(wx.ImageFromStream(StringIO(photo)))
self.LastPhotoImager.components.ImageShow.bitmap = newBitmap
self.LastPhotoImager.telescope=self.telescopesel
self.LastPhotoImager.components.ButtonClose.visible = True
self.LastPhotoImager.components.ButtonDownload.visible = True
self.LastPhotoImager.fromEvent = "lastphoto"
self.LastPhotoImager.visible = True
del nolog
def on_FitsDownloaded(self, fitpath):
sysType = self.systemType
if not os.path.exists(os.path.normpath("./gui/imager."+sysType+".rsrc.py")):
sysType = "Linux"
self.FitsImager = model.childWindow(self, imager.SkyliveImager, "./gui/imager."+sysType+".rsrc.py")
self.FitsImager._parent = self
posX = self.position[0]+(self.size[0]/2)-(self.FitsImager.size[0]/2)
posY = self.position[1]+(self.size[1]/2)-(self.FitsImager.size[1]/2)
self.FitsImager.position = (posX, posY)
self.FitsImager.title = self.getText('fitviewertitle')
# if we remove the fits file, the viewer can't save it how is
# implemented now
fitsfile = fitsimage.FitsImage(fitpath, False, self.forcedLowRes)
scidata = fitsfile.image
self.autoMax = fitsfile.autoMaxLevel
self.autoMin = fitsfile.autoMinLevel
self.fitsHeader = fitsfile.headers.ascardlist()
self.FitsImager.pilImage = fitsfile.pilImage
image = wx.EmptyImage(fitsfile.xsizeBit, fitsfile.ysizeBit)
self.xsizeBit = fitsfile.xsizeBit
self.ysizeBit = fitsfile.ysizeBit
image.SetData(fitsfile.pilImage.convert("RGB").tostring())
self.imageBitmap = graphic.Bitmap()
self.imageBitmap.setImageBits(image)
self.FitsImager.components.ImageShow.bitmap = self.imageBitmap
self.FitsImager.size = (fitsfile.xsizeBit+20, fitsfile.ysizeBit+100)
if fitsfile.pilResized:
self.FitsImager.title = self.getText('fitimagertitle1')+str(fitsfile.percresize)+self.getText('fitimagertitle2')
oxc, oyc = self.FitsImager.components.ButtonClose.position
oxs, oys = self.FitsImager.components.ButtonSave.position
oxp, oyp = self.FitsImager.components.ButtonCompare.position
oxz, oyz = self.FitsImager.components.ButtonSaveAs.position
self.FitsImager.components.ButtonClose.position = (oxc, oyc-240+int(fitsfile.ysizeBit))
self.FitsImager.components.ButtonSave.position = (oxs, oys-240+int(fitsfile.ysizeBit))
self.FitsImager.components.ButtonCompare.position = (oxp, oyp-240+int(fitsfile.ysizeBit))
self.FitsImager.components.ButtonSaveAs.position = (oxz, oyz-240+int(fitsfile.ysizeBit))
self.FitsImager.components.ButtonSaveAs.visible = True
self.FitsImager.components.ButtonClose.visible = True
self.FitsImager.components.ButtonSave.visible = True
if fitsfile.canCompare:
self.FitsImager.components.ButtonCompare.visible = True
self.FitsImager.imageData = [fitsfile.ra, fitsfile.dec, fitsfile.xfield, fitsfile.yfield]
self.FitsImager.fromEvent = "photodown"
try:
# this catch an exception in wxPython 2.6. Uhmm but it seem to work.
self.FitsImager.menuBar.setEnabled('menuPhoto', True)
except:
pass
self.FitsImager.fitfile = fitpath
self.FitsImager.origImage = [fitsfile.pilOrI, fitsfile.xsizeBit, fitsfile.ysizeBit,
fitsfile.min , fitsfile.max, fitsfile.med,
fitsfile.pilRaw, fitsfile.pilResized]
self.FitsImager.visible = True
self.FitsImager.refresh()
self.FitsImager.on_adjust_command()
def on_BigLive_mouseClick(self, event):
self.on_LiveDuplicate(event)
def on_CCDTemp(self, temp):
self.components.TelescopeCCDTempText.text=str(temp)
def on_setLiveImage(self, image):
nolog = wx.LogNull()
try:
#if True:
if self.addCross:
self.drawCross(image, self.ciceronePosx, self.ciceronePosy)
else:
newBitmap = graphic.Bitmap()
wximage = wx.ImageFromStream(StringIO(image))
w, h = wximage.GetSize()
if(int(w) != 320) or (int(h) != 240):
wximage.Rescale(320, 240)
newBitmap.setImageBits(wximage)
self.components.Live640.bitmap = newBitmap
#self.components.Live640.SetBitmap(wx.BitmapFromImage(wximage))
self.liveBitmap = newBitmap
if self.ciceroneMode and self.resendCrossC:
self.resendCross()
if self.livedup:
self.livedup.setLiveImage(self.components.Live640.bitmap)
except:
pass
del nolog
def on_setGuideImage(self, image):
nolog = wx.LogNull()
try:
newBitmap = graphic.Bitmap()
newBitmap.setImageBits(wx.ImageFromStream(StringIO(image)))
self.components.GuideImage.bitmap = newBitmap
except:
pass
del nolog
def on_TScopeCombo_select(self, event):
telscopesel = int(event.selection)+1
event.skip()
self.TelescopeChange(telscopesel)
def TelescopeChange(self, telscopesel):
self.photorun = False
self.ciceroneMode = False
self.TwistedLoop.sendNetworkData(self.srvproto.changeTelescope(str(telscopesel)))
self.setStatus(telscopesel)
self.telescopesel = telscopesel
# Reset the pointing menus
self.on_SelectTarget()
# reset the Photo configs
self.resetPhotos()
def changeFilters(self, filters):
self.components.ComboFilters.items = []
for filter in filters:
self.components.ComboFilters.append(filter)
self.components.ComboFilters.text = "X"
def StatusTextFormat(self, text="", ra="-", dec="-", photo=False):
canvas = self.components.StatusText
canvas.foregroundColor='white'
canvas.backgroundColor='blue'
canvas.clear()
canvas.fillColor='BLACK'
canvas.drawText("Status: "+text, (5,1))
if not photo:
self.oldstatustext = text
self.components.TelescopeRAText.text=ra
self.components.TelescopeDECText.text=dec
if self.systemType == "Windows":
self.writeARDEC(ra, dec)
self.writeARDECIndi(ra, dec)
def SponsorCanvasFormat(self, text=""):
c = self.components.SponsorCanvas
c.foregroundColor='white'
c.backgroundColor='blue'
c.clear()
c.fillColor='BLACK'
c.drawText(text, (5,1))
def on_setError(self, err):
Xerr=err[0]
Yerr=err[1]
self.components.XerrText.text=Xerr
self.components.YerrText.text=Yerr
def on_updateUserList(self, userlist):
self.components.UserlistArea.Clear()
self.components.UserlistArea.insertItems(userlist[:-1], 0)
last = int(self.components.UserlistArea.getCount())
#self.components.UserlistArea.delete(last-1)
def on_UserlistArea_mouseContextUp(self, event):
sel = self.components.UserlistArea.GetSelections()
if len(sel) > 0:
toadmin = False
touser = self.components.UserlistArea.getString(sel[0])
self.chat_message_tocomp = touser
if touser[:1] == '@' or touser[:1] == '>' or touser[:1] == "!":
if touser[:1] == "!":
toadmin = True
touser = touser[1:]
self.chat_message_to = touser
if config.getUsername() != touser:
relX, relY = event.GetPosition()
fX, fY = self.components.UserlistArea.position
self.popupID1 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_PrivMesgClick, id=self.popupID1)
menu = wx.Menu()
menu.Append(self.popupID1, self.getText('privMenu'))
if self.adminPrivilege and not toadmin:
self.popupID2 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_KillUserClick, id=self.popupID2)
menu.Append(self.popupID2, 'Kill')
self.popupID3 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_MuteUserClick, id=self.popupID3)
menu.Append(self.popupID3, 'Mute')
self.popupID4 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_BanUserClick, id=self.popupID4)
menu.Append(self.popupID4, 'Ban')
self.popupID5 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_StopUserClick, id=self.popupID5)
menu.Append(self.popupID5, 'Stop')
self.PopupMenu(menu, (relX+fX, relY+fY))
menu.Destroy
def on_KillUserClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.KillUser(self.chat_message_to))
def on_MuteUserClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.MuteUser(self.chat_message_to))
def on_BanUserClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.BanUser(self.chat_message_to))
def on_StopUserClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.StopUser(self.chat_message_to))
def on_PrivMesgClick(self, event):
if not self.chat_message_to in self.privchats:
self.privchats[self.chat_message_to] = model.childWindow(self, chatpriv.ChatPrivate, "./gui/chatpriv.rsrc.py")
self.privchats[self.chat_message_to].touser = self.chat_message_to
self.privchats[self.chat_message_to].tousercomp = self.chat_message_tocomp
self.privchats[self.chat_message_to].title = self.getText('privTitle')+self.chat_message_to
self.privchats[self.chat_message_to]._parent = self
self.privchats[self.chat_message_to].components.Send.label = self.getText('privSendButton')
posX = self.position[0]+(self.size[0]/2)-(self.privchats[self.chat_message_to].size[0]/2)
posY = self.position[1]+(self.size[1]/2)-(self.privchats[self.chat_message_to].size[1]/2)
if posX > 0 and posY > 0:
self.privchats[self.chat_message_to].position = (posX, posY)
self.privchats[self.chat_message_to].visible = True
def on_PrivChatClose(self, userto):
try:
del self.privchats[userto]
except:
pass
def addToChatWindow(self, who, data, color="blue"):
#dstr = time.strftime("%d-%b-%y %H:%M:%S", time.localtime())
dstr = time.strftime("%H:%M:%S", time.localtime())
html="<child><br /><font color=\"gray\" size=\""+self.chatfontsize+"\">["+dstr+"] </font>"
handle="&lt;"+who+"&gt;"
if self.latest==who:
handle="..."
self.latest=who
html+="<font color=\""+color+"\" size=\""+self.chatfontsize+"\"><b>"+handle
html+=" </b></font><font size=\""+self.chatfontsize+"\">"+data+"</font></child>"
self.chathtml.append(html)
self.Freeze()
if len(self.chathtml) > 500:
del self.chathtml[0]
self.components.ChatArea.SetPage("".join(self.chathtml))
else:
self.components.ChatArea.AppendToPage(html)
y = self.components.ChatArea.GetInternalRepresentation().GetHeight()
self.components.ChatArea.Scroll(0, y)
self.Thaw()
def on_incomingChat(self, result):
color = 'green'
if str(result[0]) == 'Skylive Server':
color = 'gray'
if str(self.username) != str(result[0]):
self.addToChatWindow(result[0], result[1], color)
#txt = '<'+result[0]+'> '+result[1]
#if str(self.username) != str(result[0]):
# self.oldtxt = self.components.ChatArea.text.split("\n")
# if len(self.oldtxt) < 500:
# self.components.ChatArea.appendText(txt+'\n')
# else:
# #Set remove(0,self.firstLine+1) --> +1 for remove \n char
# self.firstLine = self.components.ChatArea.getLineLength(0)
# self.components.ChatArea.remove(0,self.firstLine+1)
# self.components.ChatArea.appendText(txt+"\n")
def on_menuSaveChat_select(self, event):
#TODO: it's unable to write chat if special char are present in text
#self.chatPubText = self.components.ChatArea.text.encode('latin-1')
self.chatPubText = "\n".join(self.chathtml)
self.chat_file_path = os.path.expanduser("~")
self.chat_file_usr_path = os.path.normpath(self.chat_file_path+"/skylive-ng_chat")
result = dialog.saveFileDialog(self, self.getText('savechattext1'), self.chat_file_usr_path, 'chat.txt', 'Text Files: (*.txt)|*.txt')
if result.accepted:
self.path = result.paths[0]
self.chat_file = open(self.path,"w")
self.chat_file.write(self.getText('savechattext2')+self.chatPubText)
self.chat_file.close()
self.alertDialog(self.getText('savechattext3')+self.path)
def on_menuBooking_select(self, event):
self.bookingPop = model.childWindow(self, booking.Booking, "./gui/booking.rsrc.py")
self.bookingPop.visible = True
def on_menuAccount_select(self, event):
self.userinfoPop = model.childWindow(self, userinfo.UserInfo, "./gui/userinfo.rsrc.py")
self.userinfoPop.visible = True
def addToPrivChatWindow(self, who, data, to, color="blue"):
#dstr = time.strftime("%d-%b-%y %H:%M:%S", time.localtime())
dstr = time.strftime("%H:%M:%S", time.localtime())
html="<child><br /><font color=\"gray\" size=\""+self.chatfontsize+"\">["+dstr+"] </font>"
handle="&lt;"+who+"&gt;"
if self.privchats[to].latest==who:
handle="..."
self.privchats[to].latest=who
html+="<font color=\""+color+"\" size=\""+self.chatfontsize+"\"><b>"+handle
html+=" </b></font><font size=\""+self.chatfontsize+"\">"+data+"</font></child>"
pchathtml = self.privchats[to].chathtml
pchathtml.append(html)
self.Freeze()
if len(pchathtml) > 500:
del pchathtml[0]
self.privchats[to].components.ChatArea.SetPage("".join(pchathtml))
else:
self.privchats[to].components.ChatArea.AppendToPage(html)
y = self.privchats[to].components.ChatArea.GetInternalRepresentation().GetHeight()
self.privchats[to].components.ChatArea.Scroll(0, y)
self.Thaw()
self.privchats[to].chathtml = pchathtml
def on_incomingPrivChat(self, result):
# Messages from server are identical to priv messages from users
if result[0] == 'Server Skylive':
self.alertDialog(result[1])
else:
self.chat_message_tocomp = result[0]
if result[0][:1] == '@':
result[0] = result[0][1:]
else:
# This is a bad hack. In the skylive protocol, when a
# user is a paying user that can control telescopes,
# it has a @ in front of he's nickname. When you need to write a
# privmsg to this user, you need to send the message to the nick
# complete with also the initial @, but when you receive a message
# from a user you don't receive the initial @, so, if a user with
# the initial @ write a message to you and you don't have a query
# window open yet, you will get he's nick without the @ char, and
# the user can't read your answer, and the server don't advise you
# about that.
# So, to solve this issue, a very bad hack is to try to find the
# real nickname on the channel list, hoping that the user is
# already in the same channel. Maybe in future we will do
# something like modify the server to solve this issue.
for nick in self.components.UserlistArea.items:
if nick[1:] == self.chat_message_tocomp:
self.chat_message_tocomp = nick
#txt = '<'+result[0]+'> '+result[1]
self.chat_message_to = result[0]
self.on_PrivMesgClick(False)
color = 'green'
if str(result[0]) == 'Skylive Server':
color = 'gray'
if str(self.username) != str(result[0]):
self.addToPrivChatWindow(result[0], result[1], result[0], color)
#self.oldtxt = self.privchats[result[0]].components.ChatArea.text.split("\n")
#if len(self.oldtxt) < 500:
# self.privchats[result[0]].components.ChatArea.appendText(txt+"\n")
#else:
# self.firstLine = self.privchats[result[0]].components.ChatArea.getLineLength(0)
# self.privchats[result[0]].components.ChatArea.remove(0,self.firstLine+1)
# self.privchats[result[0]].components.ChatArea.appendText(txt+"\n")
def on_incomingWebLink(self, result):
link = result[0]
try:
webbrowser.open(link)
except:
self.alertDialog("Default WebBrowser is not defined")
def on_incomingBigLive(self, result):
self.on_LiveDuplicate(result)
def on_incomingHtmlMessage(self, result):
sender = result[0]
code = result[1]
width = result[2]
heigth = result[3]
rsrc = "./gui/resizableinfo.rsrc.py"
self.aboutPop = model.childWindow(self, info.infoBox, rsrc)
self.aboutPop.title = "Message from "+str(sender)
self.aboutPop.size = (int(width), int(heigth))
self.aboutPop.panel.SetSize(self.aboutPop.size)
self.aboutPop.components.infobox.visible=False
self.aboutPop.components.htmlbox.SetPage(code)
self.aboutPop.components.htmlbox.visible=True
self.aboutPop.visible = True
self.aboutPop.on_size(False)
def on_statusMessageFromServer(self, message):
self.StatusTextFormat(message[0], message[1], message[2])
def on_AuthFromServer(self, status):
#print "AUTHFROMSERVER"
try:
if not self.count:
self.count=1
else:
pass
except:
self.count=1
if not status:
self.config.changeLoginCredentials(self.count)
self.srvproto.AuthString(config.getUsername(), config.getPassword())
self.TwistedLoop.serverReconnect()
self.count+=1
else:
self.TelescopeChange(self.telescopesel)
def on_ChatSend_mouseClick(self, event):
txt = self.components.ChatField.text
self.components.ChatField.text = ''
if len(txt.replace(" ", "")) > 0:
self.TwistedLoop.sendNetworkData(self.srvproto.chatSendPublic(txt))
color = 'red'
data = parser.toHtml(txt)
self.addToChatWindow(self.username, data, color)
#txt = "<"+self.username+"> "+txt
#self.oldtxt = self.components.ChatArea.text.split("\n")
#if len(self.oldtxt) < 500:
# self.components.ChatArea.appendText(txt+'\n')
#else:
# self.firstLine = self.components.ChatArea.getLineLength(0)
# self.components.ChatArea.remove(0,self.firstLine+1)
# self.components.ChatArea.appendText(txt+"\n")
def on_ChatField_keyPress(self, event):
if event.GetKeyCode() == wx.WXK_RETURN:
self.on_ChatSend_mouseClick(event)
event.skip()
else:
event.skip()
def on_ChatSend_gainFocus(self, event):
# Ugly, bad, orrible hack to make
# the fucking windows work with RETURN keypress.
if os.name == 'nt':
if len(self.components.ChatField.text) > 0:
self.on_ChatSend_mouseClick(False)
event.skip()
self.components.ChatField.setFocus()
def on_LiveCentrePopupClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.moveCenter(self.CenterLiveString))
def on_Live640_mouseContextUp(self, event):
if self.domeisopen:
abx, aby = event.position
sizeX, sizeY = self.components.Live640.size
relX = str(abx-(sizeX/2))
relY = str(aby-(sizeY/2))
if relX[:1] != '-':
relx='+'+relX.zfill(3)
else:
relx='-'+relX[1:].zfill(3)
if relY[:1] != '-':
rely='+'+relY.zfill(3)
else:
rely='-'+relY[1:].zfill(3)
self.CenterLiveString = relx+rely
self.popupID1 = wx.NewId()
self.popupID2 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_LiveCentrePopupClick, id=self.popupID1)
self.Bind(wx.EVT_MENU, self.on_showLiveDSS, id=self.popupID2)
if self.adminPrivilege:
self.popupID3 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_activateCross, id=self.popupID3)
if not self.livedup:
self.popupID4 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_LiveDuplicate, id=self.popupID4)
menu = wx.Menu()
menu.Append(self.popupID1, self.getText('poplivemenu1'))
menu.Append(self.popupID2, self.getText('poplivemenu2'))
if self.adminPrivilege:
if self.ciceroneMode:
menu.Append(self.popupID3, self.getText('poplivemenu3'))
else:
menu.Append(self.popupID3, self.getText('poplivemenu4'))
if not self.livedup:
menu.Append(self.popupID4, self.getText('poplivemenu5'))
self.popupID5 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_autoFocus, id=self.popupID5)
menu.Append(self.popupID5, 'autofocus')
if self.adminPrivilege:
mfstr = 'manual focus'
if self.focusdialog:
mfstr = 'close manual focus'
self.popupID6 = wx.NewId()
#self.Bind(wx.EVT_MENU, self.on_FocusPlus, id=self.popupID6)
self.Bind(wx.EVT_MENU, self.on_OpenFocus, id=self.popupID6)
menu.Append(self.popupID6, mfstr)
#self.popupID7 = wx.NewId()
#self.Bind(wx.EVT_MENU, self.on_FocusLess, id=self.popupID7)
#menu.Append(self.popupID7, 'focus-')
self.popupID7 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_sync, id=self.popupID7)
menu.Append(self.popupID7, 'sync')
self.PopupMenu(menu, event.GetPosition())
menu.Destroy
def on_OpenFocus(self, event):
if not self.focusdialog:
self.focusdialog = True
self.FocusDialogWin = model.childWindow(self, focus.FocusDialog, "./gui/focus.rsrc.py")
self.FocusDialogWin._parent = self
else:
#try:
self.FocusDialogWin.close(True)
#except:
# pass
def on_CloseFocus(self, event=False):
self.focusdialog = False
del self.FocusDialogWin
def on_CloseAskStream(self, event=False):
self.askStreaming = False
def on_CloseStream(self, event=False):
self.Streaming = False
def on_autoFocus(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.sendFocus('Auto'))
def on_FocusPlus(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.sendFocus('Plus'))
def on_FocusLess(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.sendFocus('Less'))
def on_sync(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.sendSync())
def on_LiveDuplicate(self, event):
if not self.livedup:
self.livedup=model.childWindow(self, liveduplicate.LiveDuplicate, "./gui/liveduplicate.rsrc.py")
self.livedup._parent = self
self.livedup.setLiveImage(self.components.Live640.bitmap)
orw, orh = self.livedup.size
self.livedup.size = (orw*2, orh*2)
self.livedup.on_size(False)
def on_showLiveDSS(self, event):
ra = self.components.TelescopeRAText.text
dec = self.components.TelescopeDECText.text
fov = self.components.TelescopeFOVText.text
try:
y = fov.split("x")[0].replace("'", "").replace('"', '').replace(" ", ".")
x = fov.split("x")[1].replace("'", "").replace('"', '').replace(" ", ".")
if (ra != "00:00:0" and ra != "00:00.0") and dec.replace("-", "").replace("+", "") != "00.00":
#print ra, dec, x, y
ra = str(ra).replace(":", "%20").replace(".", "%20").replace(" ","")
dec = str(dec).replace(".", "%20").replace(":", "%20").replace(" ", "")
self.TwistedLoop.downloadDss(ra, dec, x, y, live=True)
except:
pass
def on_ButtonN_mouseClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.moveNorth())
def on_ButtonS_mouseClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.moveSouth())
def on_ButtonW_mouseClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.moveWest())
def on_ButtonE_mouseClick(self, event):
self.TwistedLoop.sendNetworkData(self.srvproto.moveEast())
def on_Sponsor_mouseClick(self, event):
try:
webbrowser.open("http://www.skylive.it/test2.htm")
except:
self.alertDialog("Default WebBrowser is not defined")
def on_menuSettingsLogin_select(self, event):
#print 'MENUSETTINGLOGIN'
self.config.changeLoginCredentials()
self.srvproto.AuthString(config.getUsername(), config.getPassword())
self.TwistedLoop.serverReconnect()
def on_PathChoose_mouseClick(self, event):
new_PathField = dialog.directoryDialog(self, self.getText('pathchosetext'), self.components.PathField.text)
if new_PathField.accepted:
self.components.PathField.text = new_PathField.path
self.config.put_usrDefaultPath(new_PathField.path)
self.usrDefSavePath = new_PathField.path
def on_PhotoSendToScript_mouseClick(self, event):
self.filename_seq = self.components.FileName.text
sep = self.scriptSep
if self.photo['bin'] and self.photo['filter'] and self.photo['exp'] and self.photo['repeat'] and self.filename_seq:
self.fileFounded = False
self.lastFileNumber = -1
for files in os.listdir(self.components.PathField.text):
fileFound = os.path.splitext(files)[0]
#print 'trovato file: ',fileFound
fileNameWOnum = fileFound[:-4]
if fileNameWOnum == self.filename_seq:
self.fileFounded = True
number = int(fileFound[-3:])
if number > self.lastFileNumber:
self.lastFileNumber = number
if self.fileFounded:
self.startN = str(self.lastFileNumber + 1)
else:
self.startN = str(self.photo['startn'])
self.scripts_count = self.scripts_count +1
self.script_line = "n."+str(self.scripts_count)+sep+"PHOTO"+sep+str(self.photo['exp']).zfill(3)+sep+str(self.photo['filter'])+sep+str(self.photo['guide'])+sep+str(self.photo['aflat'])+sep+str(self.photo['adark'])+sep+str(self.photo['web'])+sep+"BIN"+sep+str(self.photo['bin'])+sep+self.startN.zfill(3)+sep+str(self.photo['repeat'])+sep+os.path.normpath(self.components.PathField.text+"/"+self.filename_seq)
self.scripts.append(self.script_line)
self.updateScript()
def on_PointSendToScript_mouseClick(self, event):
sep = self.scriptSep
if self.selectedTarget:
try:
pointstring = self.srvproto.moveToTarget(self.selectedTarget)
except:
pointstring = False
if pointstring:
pointstringcmdS = pointstring.split("#^#")
pointstringscript = pointstringcmdS[3]
self.scripts_count = self.scripts_count +1
self.script_line = "n."+str(self.scripts_count)+sep+"GOTO"+sep+pointstringscript
self.scripts.append(self.script_line)
self.updateScript()
def updateScript(self):
self.components.ScriptArea.Clear()
if self.scripts:
for script in self.scripts:
self.components.ScriptArea.append(script)
else:
self.scripts_count=0
def on_ScriptArea_mouseContextUp(self, event):
sel = self.components.ScriptArea.GetSelections()
if len(sel) > 0:
script_sel = self.components.ScriptArea.getString(sel[0])
self.script_to_del = script_sel
relX, relY = event.GetPosition()
fX, fY = self.components.ScriptArea.position
self.popupID2 = wx.NewId()
self.Bind(wx.EVT_MENU, self.on_deleteScript, id=self.popupID2)
menu = wx.Menu()
menu.Append(self.popupID2, self.getText('scriptmenu1'))
self.PopupMenu(menu, (relX+fX, relY+fY))
menu.Destroy
def on_deleteScript(self, event):
self.scripts.remove(self.script_to_del)
self.updateScript()
def on_ScriptClear_mouseClick(self,event):
self.components.ScriptArea.Clear()
self.scripts=[]
self.scripts_count=0
def on_ScriptSave_mouseClick(self, event):
sep = self.scriptSep
if self.scripts:
self.script_tosave=[]
for script in self.scripts:
script_save = script.split(sep)
self.script_tosave.append(sep.join(script_save[1:]))
self.ScriptFileTxt = "\n".join(self.script_tosave)
ScriptSaveFile = dialog.saveFileDialog(self, self.getText('scriptsavetext1'), self.components.PathField.text, 'script.sks', self.getText('scriptsavetext2')+'(*.sks)|*.sks')
if ScriptSaveFile.accepted:
self.path = ScriptSaveFile.paths[0]
self.script_file = open(self.path,"w")
self.script_file.write(self.ScriptFileTxt)
self.script_file.close()
def on_ScriptLoad_mouseClick(self, event):
ScriptLoadFile = dialog.fileDialog(self, self.getText('scriptloadtext1'), self.components.PathField.text, ' ', self.getText('scriptloadtext2')+'(*.sks)|*.sks')
sep = self.scriptSep
if ScriptLoadFile.accepted:
self.load_path = ScriptLoadFile.paths[0]
self.script_file = open(self.load_path,"r")
self.ScriptFileTxt = self.script_file.read()
if len(self.ScriptFileTxt) > 0:
self.script_toload = self.ScriptFileTxt.split("\n")
for script in self.script_toload:
self.scripts_count = self.scripts_count + 1
self.scripts.append("n."+str(self.scripts_count)+sep+script)
self.updateScript()
def on_ScriptStart_mouseClick(self, event):
sysType = self.systemType
if not os.path.exists(os.path.normpath("./gui/scriptsgui."+sysType+".rsrc.py")):
sysType = "Linux"
if self.scripts:
self.scriptgui = model.childWindow(self, scriptsgui.Scriptsgui, "./gui/scriptsgui."+sysType+".rsrc.py")
self.scriptgui._parent = self
self.scriptgui.scripts = self.scripts
self.scriptgui.actualtel = self.telescopesel
posX = self.position[0]+(self.size[0]/2)-(self.scriptgui.size[0]/2)
posY = self.position[1]+(self.size[1]/2)-(self.scriptgui.size[1]/2)
self.scriptgui.position = (posX, posY)
self.scriptgui.visible = True
self.scriptguiStarted = True
def on_photoStatus(self, message):
if message == "notReady":
# uploading photo to server
# XXX i think do nothing ... but i use it to double check before download photo.
if self.photoKeyClick:
self.photoInUpload = True
elif message == "Ready":
# photo ready to be downloaded
if self.photoKeyClick and self.photoInUpload:
self.photoKeyClick = False
self.photoInUpload = False
self.TwistedLoop.downloadFits(self.telescopesel)
def on_downPopOpen(self, size, uniqueid):
if not uniqueid in self.downPop.keys():
self.downPop[uniqueid] = model.childWindow(self, downprog.DownProgr, "./gui/downprog.rsrc.py")
self.downPop[uniqueid].title = self.getText('downloadtitle')+size+" kb"
self.downPop[uniqueid].components.downpr.text = self.getText('downloadtext')+size+" kb"
self.downPop[uniqueid].visible = True
def on_downPopUpdate(self, *args):
try:
uniqueid=args[2]
self.downPop[uniqueid].components.downpr.text = args[0]
self.downPop[uniqueid].components.progBar.value = int(args[1])
self.downPop[uniqueid].components.progPerc.text = str(int(args[1]))+'%'
except:
pass
def on_downPopClose(self, uniqueid):
try:
self.downPop[uniqueid].close()
del self.downPop[uniqueid]
except:
pass
def on_menuFitsOpen_command(self, event):
self.FistOpener = model.childWindow(self, fitsopener.FitsOpener, "./gui/fitsopener.rsrc.py")
self.FistOpener.parent = self
self.FistOpener.visible = True
def on_requestData(self, req):
if req:
self.srvproto.AuthString(str(config.getUsername()), str(config.getPassword()))
self.TwistedLoop.sendNetworkData(self.srvproto.MsgLogin())
if self.initialized and self.connLoose:
self.connLoose = False
def on_about_skylive_command(self,event):
rsrc = "./gui/info.rsrc.py"
if self.systemType == 'Darwin':
rsrc = "./gui/info.rsrc.Darwin.py"
self.aboutPop = model.childWindow(self, info.infoBox, rsrc)
self.aboutPop.title = self.getText('aboutTitle')
self.aboutPop.components.infobox.visible=False
self.aboutPop.components.htmlbox.SetPage("""
<font size="2">
Skylive-ng project by:<br>
<br>
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it><br>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com><br>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it><br>
<br><br>
Trac Site : <a href="http://www.astronomix.org/trac/wiki/SkyLiveNG">
http://www.astronomix.org/trac/wiki/SkyLiveNG</a><br>
Web Site : <a href="http://www.skylive.it">http://www.skylive.it</a><br><br>
<a href="http://www.astronomix.org/trac/wiki/helpClientNG">More Info - Maggiori informazioni</a><br>
</font>
""")
self.aboutPop.components.htmlbox.visible=True
self.aboutPop.visible = True
def createFileName(self):
#Filename structure : objname_selected-filter_bin_exp-time_xxx.fit
if self.initialized and not self.custom_fn:
sep = "_"
fn1 = self.components.CurrentObjectText.text
charlist = ":-.+"
for x in charlist:
fn1= fn1.replace(x ,'')
fn2 = self.components.ComboFilters.text
fn3 = str(self.components.ComboBin.text)
fn4 = str(self.components.SpinnerExposition.value)
name = fn1+sep+fn2+sep+fn3+sep+fn4
self.components.FileName.text=name
elif not self.initialized and self.custom_fn:
name = "SkyliveNG"
self.components.FileName.text=name
def on_PhotoTXTFilename_mouseClick(self, event):
self.custom_fn = True
result = dialog.textEntryDialog(self,
self.getText('filenameDialog1'),
self.getText('filenameDialog2'),
self.components.FileName.text)
if result.accepted:
self.components.FileName.text = result.text
else:
self.custom_fn = False
self.createFileName()
def on_telescopeFeat(self, args):
arg = args.split("**")
self.components.TelescopeModelText.text=str(arg[0])
self.components.TelescopeFocalText.text=str(arg[4])
self.components.TelescopeFOVText.text=str(arg[3])
self.components.TelescopeCCDText.text=str(arg[1])
self.components.TelescopeFiltersText.text=str(arg[2])
self.changeFilters(arg[2])
def on_domeStatus(self, arg):
if arg.lower() != "closed":
self.domeisopen = True
if arg.lower() == 'unknown':
self.components.ObservatoryDomeText.text = self.getText('unknown')
else:
self.components.ObservatoryDomeText.text= self.getText('domeopen')
else:
self.domeisopen = False
self.components.ObservatoryDomeText.text= self.getText('domeclosed')
def on_rainStatus(self, arg):
stat = arg.lower()
if stat == 'clear' or stat == 'clean':
ret = self.getText('weatherclean')
elif stat == 'cloudy':
ret = self.getText('weathercloudy')
elif stat == 'vcloudy':
ret = self.getText('weathervcloudy')
elif stat == 'rain':
ret = self.getText('weatherrain')
else:
ret = self.getText('unknown')
self.components.RainSensorText.text= ret
def on_objName(self, arg):
self.components.CurrentObjectText.text=str(arg)
self.createFileName()
#def on_PingReq(self, arg):
# # XXX We shuld answer directly from the twisted part!
# if arg:
# self.TwistedLoop.sendNetworkData(self.srvproto.sendPong())
def on_LonLat(self, args):
arg = args.split("**")
self.components.TelescopeGPSPos2.text = str(arg[0])
self.components.TelescopeGPSPos1.text = str(arg[1])
def on_dssGifDownloaded(self, gif, live=False):
sysType = self.systemType
if not os.path.exists(os.path.normpath("./gui/imager."+sysType+".rsrc.py")):
sysType = "Linux"
self.DssImager = model.childWindow(self, imager.SkyliveImager, "./gui/imager."+sysType+".rsrc.py")
self.DssImager._parent = self
posX = self.position[0]+(self.size[0]/2)-(self.DssImager.size[0]/2)
posY = self.position[1]+(self.size[1]/2)-(self.DssImager.size[1]/2)
self.DssImager.position = (posX, posY)
self.DssImager.title = self.getText('dssTitle')
im = Image.open(gif)
if not live:
try:
dssgif = im.resize((self.xsizeBit,self.ysizeBit))
except:
xsize, ysize = im.size
self.xsizeBit = xsize/4
self.ysizeBit = ysize/4
dssgif = im.resize((self.xsizeBit,self.ysizeBit))
else:
xsize, ysize = im.size
self.xsizeBit = xsize/4
self.ysizeBit = ysize/4
dssgif = im.resize((self.xsizeBit,self.ysizeBit))
image = wx.EmptyImage(self.xsizeBit, self.ysizeBit)
image.SetData(dssgif.convert("RGB").tostring())
newBitmap = graphic.Bitmap()
newBitmap.setImageBits(image)
self.DssImager.components.ImageShow.bitmap = newBitmap
self.DssImager.size = (self.xsizeBit+20, self.ysizeBit+100)
oxc, oyc = self.DssImager.components.ButtonClose.position
self.DssImager.components.ButtonClose.position = (oxc, oyc-240+int(self.ysizeBit))
self.DssImager.components.ButtonClose.visible = True
self.DssImager.fromEvent = "dssGif"
self.DssImager.visible = True
def on_setStars(self, list):
if not self.starsSetted:
p = protocol.ProtoParser()
res = list.split(";")
self.starlist = p.ParseLX200CatalogFromSkylive(res)
self.setStarsList()
self.starsSetted = True
def on_setFWHM(self, fwhm):
self.components.FWHMText.text = str(fwhm)
def on_Streaming(self, suri):
oldStream = self.StreamUri
self.StreamUri = suri
if self.StreamUri == 'NONE':
if self.Streaming:
try:
self.Streaming.close()
except:
pass
else:
if not self.Streaming:
self.on_menuVideoOpen_command()
else:
if oldStream != self.StreamUri:
self.Streaming.close()
self.on_menuVideoOpen_command()
def on_ForceStreaming(self, suri):
oldStream = self.StreamUri
self.StreamUri = suri
if self.StreamUri == 'NONE':
if self.Streaming:
try:
self.Streaming.close()
except:
pass
else:
if not self.Streaming:
self.on_menuVideoOpen_command(force=True)
else:
if oldStream != self.StreamUri:
self.Streaming.close()
self.on_menuVideoOpen_command(force=True)
def on_setDoubles(self, list):
if not self.doubleSetted:
p = protocol.ProtoParser()
res = list.split(";")
self.doublelist = p.ParseLX200CatalogFromSkylive(res)
self.setDoublesList()
self.doubleSetted = True
def on_setTscopeCombo(self, tnum):
if not self.TscopeComboSetted:
for tscope in range(1, int(tnum)+1):
self.components.TScopeCombo.append(self.getText('TScopeComboGen') % str(tscope))
self.TscopeComboSetted = True
def on_setAdminPriv(self, isAdmin):
if isAdmin:
self.adminPrivilege = True
def resetCiceroneMode(self):
self.ciceroneMode = False
self.resendCrossC = False
self.addCross = False
sizeX, sizeY = self.components.Live640.size
self.ciceronePosx = sizeX/2
self.ciceronePosy = sizeY/2
def on_activeCicerone(self, posxy):
self.addCross = True
self.ciceronePosx = posxy[0]
self.ciceronePosy = posxy[1]
def drawCross(self, liveImage, pox, poy):
posx = int(pox)
posy = int(poy)
p = ImageFile.Parser()
p.feed(liveImage)
im = p.close()
draw = ImageDraw.Draw(im)
draw.line([(posx, posy),(posx+15, posy+15)], fill=self.defaultPointerColor, width=1)
draw.line([(posx, posy),(posx+7, posy)], fill=self.defaultPointerColor, width=1)
draw.line([(posx, posy),(posx, posy+10)], fill=self.defaultPointerColor, width=1)
del draw
image = wx.EmptyImage(320, 240)
image.SetData(im.convert("RGB").tostring())
Bitmap = graphic.Bitmap()
Bitmap.setImageBits(image)
try:
self.components.Live640.bitmap = Bitmap
self.liveBitmap = Bitmap
self.addCross = False
except:
pass
def on_Live640_mouseDoubleClick(self, event):
if self.adminPrivilege and self.ciceroneMode:
abx, aby = event.position
self.crossX = abx
self.crossY = aby
command = self.srvproto.sendCross(str(abx), str(aby))
self.TwistedLoop.sendNetworkData(command)
self.resendCrossC = True
def resendCross(self):
command = self.srvproto.sendCross(str(self.crossX), str(self.crossY))
self.TwistedLoop.sendNetworkData(command)
def on_activateCross(self, event):
if self.ciceroneMode:
self.ciceroneMode = False
else:
self.ciceroneMode = True
def writeARDEC(self, ra, dec):
#this is to fit old fake driver for windows skymap to track scope position
if self.systemType == "Windows" and self.useExtProgram == 'True':
txt = ra+'#'+dec.replace('*','.')+'#'
# XXX It is better to choose a TEMP path
# but we have also to modify the fake driver
ardecFile = open('c:\\ardec.txt',"w")
ardecFile.write(txt)
ardecFile.close()
def on_menuSettingsPreference_select(self, event):
self.usrSettings = model.childWindow(self, settings.Settings, "./gui/settings/settings.rsrc.py")
self.usrSettings._parent = self
self.usrSettings.visible = True
def setCharSizes(self):
if self.charSizes:
self.chatfontsize = self.charSizes['chatsize']
#self.components.ChatArea.font = {'size':int(self.charSizes['chatsize'])}
self.components.UserlistArea.font = {'size':int(self.charSizes['listsize'])}
self.components.ChatField.font = {'size': int(self.charSizes['inputsize'])}
def on_OnLineHelp_command(self, event):
try:
webbrowser.open("http://www.astronomix.org/trac/wiki/helpClientNG")
except:
self.alertDialog("Default WebBrowser is not defined")
def on_menuMeteoOpen_command(self, event):
try:
webbrowser.open("http://www.astronomix.org/trac/wiki/meteoClientNG")
except:
self.alertDialog("Default WebBrowser is not defined")
def on_menuVideoOpen_command(self, event=False, force=False):
self.enableStream, self.askStream=config.get_streamingPref()
if not self.askStreaming and not self.Streaming and self.askStream in ['True', 'yes', 'y', 'Yes', '1']:
self.askStreaming = model.childWindow(self, askstream.AskStream, "./gui/askstream.rsrc.py")
elif not self.askStreaming and not self.Streaming and self.enableStream in ['True', 'yes', 'y', 'Yes', '1']:
self.on_realStartStream(event)
elif not self.askStreaming and not self.Streaming and force:
# We are configure to not ask, but we have no streaming enabled, so, we ask
# anyway.
self.askStreaming = model.childWindow(self, askstream.AskStream, "./gui/askstream.rsrc.py")
def on_realNoStream(self, event):
if self.askStreaming:
# Called from the askStreaming window
if self.askStreaming.components.save.checked:
config.put_streamingPref(False, False)
self.askStreaming.close(True)
def on_realStartStream(self, event):
if self.askStreaming:
if self.askStreaming.components.save.checked:
config.put_streamingPref(True, False)
self.askStreaming.close(True)
if not self.Streaming:
self.Streaming = model.childWindow(self, stream.Stream, "./gui/stream.rsrc.py")
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.components.Pointing.label = self.getText('Pointing')
self.components.PhotoInputs.label = self.getText('PhotoInputs')
self.components.CCDBox.label = self.getText('CCDBox')
self.components.StatusBox.label = self.getText('StatusBox')
self.components.StaticBox4.label = self.getText('StaticBox4')
self.components.Telescope.label = self.getText('Telescope')
self.components.TScopeCombo.text = self.getText('TScopeCombo')
self.components.ChatSend.label = self.getText('ChatSend')
self.components.ButtonN.label = self.getText('ButtonN')
self.components.ButtonW.label = self.getText('ButtonW')
self.components.ButtonE.label = self.getText('ButtonE')
self.components.ButtonS.label = self.getText('ButtonS')
self.components.ComboPlanets.text = self.getText('ComboPlanets')
self.components.PointPlanets.text = self.getText('PointPlanets')
self.components.ComboStars.text = self.getText('ComboStars')
self.components.PointStars.text = self.getText('PointStars')
self.components.ComboDouble.text = self.getText('ComboDouble')
self.components.PointDouble.text = self.getText('PointDouble')
self.components.ComboMessier.text = self.getText('ComboMessier')
self.components.PointMessier.text = self.getText('PointMessier')
#self.components.ComboIC.text = self.getText('ComboIC')
self.components.PointAR1.text = self.getText('PointAR1')
self.components.PointGOTO.label = self.getText('PointGOTO')
self.components.PointSendToScript.label = self.getText('PointSendToScript')
self.components.PathChoose.label = self.getText('PathChoose')
self.components.LastPhoto.label = self.getText('LastPhoto')
self.components.BigLive.label = self.getText('BigLive')
self.components.MakePhoto.label = self.getText('MakePhoto')
self.components.PhotoSendToScript.label = self.getText('PhotoSendToScript')
self.components.PhotoTXTRepeat.text = self.getText('PhotoTXTRepeat')
self.components.PhotoTXTStartnumber.text = self.getText('PhotoTXTStartnumber')
self.components.PhotoTXTFilename.label = self.getText('PhotoTXTFilename')
self.components.PhotoTXTGuide.text = self.getText('PhotoTXTGuide')
self.components.PhotoTXTFilter.text = self.getText('PhotoTXTFilter')
self.components.PhotoTXTExp.text = self.getText('PhotoTXTExp')
self.components.ScriptLoad.label = self.getText('ScriptLoad')
self.components.ScriptSave.label = self.getText('ScriptSave')
self.components.ScriptStart.label = self.getText('ScriptStart')
self.components.ScriptStop.label = self.getText('ScriptStop')
self.components.ScriptContinue.label = self.getText('ScriptContinue')
self.components.ScriptClear.label = self.getText('ScriptClear')
self.components.ScriptReset.label = self.getText('ScriptReset')
self.components.ScriptStatus.text = self.getText('ScriptStatus')
self.components.StatusRain.text = self.getText('StatusRain')
self.components.StatusDome.text = self.getText('StatusDome')
self.components.StatusObject.text = self.getText('StatusObject')
self.components.TelescopeCCDTemp.text = self.getText('TelescopeCCDTemp')
self.components.MoveRA.text = self.getText('MoveRA')
self.components.TelescopeFilters.text = self.getText('TelescopeFilters')
self.components.TelescopeGPS.text = self.getText('TelescopeGPS')
self.components.TelescopeGPS2.text = self.getText('TelescopeGPS2')
self.components.TelescopeFOW.text = self.getText('TelescopeFOW')
self.components.TelescopeFocal.text = self.getText('TelescopeFocal')
self.components.TelescopeMODEL.text = self.getText('TelescopeMODEL')
self.components.Sponsor.label = self.getText('Sponsor')
submenu = ['menuCheckVersion', 'menuSaveChat', 'menuFileExit',
'menuSettingsLogin', 'menuSettingsPreference',
'menuFitsOpen', 'menuMeteoOpen', 'menuHelpAboutSkyliveNG',
'menuHelpHelpOnLine']
try:
for item in submenu:
idmenuItem = self.menuBar.getMenuId(item)
self.MenuBar.SetLabel(idmenuItem, self.getText(item))
except:
pass
def on_TeleLink(self, stat):
if stat == 'TeleON':
self.teleOn = True
elif stat == 'TeleOFF':
self.teleOn = False
def on_udpcmd(self, cmd):
#print "ricevuto ", cmd
self.on_SelectTarget('AR', cmd)
#print self.selectedTarget
try:
pointstring = self.srvproto.moveToTarget(self.selectedTarget)
except:
pointstring = False
if pointstring:
self.TwistedLoop.sendNetworkData(pointstring)
def on_indicmd(self, cmd):
# XXX for the moment just like udpcmd
#print 'INDI COMMAND', cmd
self.on_udpcmd(cmd)
def writeARDECIndi(self, RA, DEC):
ra = RA.replace('.', ':')
dec = DEC.replace('.', ':')
self.TwistedLoop.sendINDITelePos(ra, dec)
#def on_ChatArea_mouseDoubleClick(self, event):
# x = ''
# y = ''
# url = False
# posA = 0
# posB = 0
# noUrl = False
# cpoint = self.components.ChatArea.getSelection()
# while 'http' not in x and '>' not in x:
# x = self.components.ChatArea.getString(cpoint[0]-posA, cpoint[0]-posA+4)
# if '>' in x or '<' in x:
# noUrl = True
# posA+=1
# if not noUrl:
# while y != ' ' and y != '\n':
# y = self.components.ChatArea.getString(cpoint[1]+posB, cpoint[1]+posB+1)
# posB+=1
# A = cpoint[0]-posA+1
# B = cpoint[1]+posB-1
# text = self.components.ChatArea.getString(A, B)
# if len(text.split(' ')) > 1:
# urlTry = text.split(' ')[0]
# else:
# urlTry = text
# if len(urlTry) > 12:
# url = urlTry
# try:
# if url:
# webbrowser.open(url)
# except:
# self.dialog.alertdialog(self, "Default WebBrowser is not defined")
def osxUpgradeDownloaded(self):
self.dialog.alertdialog(self, self.getText('osxUpgradeDone'))
self.on_close(self, True)
def on_ChatArea_mouseDown(self, event):
self.canSelect = True
event.skip()
def on_ChatArea_mouseUp(self, event):
self.canSelect = False
event.skip()
def on_ChatArea_gainFocus(self, event):
# Ugly, bad, orrible hack to make
# the fucking windows work with RETURN keypress.
if not self.canSelect:
if os.name == 'nt':
if len(self.components.ChatField.text) > 0:
self.on_ChatSend_mouseClick(False)
self.components.ChatField.setFocus()
event.skip()
def on_ChatArea_keyPress(self, event):
key = event.GetKeyCode()
if key in range (31, 128):
self.components.ChatField.setFocus()
self.components.ChatField.appendText(unicode(chr(key)))
else:
self.components.ChatField.setFocus()
event.skip()
def on_setBins(self, bins):
binitems = bins.split(',')
self.components.ComboBin.items = []
self.components.ComboBin.items = binitems
self.components.ComboBin.text = u'X'
def script_Command(self, cmd, *args, **kwargs):
#print 'script command', cmd, args, kwargs
if self.scriptguiStarted:
#print 'started'
try:
f = getattr(self.scriptgui, cmd)
if f and callable(f):
return f(*args, **kwargs)
except:
pass
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model
class Register(model.CustomDialog):
def on_initialize(self, event):
pass
{'type':'CustomDialog',
'name':'Minimal',
'title': u'New account request',
'size':(490, 255),
'components': [
#{'application':{'type':'Application',
# 'name':'Template',
# 'backgrounds': [
# {'type':'Background',
# 'name':'bgTemplate',
# 'title':u'New account request',
# 'size':(490, 255),
# 'useSizers':0,
#
# 'menubar': {'type':'MenuBar',
# 'menus': [
# {'type':'Menu',
# 'name':'menuFile',
# 'label':'&File',
# 'items': [
# {'type':'MenuItem',
# 'name':'menuFileExit',
# 'label':'E&xit',
# 'command':'exit',
# },
# ]
# },
# ]
# },
# 'components': [
{'type':'StaticLine',
'name':'StaticLine1',
'position':(271, 8),
'size':(-1, 180),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'layout':'vertical',
},
{'type':'ComboBox',
'name':'ComboBox3',
'position':(285, 93),
'size':(178, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'items':[],
'text':'ComboBox3',
},
{'type':'StaticText',
'name':'TextObject',
'position':(285, 70),
'size':(180, 40),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'I whish to observ:',
},
{'type':'StaticText',
'name':'TextUsername',
'position':(286, 17),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Please choose a username:',
},
{'type':'StaticText',
'name':'TextCity',
'position':(10, 135),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'City',
},
{'type':'StaticText',
'name':'TextNation',
'position':(10, 165),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Nation',
},
{'type':'StaticText',
'name':'TextEmail',
'position':(10, 105),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Email',
},
{'type':'StaticText',
'name':'TextSurname',
'position':(10, 75),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Surname',
},
{'type':'StaticText',
'name':'TextName',
'position':(10, 45),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Name',
},
{'type':'StaticText',
'name':'TextLanguage',
'position':(10, 15),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Language',
},
{'type':'Button',
'name':'Submit',
'position':(321, 159),
'size':(-1, 27),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'label':'Submit',
},
{'type':'TextField',
'name':'Name',
'position':(80, 40),
'size':(180, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Name',
},
{'type':'ComboBox',
'name':'ComboBox2',
'position':(80, 10),
'size':(178, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'items':[],
'text':'ComboBox2',
},
{'type':'CheckBox',
'name':'TermsOfUsage',
'position':(285, 130),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'label':'Yes, i accept ',
},
{'type':'ComboBox',
'name':'ComboBox1',
'position':(80, 160),
'size':(178, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'items':[],
'text':'ComboBox1',
},
{'type':'TextField',
'name':'Username',
'position':(285, 40),
'size':(180, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Username',
},
{'type':'TextField',
'name':'Surname',
'position':(80, 70),
'size':(180, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Surname',
},
{'type':'TextField',
'name':'Email',
'position':(80, 100),
'size':(180, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'Email',
},
{'type':'TextField',
'name':'City',
'position':(80, 130),
'size':(179, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'text':'City',
},
] # end components
,
'sizers':
[
{
'name' : 'ALL',
'type' : 'i',
'children' : [
{
'name' : 'TOP SIZER',
'typ' : 'v',
'horGrowth' : 1,
'verGrowth' : 1 },
{
'name' : 'UNPLACED',
'type' : 'i',
'children' : [
{
'name' : 'ComboBox1' },
{
'name' : 'ComboBox2' },
{
'name' : 'Surname' },
{
'name' : 'Name' },
{
'name' : 'Email' },
{
'name' : 'City' },
{
'name' : 'Username' },
{
'name' : 'TextLanguage' },
{
'name' : 'TextName' },
{
'name' : 'TextSurname' },
{
'name' : 'TextEmail' },
{
'name' : 'TextNation' },
{
'name' : 'TextCity' },
{
'name' : 'TextUsername' },
{
'name' : 'StaticLine1' },
{
'name' : 'ComboBox3' },
{
'name' : 'TextObject' },
{
'name' : 'TermsOfUsage' },
{
'name' : 'Submit' },
] # end of UNPLACED
},
] # end of ALL
},
] # end of sizers
#} # end background
#] # end backgrounds
#} }
}
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':' ',
'style': ['resizeable'],
'icon':'gui/img/ICONA.ico',
'size':(530, 310),
'components': [
{'type':'Button',
'name':'closeinfo',
'position':(230, 285),
'size':(50, 25),
'label':u'Close',
'visible':False,
},
{'type':'TextArea',
'name':'infobox',
'position':(10, 10),
'size':(510, 275),
'editable':False,
},
{'type':'InfoHtmlWindow',
'name':'htmlbox',
'position':(10, 10),
'size':(510, 275),
'editable':False,
'visible':False,
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Scripts queue and Status (MAC)',
'icon':'gui/img/ICONA.ico',
'size':(450, 400),
'backgroundColor':(192, 192, 192),
'components': [
{'type':'Button',
'name':'pauseScript',
'position':(258, 347),
'size':(-1, 23),
'label':'Pause',
},
{'type':'Button',
'name':'startScript',
'position':(337, 347),
'size':(-1, 23),
'enabled':False,
'label':'Start scripts',
},
{'type':'TextArea',
'name':'ScriptStatusArea',
'position':(15, 309),
'size':(420, 22),
'editable':False,
},
{'type':'StaticBox',
'name':'SGstatusBox',
'position':(10, 290),
'size':(430, 50),
'label':'Script Status',
},
{'type':'TextArea',
'name':'repeatArea',
'position':(281, 250),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'nExpTXT',
'position':(162, 255),
'text':'Number of Exposure',
},
{'type':'TextArea',
'name':'startnArea',
'position':(95, 250),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'startNTXT',
'position':(15, 255),
'text':'StartNumber',
},
{'type':'CheckBox',
'name':'AutoDarkArea',
'position':(414, 188),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText8',
'position':(365, 193),
'text':'AutoDark',
},
{'type':'TextArea',
'name':'fileArea',
'position':(95, 220),
'size':(322, 22),
'editable':False,
'text':'/',
},
{'type':'StaticText',
'name':'pathTXT',
'position':(15, 224),
'text':'Path/Filename',
},
{'type':'CheckBox',
'name':'AutoFlatArea',
'position':(345, 188),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText6',
'position':(301, 193),
'text':'AutoFlat',
},
{'type':'CheckBox',
'name':'GuideArea',
'position':(237, 188),
'enabled':False,
'label':' ',
},
{'type':'CheckBox',
'name':'WebArea',
'position':(280, 188),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText5',
'position':(258, 193),
'text':'Web',
},
{'type':'StaticText',
'name':'guideTXT',
'position':(204, 193),
'text':'Guide',
},
{'type':'TextArea',
'name':'BinArea',
'position':(170, 190),
'size':(30, 22),
'editable':False,
'text':'X',
},
{'type':'StaticText',
'name':'StaticText3',
'position':(150, 193),
'text':'Bin',
},
{'type':'TextArea',
'name':'FilterArea',
'position':(116, 190),
'size':(30, 22),
'editable':False,
'text':'X',
},
{'type':'StaticText',
'name':'filterTXT',
'position':(88, 193),
'text':'Filter',
},
{'type':'TextArea',
'name':'ExpArea',
'position':(40, 190),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'expTXT',
'position':(16, 193),
'text':'Exp',
},
{'type':'StaticBox',
'name':'runningBox',
'position':(10, 170),
'size':(430, 110),
'label':'Script Running',
},
{'type':'TextArea',
'name':'queue_scripts',
'position':(15, 30),
'size':(420, 120),
'editable':False,
},
{'type':'StaticBox',
'name':'queueBox',
'position':(10, 10),
'size':(430, 150),
'label':'Scripts in queue',
},
{'type':'StaticText',
'name':'clockTimer',
'position':(30, 350),
'text':'00:00:00',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Scripts queue and Status (Linux)',
'size':(450, 380),
'icon':'gui/img/ICONA.ico',
'backgroundColor':(192, 192, 192),
'components': [
{'type':'Button',
'name':'pauseScript',
'position':(278, 347),
'size':(50, 23),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'label':'Pause',
},
{'type':'Button',
'name':'startScript',
'position':(357, 347),
'size':(84, 23),
'enabled':False,
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'label':'Start scripts',
},
{'type':'TextArea',
'name':'ScriptStatusArea',
'position':(15, 309),
'size':(420, 22),
'editable':False,
},
{'type':'StaticBox',
'name':'SGstatusBox',
'position':(10, 290),
'size':(430, 50),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'label':'Script Status',
},
{'type':'TextArea',
'name':'repeatArea',
'position':(281, 250),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'nExpTXT',
'position':(162, 255),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'Number of Exposure',
},
{'type':'TextArea',
'name':'startnArea',
'position':(95, 250),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'startNTXT',
'position':(15, 255),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'StartNumber',
},
{'type':'CheckBox',
'name':'AutoDarkArea',
'position':(414, 188),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText8',
'position':(365, 193),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'AutoDark',
},
{'type':'TextArea',
'name':'fileArea',
'position':(95, 220),
'size':(322, 22),
'editable':False,
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'/',
},
{'type':'StaticText',
'name':'pathTXT',
'position':(15, 224),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'Path/Filename',
},
{'type':'CheckBox',
'name':'AutoFlatArea',
'position':(345, 188),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText6',
'position':(301, 193),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'AutoFlat',
},
{'type':'CheckBox',
'name':'GuideArea',
'position':(237, 188),
'enabled':False,
'label':' ',
},
{'type':'CheckBox',
'name':'WebArea',
'position':(280, 188),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText5',
'position':(258, 193),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'Web',
},
{'type':'StaticText',
'name':'guideTXT',
'position':(204, 193),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'Guide',
},
{'type':'TextArea',
'name':'BinArea',
'position':(170, 190),
'size':(30, 22),
'editable':False,
'text':'X',
},
{'type':'StaticText',
'name':'StaticText3',
'position':(150, 193),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'Bin',
},
{'type':'TextArea',
'name':'FilterArea',
'position':(116, 190),
'size':(30, 22),
'editable':False,
'text':'X',
},
{'type':'StaticText',
'name':'filterTXT',
'position':(88, 193),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'Filter',
},
{'type':'TextArea',
'name':'ExpArea',
'position':(40, 190),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'expTXT',
'position':(16, 193),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'Exp',
},
{'type':'StaticBox',
'name':'runningBox',
'position':(10, 170),
'size':(430, 110),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'label':'Script Running',
},
{'type':'TextArea',
'name':'queue_scripts',
'position':(15, 30),
'size':(420, 120),
'editable':False,
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
},
{'type':'StaticBox',
'name':'queueBox',
'position':(10, 10),
'size':(430, 150),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'label':'Scripts in queue',
},
{'type':'StaticText',
'name':'clockTimer',
'position':(30, 350),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'00:00:00',
},
] # end components
} # end background
] # end backgrounds
} }
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Scripts queue and Status',
'size':(457, 435),
'icon':'gui/img/ICONA.ico',
'backgroundColor':(192, 192, 192),
'style':['resizeable'],
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
]
},
]
},
'components': [
{'type':'Button',
'name':'pauseScript',
'position':(278, 347),
'size':(-1, 23),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Pause',
},
{'type':'Button',
'name':'startScript',
'position':(357, 347),
'size':(84, 23),
'enabled':False,
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Start scripts',
},
{'type':'TextArea',
'name':'ScriptStatusArea',
'position':(15, 309),
'size':(420, 22),
'editable':False,
},
{'type':'StaticBox',
'name':'SGstatusBox',
'position':(10, 290),
'size':(430, 50),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Script Status',
},
{'type':'TextArea',
'name':'repeatArea',
'position':(281, 249),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'nExpTXT',
'position':(162, 252),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Number of Exposure',
},
{'type':'TextArea',
'name':'startnArea',
'position':(95, 250),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'startNTXT',
'position':(15, 253),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'StartNumber',
},
{'type':'CheckBox',
'name':'AutoDarkArea',
'position':(390, 223),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText8',
'position':(334, 223),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'AutoDark',
},
{'type':'TextArea',
'name':'fileArea',
'position':(95, 220),
'size':(231, 22),
'editable':False,
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 8},
'text':'/',
},
{'type':'StaticText',
'name':'pathTXT',
'position':(15, 224),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Path/Filename',
},
{'type':'CheckBox',
'name':'AutoFlatArea',
'position':(390, 193),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText6',
'position':(340, 193),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'AutoFlat',
},
{'type':'CheckBox',
'name':'GuideArea',
'position':(255, 193),
'enabled':False,
'label':' ',
},
{'type':'CheckBox',
'name':'WebArea',
'position':(311, 193),
'enabled':False,
'label':' ',
},
{'type':'StaticText',
'name':'StaticText5',
'position':(283, 193),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Web',
},
{'type':'StaticText',
'name':'guideTXT',
'position':(219, 193),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Guide',
},
{'type':'TextArea',
'name':'BinArea',
'position':(182, 190),
'size':(30, 22),
'editable':False,
'text':'X',
},
{'type':'StaticText',
'name':'StaticText3',
'position':(161, 193),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Bin',
},
{'type':'TextArea',
'name':'FilterArea',
'position':(126, 190),
'size':(30, 22),
'editable':False,
'text':'X',
},
{'type':'StaticText',
'name':'filterTXT',
'position':(95, 193),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Filter',
},
{'type':'TextArea',
'name':'ExpArea',
'position':(40, 190),
'size':(45, 22),
'editable':False,
'text':'000',
},
{'type':'StaticText',
'name':'expTXT',
'position':(16, 193),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'text':'Exp',
},
{'type':'StaticBox',
'name':'runningBox',
'position':(10, 170),
'size':(430, 110),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Script Running',
},
{'type':'TextArea',
'name':'queue_scripts',
'position':(15, 30),
'size':(420, 120),
'editable':False,
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 8},
},
{'type':'StaticBox',
'name':'queueBox',
'position':(10, 10),
'size':(430, 150),
'font':{'style': 'bold', 'faceName': u'Arial', 'family': 'sansSerif', 'size': 8},
'label':'Scripts in queue',
},
{'type':'StaticText',
'name':'clockTimer',
'position':(30, 350),
'font':{'faceName': u'Arial', 'family': 'ArialSerif', 'size': 8},
'text':'00:00:00',
},
] # end components
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, dialog, timer
import os, wx
from skylive import protocol, config
import downprog
import time
from zipfile import ZipFile as zip
from skylive.lang import language
class Scriptsgui(model.Background):
def on_initialize(self, event):
self.initialized=False
self.verifyFree=False
self._parent = self.getParent()
self.teleOn = self._parent.teleOn
self.writeStatus("Initializing....")
self.lang = self._parent.lang
self.gui = 'scriptsgui'
self.ItemText = language.getItemText
self.setGui()
self.srvproto = self._parent.srvproto
self.telescopeOk = False
self.actionRequest = False
self.usrid = config.getUsername()
self.usrpsw = config.getPassword()
self.seqNum = 0
self.fileNum = 0
self.freeCount = 0
self.demultiCount = 0
self.scriptSep = self._parent.scriptSep
self.eventTimerStart()
self.initialized=True
self.setTeleLinkStatus(self._parent.teleOn)
self.goNextScript()
self.PhotoRunning = False
def eventTimerStart(self):
self.eventTimer = timer.Timer(self.components.clockTimer, -1)
self.eventTimer.Start(100)
self.eventTimerRunning = True
def eventTimerStop(self):
try:
self.eventTimer.Stop()
self.eventTimerRunning = False
del self.eventTimer
self.eventTimer = False
except:
pass
def on_close(self, event):
if self.actionRequest:
resultQuestion = dialog.messageDialog(self, self.getText('scriptExitWarning1'), self.getText('scriptExitWarning2'))
if resultQuestion.accepted:
self._parent.components.TScopeCombo.enabled = True
self.actionRequest = False
self._parent.scriptguiStarted = False
event.skip()
else:
self._parent.components.TScopeCombo.enabled = True
self._parent.scriptguiStarted = False
event.skip()
def on_callback(self, cmd):
for key in cmd:
f=getattr(self, 'on_'+key, None)
if f and callable(f):
f(cmd[key])
def updateQueue(self):
if self.scripts:
self.components.queue_scripts.text=""
for script in self.scripts:
getactionscript = script.split(self.scriptSep)
if getactionscript[1] == "PHOTO":
self.components.queue_scripts.appendText(script+"_XXX.fit\n")
elif getactionscript[1] == "GOTO":
self.components.queue_scripts.appendText(script+"\n")
else:
dialog.alertdialog(self.getText('scriptWarning1'))
self.close()
def writeStatus(self, statusTxt=""):
self.components.ScriptStatusArea.text = statusTxt
def resetInfoScript(self):
self.components.ExpArea.text="000"
self.components.FilterArea.text="X"
self.components.BinArea.text="X"
self.components.fileArea.text="/"
self.components.startnArea.text="0"
self.components.repeatArea.text="0"
self.writeStatus(self.getText('scriptStatus1'))
self.components.GuideArea.checked=False
self.components.WebArea.checked=False
self.components.AutoDarkArea.checked=False
self.components.AutoFlatArea.checked=False
def extractDataScript(self):
if self.scripts:
self.paramScript = {}
self.scriptData = self.scripts[0].split(self.scriptSep)
if self.scriptData[1] == "PHOTO":
self.paramScript = {"type":self.scriptData[1],
"exp":self.scriptData[2],
"filt":self.scriptData[3],
"guide":self.scriptData[4],
"aflat":self.scriptData[5],
"adark":self.scriptData[6],
"web":self.scriptData[7],
"bin":self.scriptData[9],
"startn":self.scriptData[10],
"repeat":self.scriptData[11],
"path":self.scriptData[12]
}
elif self.scriptData[1] =="GOTO":
self.paramScript = {"type":self.scriptData[1],
"cmd":self.scriptData[2]
}
def updateInfoScript(self):
self.extractDataScript()
if self.paramScript["type"] == "PHOTO":
self.components.ExpArea.text=self.paramScript["exp"]
self.components.FilterArea.text=self.paramScript["filt"]
self.components.BinArea.text=self.paramScript["bin"]
self.components.fileArea.text=self.paramScript["path"]+"_XXX.fit"
self.components.startnArea.text=self.paramScript["startn"]
self.components.repeatArea.text=self.paramScript["repeat"]
if self.paramScript["guide"] == "1":
self.components.GuideArea.checked=True
if self.paramScript["aflat"] == "1":
self.components.AutoFlatArea.checked=True
if self.paramScript["adark"] == "1":
self.components.AutoDarkArea.checked=True
if self.paramScript["web"] == "1":
self.components.WebArea.checked=True
def goNextScript(self):
self.resetInfoScript()
self.updateQueue()
self.updateInfoScript()
self._parent.updateScript()
def endScript(self):
self.resetInfoScript()
self.writeStatus(self.getText('scriptStatus2'))
self.components.queue_scripts.text=self.getText('scriptStatus3')
self._parent.updateScript()
self.actionRequest = False
self.components.startScript.enabled = False
self.eventTimerStop()
def scriptDone(self):
if self.scripts:
self.scripts.remove(self.scripts[0])
if self.scripts:
self.goNextScript()
else:
self.endScript()
def makeaPhoto(self):
self.seqNum = 99
photostring = self.srvproto.makePhoto(exp=self.paramScript["exp"], filter=self.paramScript["filt"], guide=self.paramScript["guide"], bin=self.paramScript["bin"], aflat=self.paramScript["aflat"], adark=self.paramScript["adark"], web=self.paramScript["web"])
if photostring:
self._parent.TwistedLoop.sendNetworkData(photostring)
self.expNumber = self.expNumber + 1
self.PhotoRunning = True
self.seqNum = 1
def runPhotoScript(self):
self.seqNum = 99
self.numExps = int(self.paramScript["repeat"])
if self.expNumber < self.numExps:
if self.actionRequest and self.telescopeOk:
self.seqNum = 0
else:
self.seqNum = 0
self.scriptDone()
self.startRunScript()
def on_scriptFitsDownloaded(self, fits):
self.seqNum = 99
repeatedFile = False
numRepeatedFile = 0
numForRep = -1
fileFounded = False
isNum = False
savingDir, savingFile =os.path.split(self.pathNewFit)
extSF = os.path.splitext(savingFile)[1]
fileNameToSave = savingFile
#
# This part used to find a filename not already present
# in the savingDir need to be rewritten in a better way.
# If we walk in a very BIG directory, this way of doing things
# can be very SLOW. It is better to use a stat() call or something
# like os.path.isfile() generating something like
# filename+sequenceNum+'.fit' and checking if a file with this name
# exists or not, and if exist increment of 1 the sequenceNum and
# retrying, so, we don't need to walk over all files in the directory.
#
for files in os.listdir(savingDir):
filename, ext = os.path.splitext(files)
if '(' and ')' in filename[-4:]:
startRead = False
numRep = ''
for ch in filename:
if ch == '(':
startRead = True
else:
if startRead and ch != ')':
numRep = numRep+ch
elif startRead and ch == ')':
startRead = False
try:
numRepeatedFile = int(numRep)
isNum = True
except:
isNum = False
repeatedFile = False
if isNum:
repText = '('+str(numRepeatedFile)+')'
filenameWOrep = filename.replace(repText, '')
if filenameWOrep == os.path.splitext(savingFile)[0]:
repeatedFile = True
if numRepeatedFile > numForRep:
numForRep = numRepeatedFile
fileNameToSave = filenameWOrep+'('+str(numForRep+1)+')'+extSF
else:
if filename == os.path.splitext(savingFile)[0] and not repeatedFile:
fileNameToSave = filename+'(1)'+extSF
break
else:
if not repeatedFile:
fileNameToSave = savingFile
toSave = os.path.normpath(savingDir+'/'+fileNameToSave)
readFile = zip(fits, 'r')
fitsData = readFile.read("SkyFrame.fit")
readFile.close()
savedFile = open(toSave, 'wb')
savedFile.write(fitsData)
savedFile.close()
self.fileNum = self.fileNum + 1
self.seqNum = 5
def photoSave(self, fitname, fitnumber):
self.seqNum = 99
if self.components.WebArea.checked:
self._parent.TwistedLoop.scriptGetFitFile(self._parent.telescopesel)
self.pathNewFit = os.path.normpath(fitname+"_"+str(fitnumber).zfill(3)+".fit")
self.writeStatus("Saving "+self.pathNewFit)
self.seqNum = 4
else:
self.writeStatus(self.getText('scriptStatus10'))
self.seqNum = 5
def runGotoScript(self):
if self.actionRequest and self.telescopeOk:
self.seqNum = 0
def sendGotocmd(self):
self.seqNum = 99
pointstring = self.usrid+"#^#"+self.usrpsw+"#^#"+"COMANDO#^#"+self.paramScript["cmd"]+"#^#NULL"
self._parent.TwistedLoop.sendNetworkData(pointstring)
self.seqNum = 1
def startRunScript(self):
if self.scripts:
if self.paramScript["type"] == "PHOTO":
self.expNumber = 0
self.fileNum = int(self.paramScript["startn"])
self.runPhotoScript()
if self.paramScript["type"] == "GOTO":
self.runGotoScript()
else:
self.actionRequest = False
self._parent.components.TScopeCombo.enabled = True
def on_pauseScript_mouseClick(self, event):
if self.eventTimerRunning:
self.eventTimerStop()
self.components.clockTimer.text = self.getText('stoppedScript')
self.components.pauseScript.label = self.getText('restartScript')
else:
self.eventTimerStart()
self.components.pauseScript.label = self.getText('pauseScript')
event.skip()
def on_startScript_mouseClick(self, event):
self.actionRequest = True
self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendTeleStatus())
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.title = self.getText('title')
self.components.pauseScript.label = self.getText('pauseScript')
self.components.startScript.label = self.getText('startScript')
self.components.SGstatusBox.label = self.getText('SGstatusBox')
self.components.nExpTXT.text = self.getText('nExpTXT')
self.components.pathTXT.text = self.getText('pathTXT')
self.components.guideTXT.text = self.getText('guideTXT')
self.components.filterTXT.text = self.getText('filterTXT')
self.components.expTXT.text = self.getText('expTXT')
self.components.startNTXT.text = self.getText('startNTXT')
self.components.runningBox.label = self.getText('runningBox')
self.components.queueBox.label = self.getText('queueBox')
def enableAll(self, msg):
self.components.startScript.enabled = True
self.writeStatus(msg)
def disableAll(self, msg):
self.components.startScript.enabled = False
self.writeStatus(msg)
def setTeleLinkStatus(self, status):
if status:
if self._parent.domeisopen:
self.enableAll(self.getText('telestatus1'))
else:
self.disableAll(self.getText('telestatus2'))
else:
if self._parent.domeisopen:
self.disableAll(self.getText('telestatus3'))
else:
self.disableAll(self.getText('telestatus4'))
self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendTeleStatus())
def on_TeleLink(self, stat):
if stat == 'TeleON':
self.setTeleLinkStatus(True)
self.teleOn = True
elif stat =='TeleOFF':
self.setTeleLinkStatus(False)
self.teleOn = False
self.telescopeOk = False
def on_TeleStatus(self, stat):
if stat == 'Busy' and self.teleOn and not self.actionRequest:
self.telescopeOk = False
self.disableAll(self.getText('telestatus5')) #tele occupato
self.startVerifyFree()
elif stat == 'Free' and self.teleOn and not self.actionRequest:
self.enableAll(self.getText('telestatus6'))
if self.verifyFree:
self.verifyFree=False
elif stat == 'Free' and self.teleOn and self.actionRequest and not self.seqNum == 1:
self.disableAll(self.getText('telestatus7'))
self.telescopeOk = True
self.startRunScript()
elif stat == 'Busy' and not self.teleOn:
self.telescopeOk = False
self.disableAll(self.getText('telestatus4'))
elif stat == 'Busy' and self.paramScript["type"] == "GOTO" and self.seqNum == 1:
self.freeCount = 0
self.writeStatus(self.getText('telestatus8'))
elif stat == 'Free' and self.paramScript["type"] == "GOTO" and self.seqNum == 1:
self.writeStatus(self.getText('telestatus9'))
self.freeCount += 1
if self.freeCount == 11:
self.scriptDone()
self.startRunScript()
def on_clockTimer_timer(self, event):
self.components.clockTimer.text = time.strftime('%H:%M:%S')
self.timedEvent()
event.skip()
def timedEvent(self):
if self.demultiCount == 0:
self.demultiCount = 1
now=time.time()
try:
if self.telescopeOk:
if self.actionRequest and self.paramScript["type"] == "PHOTO":
if self.seqNum == 0:
self.makeaPhoto()
if self.seqNum == 1:
self.writeStatus(self.getText('scriptStatus7a')+str(self.expNumber)+self.getText('scriptStatus7b')+str(self.numExps))
self.seqNum = 99
if self.seqNum == 2:
self.writeStatus(self.getText('scriptStatus8'))
self.seqNum = 99
if self.seqNum == 3:
self.photoSave(self.paramScript["path"], self.fileNum)
if self.seqNum == 5:
self.runPhotoScript()
if self.actionRequest and self.paramScript["type"] == "GOTO":
if self.seqNum == 0:
self.sendGotocmd()
if self.seqNum == 1:
self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendTeleStatus())
if self.verifyFree:
if self.countVF < self.limitVF:
self.countVF += 1
else:
self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendTeleStatus())
self.countVF = 0
if self.PhotoRunning:
self._parent.TwistedLoop.sendNetworkData(self.srvproto.sendPhotoRunning(self.actualtel))
except:
pass
elif self.demultiCount in range (1, 10):
self.demultiCount += 1
if self.demultiCount == 10:
self.demultiCount = 0
def on_photoStatus(self, stat):
if self.actionRequest:
if stat == 'notReady':
self.seqNum = 2
elif stat == 'Ready':
self.PhotoRunning = False
self.seqNum = 3
def startVerifyFree(self):
self.verifyFree=True
self.countVF = 0
self.limitVF = 6
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, dialog
from skylive import config
from skylive.lang import language
import platform
class Extras(model.PageBackground):
def on_initialize(self, event):
self.faketext = 'useARDEC'
self.inditext = 'useINDI'
self.lang = self._parent.lang
self.forcedLowRes = self._parent.forcedLowRes
self.gui = 'extra'
self.ItemText = language.getItemText
self.setGui()
self.useExtProgram = self._parent.useExtProgram
self.useINDIProgram = self._parent.useINDIProgram
self.enableStream = self._parent.enableStream
self.askStream = self._parent.askStream
self.enableARDECCheck()
self.enableINDICheck()
self.enableStreamCheck()
self.askStreamCheck()
if self.forcedLowRes:
self.components.forceLowRes.checked = True
def enableStreamCheck(self):
if self.enableStream in ['True', 'yes', 'y', 'Yes', '1']:
self.components.enableStream.checked = True
def askStreamCheck(self):
if self.askStream == ['True', 'yes', 'y', 'Yes', '1']:
self.components.askStream.checked = True
def enableARDECCheck(self):
if platform.system() == "Microsoft" or platform.system() == "Windows":
self.components.useARDEC.enabled = True
self.components.useARDEC.visible = True
if self.useExtProgram == ['True', 'yes', 'y', 'Yes', '1']:
self.components.useARDEC.checked = True
def enableINDICheck(self):
self.components.useINDI.enabled = True
if self.useINDIProgram == ['True', 'yes', 'y', 'Yes', '1']:
self.components.useINDI.checked = True
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.components.useARDEC.label = self.getText(self.faketext)
self.components.useINDI.label = self.getText(self.inditext)
self.components.closeButton.label = self.getText('closeButton')
self.components.defaultButton.label = self.getText('defaultButton')
self.components.applyButton.label = self.getText('applyButton')
self.components.extraBox.label = self.getText('extraBox')
self.components.enableStream.label = self.getText('enableStream')
self.components.askStream.label = self.getText('askStream')
def on_applyButton_mouseClick(self, event=None):
if self.components.useARDEC.checked:
config.put_extProgram('True')
self._parent.useExtProgram = 'True'
self._parent.startFake()
else:
config.put_extProgram('False')
self._parent.useExtProgram = 'False'
self._parent.stopFake()
if self.components.useINDI.checked:
config.put_extINDIProgram('True')
self._parent.useINDIProgram = 'True'
self._parent.startINDI()
else:
config.put_extINDIProgram('False')
self._parent.useINDIProgram = 'False'
self._parent.stopINDI()
config.put_streamingPref(self.components.enableStream.checked, self.components.askStream.checked)
self._parent.askStream = str(self.components.askStream.checked)
self._parent.enableStream = str(self.components.enableStream.checked)
oldres = self._parent.forcedLowRes
newres = self.components.forceLowRes.checked
if oldres != newres:
config.put_lowResPref(newres)
self._parent.forcedLowRes = newres
# TODO: change resolution at runtime!
dialog.alertDialog(self, 'Please restart program to take effect')
def on_defaultButton_mouseClick(self, event):
self.components.useARDEC.checked = False
self.components.useINDI.checked = False
self.components.forceLowRes.checked = False
self.on_applyButton_mouseClick()
def on_closeButton_mouseClick(self, event):
self.parent.close()
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':'Extras',
'components': [
{'type':'StaticBox',
'name':'extraBox',
'position':(10, 10),
'size':(370, 180),
'label':u'Extras',
},
{'type':'CheckBox',
'name':'useINDI',
'position':(20, 30),
'enabled':False,
'label':u'Use Compatibility whit INDI Driver ',
},
{'type':'CheckBox',
'name':'forceLowRes',
'position':(20, 50),
'enabled':True,
'label':u'Force gui to low Resolution (eg. for a subnotebook)',
},
{'type':'CheckBox',
'name':'useARDEC',
'position':(20, 70),
'enabled':False,
'label':u'Use Compatibility whit LX200 fake driver (Windows Only)',
'visible': False
},
{'type':'CheckBox',
'name':'enableStream',
'position':(20, 90),
'enabled':True,
'label':u'Enable Streaming support',
'visible': True
},
{'type':'CheckBox',
'name':'askStream',
'position':(20, 110),
'enabled':True,
'label':u'Ask before open a stream',
'visible':True
},
{'type':'Button',
'name':'closeButton',
'position':(170, 150),
'size':(-1, 25),
'label':u'Close',
},
{'type':'Button',
'name':'defaultButton',
'position':(90, 150),
'size':(-1, 25),
'label':u'Default',
},
{'type':'Button',
'name':'applyButton',
'position':(20, 150),
'size':(-1, 25),
'label':u'Apply',
},
] # end components
} # end background
] # end backgrounds
} }
from Pycard import model, dialog
from skylive import config
from skylive.lang import language
import platform
class Langs(model.PageBackground):
def on_initialize(self, event):
self.lang = self._parent.lang
self.gui = 'langs'
self.langsList = {'en':'English', 'it':'Italiano'}
self.ItemText = language.getItemText
self.setGui()
self.setComboLangs()
def setComboLangs(self):
for l in self.langsList.values():
self.components.langsAvaiable.append(l)
self.components.langsAvaiable.text = self.langsList[self.lang]
def on_langsAvaiable_select(self, event):
for l in self.langsList.keys():
if self.langsList[l] == self.components.langsAvaiable.text:
self.selectedLanguage = l
break
else:
pass
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.components.langsAvaiableTXT.text = self.getText('langsAvaiableTXT')
self.components.closeButton.label = self.getText('closeButton')
self.components.defaultButton.label = self.getText('defaultButton')
self.components.applyButton.label = self.getText('applyButton')
self.components.langsBox.label = self.getText('langsBox')
def on_applyButton_mouseClick(self, event):
config.put_usrLang(self.selectedLanguage)
self.lang = self.selectedLanguage
self._parent.lang = self.lang
self.setGui()
self._parent.setGui()
def on_defaultButton_mouseClick(self, event):
config.put_usrLang('en')
self.lang = 'en'
self._parent.lang = self.lang
self.setGui()
self._parent.setGui()
def on_closeButton_mouseClick(self, event):
self.parent.close()
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':'Langs',
'components': [
{'type':'StaticBox',
'name':'langsBox',
'position':(10, 10),
'size':(370, 180),
'label':u'Languages',
},
{'type':'StaticText',
'name':'langsAvaiableTXT',
'position':(20, 42),
'text':u'Avaiable Languages:',
},
{'type':'ComboBox',
'name':'langsAvaiable',
'position':(160, 40),
'size':(140, 25),
'text':u'Select',
},
{'type':'Button',
'name':'closeButton',
'position':(170, 150),
'size':(-1, 25),
'label':u'Close',
},
{'type':'Button',
'name':'defaultButton',
'position':(90, 150),
'size':(-1, 25),
'label':u'Default',
},
{'type':'Button',
'name':'applyButton',
'position':(20, 150),
'size':(-1, 25),
'label':u'Apply',
},
] # end components
} # end background
] # end backgrounds
} }
from Pycard import model, dialog
from skylive import config
from skylive.lang import language
class Pointer(model.PageBackground):
def on_initialize(self, event):
self.lang = self._parent.lang
self.gui = 'pointer'
self.ItemText = language.getItemText
self.setGui()
self.currentColorPointer = self._parent.defaultPointerColor
self.setPointerColorTest(self._parent.defaultPointerColor)
#start color pointer section
def setPointerColorTest(self, color='#FF7700'):
self.components.testColor.backgroundColor = color
self.PointerColorSelected = color
def on_colorButton_mouseClick(self, event):
result = dialog.colorDialog(self)
if result.accepted:
color = self.RGBToHTMLColor(result.color)
self.setPointerColorTest(color)
def on_applyColorButton_mouseClick(self, event):
self._parent.defaultPointerColor = self.PointerColorSelected
config.put_usrPointerColor(self.PointerColorSelected)
def on_defaultColorButton_mouseClick(self, event):
self.setPointerColorTest()
def RGBToHTMLColor(self, rgb_tuple):
hexcolor = '#%02x%02x%02x' % rgb_tuple
return hexcolor
def on_closeButton_mouseClick(self, event):
self.parent.close()
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.components.colorButton.label = self.getText('colorButton')
self.components.color.text = self.getText('color')
self.components.pointerBox.label = self.getText('pointerBox')
self.components.defaultColorButton.label = self.getText('defaultColorButton')
self.components.applyColorButton.label = self.getText('applyColorButton')
self.components.closeButton.label = self.getText('closeButton')
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':'pointer',
'components': [
{'type':'StaticBox',
'name':'pointerBox',
'position':(10, 10),
'size':(370, 180),
'label':u'Pointer Preference',
},
{'type':'StaticText',
'name':'color',
'position':(20, 30),
'text':u'Live Pointer Color:',
},
{'type':'TextField',
'name':'testColor',
'position':(150, 25),
'size':(25, 25),
'editable':False,
'border':'none',
},
{'type':'Button',
'name':'colorButton',
'position':(190, 25),
'size':(-1, 25),
'label':u'Select',
},
{'type':'Button',
'name':'closeButton',
'position':(170, 150),
'size':(-1, 25),
'label':u'Close',
},
{'type':'Button',
'name':'defaultColorButton',
'position':(90, 150),
'size':(-1, 25),
'label':u'Default',
},
{'type':'Button',
'name':'applyColorButton',
'position':(20, 150),
'size':(-1, 25),
'label':u'Apply',
},
] # end components
} # end background
] # end backgrounds
} }
#!/usr/bin/env python
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import dialog, model
from Pycard.twistedsupport import twistedModel
from twisted.internet import reactor
import urllib2
from skylive import config
from skylive.lang import language
class DumbProxyAuthMgr:
def __init__(self):
self.user = self.passwd = None
def add_password(self, realm, uri, user, passwd):
self.user = user
self.passwd = passwd
def find_user_password(self, realm, authuri):
return self.user, self.passwd
# XXX Unire le due in una sola classe e agire su due derivate!!!
class proxyConf(model.PageBackground):
def on_initialize(self, event):
self.resetCfg()
self.proxyEnabled = False
self.proxyCfg = config.get_usrProxy()
self.checkStatus()
def checkStatus(self):
if self.proxyCfg['useProxy'] == "yes":
self.proxyEnabled = True
self.components.modifyButton.enabled = True
self.components.CheckBoxUseProxy.checked = True
self.components.CheckBoxUseProxy.enabled = False
self.showProxyCfg()
else:
self.proxyEnabled = False
self.components.modifyButton.enabled = True
self.components.CheckBoxUseProxy.checked = False
self.components.CheckBoxUseProxy.enabled = True
self.showProxyCfg()
def on_close(self, event):
event.skip()
def resetCfg(self):
self.components.proxyurl.text = ''
self.components.proxyport.text = ''
self.components.proxyuser.text = ''
self.components.proxypsw.text = ''
self.components.CheckBoxUseProxy.checked = False
def showProxyCfg(self):
self.components.proxyurl.text = self.proxyCfg['proxyUrl']
self.components.proxyport.text = str(self.proxyCfg['proxyPort'])
self.components.proxyuser.text = self.proxyCfg['proxyUsrName']
self.components.proxypsw.text = self.proxyCfg['proxyUsrPsw']
def on_CheckBoxUseProxy_mouseClick(self, event):
if self.components.CheckBoxUseProxy.checked:
if self.proxyEnabled:
self.components.modifyButton.enabled = True
self.components.cleanButton.enabled = True
self.useProxy = "yes"
else:
self.useProxy = "no"
self.enableCfg()
else:
if self.proxyEnabled:
self.useProxy = "no"
self.components.applyButton.enabled = True
else:
self.disableCfg()
self.useProxy = "no"
def enableCfg(self):
self.components.proxyurl.enabled = True
self.components.proxyport.enabled = True
self.components.proxyuser.enabled = True
self.components.proxypsw.enabled = True
self.components.proxytest.enabled = True
self.components.proxyurltxt.enabled = True
self.components.proxyporttxt.enabled = True
self.components.proxyusertxt.enabled = True
self.components.proxypswtxt.enabled = True
def disableCfg(self):
self.components.proxyurl.enabled = False
self.components.proxyport.enabled = False
self.components.proxyuser.enabled = False
self.components.proxypsw.enabled = False
self.components.proxytest.enabled = False
self.components.proxyurltxt.enabled = False
self.components.proxyporttxt.enabled = False
self.components.proxyusertxt.enabled = False
self.components.proxypswtxt.enabled = False
def doProxyTest(self, *args):
ret = False
authinfo = urllib2.ProxyBasicAuthHandler(DumbProxyAuthMgr())
authinfo.add_password(None, None, args[0]['proxyUsrName'], args[0]['proxyUsrPsw'])
proxy_url = "http://"+args[0]['proxyUrl']+":"+str(args[0]['proxyPort'])
proxy_support = urllib2.ProxyHandler({"http" : proxy_url})
# build a new opener that adds authentication and caching FTP handlers
opener = urllib2.build_opener(proxy_support, authinfo, urllib2.CacheFTPHandler)
# install it
urllib2.install_opener(opener)
# test it
uri = "http://www.skylive.it/skylive-new/immagini/sandro.jpg"
try:
test = urllib2.urlopen(uri)
ret = True
except urllib2.URLError:
ret = False
return ret
def allFields(self):
ret = False
if self.components.CheckBoxUseProxy.checked:
useProxy = "yes"
else:
useProxy = "no"
proxyUrl = self.components.proxyurl.text.replace(' ', '')
proxyPort = self.components.proxyport.text.replace(' ', '')
proxyUsrName = self.components.proxyuser.text
proxyUsrPsw = self.components.proxypsw.text
if proxyUrl != '' and proxyPort != '':
if proxyUsrName.replace(' ', '') == '':
proxyUsrName = ''
if proxyUsrPsw.replace(' ', '') == '':
proxyUsrPsw = ''
ret = {'useProxy' : useProxy, 'proxyUrl' : proxyUrl, 'proxyPort' : proxyPort,
'proxyUsrName' : proxyUsrName, 'proxyUsrPsw' : proxyUsrPsw}
else:
dialog.alertDialog(self, "Please fill all Fields and retry")
ret = False
return ret
def on_proxytest_mouseClick(self, event):
if self.allFields():
if self.doProxyTest(self.allFields()):
self.useProxy = "yes"
dialog.alertDialog(self, "Configuration successifull tested! Now you can store it")
self.disableCfg()
self.components.modifyButton.enabled = True
self.components.applyButton.enabled = True
else:
self.useProxy = "no"
self.components.applyButton.enabled = False
dialog.alertDialog(self, "Configuration Error, Please check it and retry")
def applyedCfg(self):
if self.components.CheckBoxUseProxy.checked:
useProxy = "yes"
else:
useProxy = "no"
proxyUrl = self.components.proxyurl.text.replace(' ', '')
proxyPort = self.components.proxyport.text.replace(' ', '')
proxyUsrName = self.components.proxyuser.text
proxyUsrPsw = self.components.proxypsw.text
if proxyUsrName.replace(' ', '') == '':
proxyUsrName = ''
if proxyUsrPsw.replace(' ', '') == '':
proxyUsrPsw = ''
if len(proxyUsrName) > 0 and len(proxyUsrPsw) > 0:
proxyuseauth = 'yes'
else:
proxyuseauth = 'no'
ret = {'useProxy' : useProxy, 'proxyUrl' : proxyUrl, 'proxyPort' : proxyPort,
'proxyUsrName' : proxyUsrName, 'proxyUsrPsw' : proxyUsrPsw, 'proxyAuth': proxyuseauth}
return ret
def on_applyButton_mouseClick(self, event):
config.put_usrProxy(self.applyedCfg())
self.components.applyButton.enabled = False
self.components.proxytest.enabled = False
self.disableCfg()
if self.proxyEnabled:
self.components.modifyButton.enabled = True
self.components.cleanButton.enabled = True
self._parent.TwistedLoop.serverReconnect()
def on_modifyButton_mouseClick(self, event):
self.enableCfg()
self.components.modifyButton.enabled = False
self.components.proxytest.enabled = True
self.components.cleanButton.enabled = True
self.components.CheckBoxUseProxy.enabled = True
def on_cleanButton_mouseClick(self, event):
self.resetCfg()
config.put_usrProxy(self.applyedCfg())
self.components.proxytest.enabled = True
self.components.applyButton.enabled = False
self.disableCfg()
self.components.cleanButton.enabled = False
class proxyConf2(model.Background):
def on_initialize(self, event):
self.resetCfg()
self.proxyEnabled = False
self.proxyCfg = config.get_usrProxy()
self.checkStatus()
def checkStatus(self):
if self.proxyCfg['useProxy'] == "yes":
self.proxyEnabled = True
self.components.modifyButton.enabled = True
self.components.CheckBoxUseProxy.checked = True
self.components.CheckBoxUseProxy.enabled = False
self.showProxyCfg()
else:
self.proxyEnabled = False
self.components.modifyButton.enabled = True
self.components.CheckBoxUseProxy.checked = False
self.components.CheckBoxUseProxy.enabled = True
self.showProxyCfg()
def on_close(self, event):
event.skip()
def resetCfg(self):
self.components.proxyurl.text = ''
self.components.proxyport.text = ''
self.components.proxyuser.text = ''
self.components.proxypsw.text = ''
self.components.CheckBoxUseProxy.checked = False
def showProxyCfg(self):
self.components.proxyurl.text = self.proxyCfg['proxyUrl']
self.components.proxyport.text = str(self.proxyCfg['proxyPort'])
self.components.proxyuser.text = self.proxyCfg['proxyUsrName']
self.components.proxypsw.text = self.proxyCfg['proxyUsrPsw']
def on_CheckBoxUseProxy_mouseClick(self, event):
if self.components.CheckBoxUseProxy.checked:
if self.proxyEnabled:
self.components.modifyButton.enabled = True
self.components.cleanButton.enabled = True
self.useProxy = "yes"
else:
self.useProxy = "no"
self.enableCfg()
else:
if self.proxyEnabled:
self.useProxy = "no"
self.components.applyButton.enabled = True
else:
self.disableCfg()
self.useProxy = "no"
def enableCfg(self):
self.components.proxyurl.enabled = True
self.components.proxyport.enabled = True
self.components.proxyuser.enabled = True
self.components.proxypsw.enabled = True
self.components.proxytest.enabled = True
self.components.proxyurltxt.enabled = True
self.components.proxyporttxt.enabled = True
self.components.proxyusertxt.enabled = True
self.components.proxypswtxt.enabled = True
def disableCfg(self):
self.components.proxyurl.enabled = False
self.components.proxyport.enabled = False
self.components.proxyuser.enabled = False
self.components.proxypsw.enabled = False
self.components.proxytest.enabled = False
self.components.proxyurltxt.enabled = False
self.components.proxyporttxt.enabled = False
self.components.proxyusertxt.enabled = False
self.components.proxypswtxt.enabled = False
def doProxyTest(self, *args):
ret = False
# set up authentication info
authinfo = urllib2.ProxyBasicAuthHandler(DumbProxyAuthMgr())
authinfo.add_password(None, None, args[0]['proxyUsrName'], args[0]['proxyUsrPsw'])
proxy_url = "http://"+args[0]['proxyUrl']+":"+str(args[0]['proxyPort'])
proxy_support = urllib2.ProxyHandler({"http" : proxy_url})
# build a new opener that adds authentication and caching FTP handlers
opener = urllib2.build_opener(proxy_support, authinfo, urllib2.CacheFTPHandler)
# install it
urllib2.install_opener(opener)
# test it
uri = "http://www.skylive.it/skylive-new/immagini/sandro.jpg"
try:
test = urllib2.urlopen(uri)
ret = True
except urllib2.URLError:
ret = False
return ret
def allFields(self):
ret = False
if self.components.CheckBoxUseProxy.checked:
useProxy = "yes"
else:
useProxy = "no"
proxyUrl = self.components.proxyurl.text.replace(' ', '')
proxyPort = self.components.proxyport.text.replace(' ', '')
proxyUsrName = self.components.proxyuser.text
proxyUsrPsw = self.components.proxypsw.text
if proxyUrl != '' and proxyPort != '':
if proxyUsrName.replace(' ', '') == '':
proxyUsrName = ''
if proxyUsrPsw.replace(' ', '') == '':
proxyUsrPsw = ''
ret = {'useProxy' : useProxy, 'proxyUrl' : proxyUrl, 'proxyPort' : proxyPort,
'proxyUsrName' : proxyUsrName, 'proxyUsrPsw' : proxyUsrPsw}
else:
dialog.alertDialog(self, "Please fill all Fields and retry")
ret = False
return ret
def on_proxytest_mouseClick(self, event):
if self.allFields():
if self.doProxyTest(self.allFields()):
self.useProxy = "yes"
dialog.alertDialog(self, "Configuration successifull tested! Now you can store it")
self.disableCfg()
self.components.modifyButton.enabled = True
self.components.applyButton.enabled = True
else:
self.useProxy = "no"
self.components.applyButton.enabled = False
dialog.alertDialog(self, "Configuration Error, Please check it and retry")
def applyedCfg(self):
if self.components.CheckBoxUseProxy.checked:
useProxy = "yes"
else:
useProxy = "no"
proxyUrl = self.components.proxyurl.text.replace(' ', '')
proxyPort = self.components.proxyport.text.replace(' ', '')
proxyUsrName = self.components.proxyuser.text
proxyUsrPsw = self.components.proxypsw.text
if proxyUsrName.replace(' ', '') == '':
proxyUsrName = ''
if proxyUsrPsw.replace(' ', '') == '':
proxyUsrPsw = ''
if len(proxyUsrName) > 0 and len(proxyUsrPsw) > 0:
proxyuseauth = 'yes'
else:
proxyuseauth = 'no'
ret = {'useProxy' : useProxy, 'proxyUrl' : proxyUrl, 'proxyPort' : proxyPort,
'proxyUsrName' : proxyUsrName, 'proxyUsrPsw' : proxyUsrPsw, 'proxyAuth': proxyuseauth}
return ret
def on_applyButton_mouseClick(self, event):
config.put_usrProxy(self.applyedCfg())
self.components.applyButton.enabled = False
self.components.proxytest.enabled = False
self.disableCfg()
if self.proxyEnabled:
self.components.modifyButton.enabled = True
self.components.cleanButton.enabled = True
def on_modifyButton_mouseClick(self, event):
self.enableCfg()
self.components.modifyButton.enabled = False
self.components.proxytest.enabled = True
self.components.cleanButton.enabled = True
self.components.CheckBoxUseProxy.enabled = True
def on_cleanButton_mouseClick(self, event):
self.resetCfg()
config.put_usrProxy(self.applyedCfg())
self.components.proxytest.enabled = True
self.components.applyButton.enabled = False
self.disableCfg()
self.components.cleanButton.enabled = False
def run():
#app = model.Application(proxyConf2, './skylive/settings/proxyconf.rsrc.py')
app = twistedModel.TwistedApplication(proxyConf2, './gui/settings/proxyconf.rsrc.py')
app.MainLoop()
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'proxygui',
'title':u'Proxy Settings Editor',
'size':(379, 250),
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit\tAlt+X',
'command':'exit',
},
]
},
]
},
'components': [
{'type':'StaticBox',
'name':'proxybox',
'position':(10, 10),
'size':(359, 191),
'backgroundColor':(237, 233, 227),
'label':'Proxy Settings',
},
{'type':'Button',
'name':'applyButton',
'position':(217, 162),
'size':(-1, 30),
'label':'Apply',
'enabled':False
},
{'type':'Button',
'name':'cleanButton',
'position':(152, 162),
'size':(-1, 30),
'label':'Clean',
'enabled':False
},
{'type':'Button',
'name':'modifyButton',
'position':(87, 162),
'size':(-1, 30),
'label':'Modify',
'enabled':False
},
{'type':'Button',
'name':'proxytest',
'position':(22, 162),
'size':(-1, 30),
'label':'Test',
'enabled':False
},
{'type':'TextField',
'name':'proxypsw',
'position':(137, 127),
'size':(137, -1),
'enabled':False
},
{'type':'TextField',
'name':'proxyuser',
'position':(137, 93),
'size':(137, -1),
'enabled':False
},
{'type':'StaticText',
'name':'proxypswtxt',
'position':(22, 130),
'size':(111, -1),
'backgroundColor':(237, 233, 227),
'text':'Proxy Password',
'enabled':False
},
{'type':'StaticText',
'name':'proxyusertxt',
'position':(22, 98),
'size':(115, -1),
'backgroundColor':(237, 233, 227),
'text':'Proxy UserName',
'enabled':False
},
{'type':'TextField',
'name':'proxyport',
'position':(310, 57),
'size':(50, -1),
'text':'3128',
'enabled':False
},
{'type':'TextField',
'name':'proxyurl',
'position':(63, 57),
'size':(198, -1),
'enabled':False
},
{'type':'StaticText',
'name':'proxyporttxt',
'position':(275, 62),
'size':(30, 18),
'backgroundColor':(237, 233, 227),
'text':'Port',
'enabled':False
},
{'type':'StaticText',
'name':'proxyurltxt',
'position':(22, 62),
'size':(46, 18),
'backgroundColor':(237, 233, 227),
'text':'URL/IP',
'enabled':False
},
{'type':'StaticText',
'name':'StaticText5',
'position':(22, 30),
'size':(64, 18),
'backgroundColor':(237, 233, 227),
'text':'Use Proxy',
},
{'type':'CheckBox',
'name':'CheckBoxUseProxy',
'position':(95, 28),
'label':'',
},
] # end components
} # end background
] # end backgrounds
} }
from Pycard import model
from skylive import config
from skylive.lang import language
class Pvt(model.PageBackground):
def on_initialize(self, event):
self.lang = self._parent.lang
self.gui = 'pvt'
self.ItemText = language.getItemText
self.setGui()
self.canBeep, self.canPopup = config.get_pvtPref()
self.components.useBeep.checked = self.canBeep
self.components.usePopup.checked = self.canPopup
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.components.pvtBox.label = self.getText('pvtBox')
self.components.useBeep.label = self.getText('useBeep')
self.components.usePopup.label = self.getText('usePopup')
self.components.applyButton.label = self.getText('applyButton')
self.components.defaultButton.label = self.getText('defaultButton')
self.components.closeButton.label = self.getText('closeButton')
def on_applyButton_mouseClick(self, event):
b = self.components.useBeep.checked
p = self.components.usePopup.checked
config.put_pvtPref(str(b), str(p))
def on_defaultButton_mouseClick(self, event):
self.components.useBeep.checked = True
self.components.usePopup.checked = True
config.put_pvtPref(True, True)
def on_closeButton_mouseClick(self, event):
self.parent.close()
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':'Private Chat Pref.',
'components': [
{'type':'StaticBox',
'name':'pvtBox',
'position':(10, 10),
'size':(370, 180),
'label':u'Private Chat Preference',
},
{'type':'CheckBox',
'name':'useBeep',
'position':(20, 30),
'label':u'Beep when new private message incoming',
},
{'type':'CheckBox',
'name':'usePopup',
'position':(20, 50),
'label':u'Popup the window when new msg incoming',
},
{'type':'Button',
'name':'closeButton',
'position':(170, 150),
'size':(-1, 25),
'label':u'Close',
},
{'type':'Button',
'name':'defaultButton',
'position':(90, 150),
'size':(-1, 25),
'label':u'Default',
},
{'type':'Button',
'name':'applyButton',
'position':(20, 150),
'size':(-1, 25),
'label':u'Apply',
},
] # end components
} # end background
] # end backgrounds
} }
#!/usr/bin/python
"""
__version__ = "$Revision: 1.3 $"
__date__ = "$Date: 2004/04/14 02:38:47 $"
"""
from Pycard import model
import textsize, pointer, extra, langs, proxyconf, pvt
from skylive.lang import language
import os
from skylive.utils import genutils
def expandDarwin(win):
if genutils.platform() == 'Darwin':
w, h = win.size
win.size = (w+60, h)
win.panel.SetSize(win.size)
class Settings(model.Background):
def on_initialize(self, event):
self._parent = self.getParent()
self.lang = self._parent.lang
self.gui = 'settings'
self.ItemText = language.getItemText
self.components.notebook.SetMinSize(self.components.notebook.size)
self.singleItemExpandingSizerLayout()
# OSX need a different resize!
expandDarwin(self)
win1 = model.childWindow(self.components.notebook, textsize.TextSizes, os.path.normpath("./gui/settings/textsize.rsrc.py"))
self.components.notebook.AddPage(win1, self.getText('win1'), True)
win1._parent = self._parent
win1.parent = self
win2 = model.childWindow(self.components.notebook, pointer.Pointer, os.path.normpath("./gui/settings/pointer.rsrc.py"))
self.components.notebook.AddPage(win2, self.getText('win2'), True)
win2._parent = self._parent
win2.parent = self
win4 = model.childWindow(self.components.notebook, langs.Langs, os.path.normpath("./gui/settings/langs.rsrc.py"))
self.components.notebook.AddPage(win4, self.getText('win4'), True)
win4._parent = self._parent
win4.parent = self
win5 = model.childWindow(self.components.notebook, proxyconf.proxyConf, os.path.normpath("./gui/settings/proxyconf.rsrc.py"))
self.components.notebook.AddPage(win5, self.getText('win5'), True)
win5._parent = self._parent
win5.parent = self
win6 = model.childWindow(self.components.notebook, pvt.Pvt, os.path.normpath("./gui/settings/pvt.rsrc.py"))
self.components.notebook.AddPage(win6, self.getText('win6'), True)
win6._parent = self._parent
win6.parent = self
win3 = model.childWindow(self.components.notebook, extra.Extras, os.path.normpath("./gui/settings/extra.rsrc.py"))
self.components.notebook.AddPage(win3, self.getText('win3'), True)
win3._parent = self._parent
win3.parent = self
self.components.notebook.stringSelection = self.getText('win1')
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':'Settings',
'size':(420, 240),
'icon':'gui/img/ICONA.ico',
'components': [
{'type':'Notebook',
'name':'notebook',
'position':(10, 10),
'size':(400, 230),
},
] # end components
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model, dialog
from skylive import config
from skylive.lang import language
import platform
class TextSizes(model.PageBackground):
def on_initialize(self, event):
self.lang = self._parent.lang
self.gui = 'textsize'
self.ItemText = language.getItemText
self.setGui()
self.currentSizes = self._parent.charSizes
self.setChatCharCombo()
self.setListCharCombo()
self.setInputCharCombo()
self.setTestInputSize(self.currentSizes['inputsize'])
self.setTestChatSize(self.currentSizes['chatsize'])
self.setTestListSize(self.currentSizes['listsize'])
#start text char size section
def setChatCharCombo(self):
minsize = 1
maxsize = 4
if platform.system() == 'Darwin':
maxsize = 5
for n in range(minsize, maxsize+1):
self.components.ComboChatSize.append(str(n))
self.components.ComboChatSize.text = str(self.currentSizes['chatsize'])
def setInputCharCombo(self):
minsize = 8
maxsize = 10
if platform.system() == 'Darwin':
maxsize = 13
for n in range(minsize, maxsize+1):
self.components.ComboInputSize.append(str(n))
self.components.ComboInputSize.text = str(self.currentSizes['inputsize'])
def setListCharCombo(self):
minsize = 7
maxsize = 9
if platform.system() == 'Darwin':
maxsize = 13
for n in range(minsize, maxsize+1):
self.components.ComboListSize.append(str(n))
self.components.ComboListSize.text = str(self.currentSizes['listsize'])
def setTestChatSize(self, size=8):
try:
self.components.testChatSize.font = {'size':int(size)}
except:
pass
def setTestInputSize(self, size=8):
try:
self.components.testInputSize.font = {'size':int(size)}
except:
pass
def setTestListSize(self, size=7):
try:
self.components.testListSize.font = {'size':int(size)}
except:
pass
def on_ComboChatSize_textUpdate(self, event):
self.setTestChatSize(self.components.ComboChatSize.text)
def on_ComboListSize_textUpdate(self, event):
self.setTestListSize(self.components.ComboListSize.text)
def on_ComboInputSize_textUpdate(self, event):
self.setTestInputSize(self.components.ComboInputSize.text)
def on_applyButton_mouseClick(self, event):
try:
self._parent.components.ChatArea.font = {'size': int(self.components.ComboChatSize.text)}
self._parent.components.UserlistArea.font = {'size': int(self.components.ComboListSize.text)}
self._parent.components.ChatField.font = {'size': int(self.components.ComboInputSize.text)}
config.put_usrCharSizes(self.components.ComboChatSize.text, self.components.ComboListSize.text, self.components.ComboInputSize.text)
except:
pass
def on_defaultButton_mouseClick(self, event):
chatsize = 8
listsize = 7
inputsize = 8
if platform.system() == 'Darwin':
chatsize = 11
listsize = 10
inputsize = 11
self.components.ComboChatSize.text = str(chatsize)
self.components.ComboListSize.text = str(listsize)
self.components.ComboInputSize.text = str(inputsize)
self.setTestInputSize(inputsize)
self.setTestChatSize(chatsize)
self.setTestListSize(listsize)
#end text char size section
def on_closeButton_mouseClick(self, event):
self.parent.close()
def getText(self, item):
return self.ItemText(self.lang, self.gui, item)
def setGui(self):
self.components.inputsize.text = self.getText('inputsize')
self.components.listsize.text = self.getText('listsize')
self.components.chatsize.text = self.getText('chatsize')
self.components.textbox.label = self.getText('textbox')
self.components.defaultButton.label = self.getText('defaultButton')
self.components.applyButton.label = self.getText('applyButton')
self.components.closeButton.label = self.getText('closeButton')
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':'Text Sizes',
'components': [
{'type':'StaticBox',
'name':'textbox',
'position':(10, 10),
'size':(370, 180),
'label':u'Text Preference',
},
{'type':'StaticText',
'name':'inputsize',
'position':(20, 84),
'text':u'Input Text Size:',
},
{'type':'TextField',
'name':'testInputSize',
'position':(230, 79),
'size':(100, 22),
'editable':False,
'text':u'abc ABC 123',
},
{'type':'ComboBox',
'name':'ComboInputSize',
'position':(150, 79),
'size':(50, 22),
'items':[],
},
{'type':'Button',
'name':'closeButton',
'position':(170, 150),
'size':(-1, 25),
'label':u'Close',
},
{'type':'Button',
'name':'defaultButton',
'position':(90, 150),
'size':(-1, 25),
'label':u'Default',
},
{'type':'Button',
'name':'applyButton',
'position':(20, 150),
'size':(-1, 25),
'label':u'Apply',
},
{'type':'TextField',
'name':'testChatSize',
'position':(230, 25),
'size':(100, 22),
'editable':False,
'text':u'abc ABC 123',
},
{'type':'TextField',
'name':'testListSize',
'position':(230, 52),
'size':(100, 22),
'editable':False,
'text':u'abc ABC 123',
},
{'type':'ComboBox',
'name':'ComboListSize',
'position':(150, 52),
'size':(50, 22),
'items':[],
},
{'type':'ComboBox',
'name':'ComboChatSize',
'position':(150, 25),
'size':(50, 22),
'items':[],
},
{'type':'StaticText',
'name':'listsize',
'position':(20, 58),
'text':u'User List Text Size:',
},
{'type':'StaticText',
'name':'chatsize',
'position':(20, 30),
'text':u'Chat Text Size:',
},
] # end components
} # end background
] # end backgrounds
} }
from Pycard import model, dialog
import wx
import wx.media
import platform
import sys
from skylive.utils import genutils as utils
#from skylive import streaming
class Stream(model.Background):
volume = 2.5
playinguri = ""
def on_initialize(self, event):
self.parent = self.getParent()
self.playing = False
self.replay = False
if utils.platform() in ('Windows', 'Microsoft'):
if int(sys.getwindowsversion()[0]) > 5:
# XXX This is a temporary solution!
self.components.StreamCombo.enabled=False
if int(sys.getwindowsversion()[0]) < 5:
self.mc = wx.media.MediaCtrl(self.components.Video)
else:
self.mc = wx.media.MediaCtrl(self.components.Video, szBackend=wx.media.MEDIABACKEND_WMP10)
else:
self.mc = wx.media.MediaCtrl(self.components.Video)
self.video_sizer = wx.BoxSizer(wx.VERTICAL)
self.video_sizer.Add(self.mc,5, wx.EXPAND|wx.ALL, border=10)
self.components.Video.SetSizer(self.video_sizer)
wx.CallAfter(self.on_Play_mouseClick)
def on_Slider1_select(self, event):
vol = self.components.Slider1.value
self.volume = float((50.0-vol)/10)
#print float(self.volume), vol
self.mc.SetVolume(float(self.volume))
def getStream(self):
StreamUri=self.parent.StreamUri.split(";")
idx=1
self.components.StreamCombo.items=[]
for u in StreamUri:
self.components.StreamCombo.append('stream'+str(idx))
idx=idx+1
streamidx=int(self.parent.streamingIndex)
try:
stream = StreamUri[streamidx]
except:
stream = StreamUri[0]
self.components.StreamCombo.text = self.components.StreamCombo.items[streamidx]
if stream=='NONE':
self.close()
else:
#if utils.platform() == 'Darwin':
# # XXX TODO QuickTime is very crappy. We really need to use GSTREAMER on
# # another way on OSX!
# if stream.startswith('http://') and (stream.endswith(':8000/skylive.ogg') or stream.endswith(':8000/skylive.mp3')):
# stream = stream.replace("http://", "icy://")[:-3]+'mp3'
return stream
def on_StreamCombo_textUpdate(self, event):
stream = self.components.StreamCombo.text
if not stream in self.components.StreamCombo.items:
stream = self.components.StreamCombo.items[0]
self.components.StreamCombo.text = stream
idx=int(stream[-1])-1
if int(self.parent.streamingIndex) != idx:
self.parent.streamingIndex = idx
self.parent.on_setStreamIdx(idx)
if self.playing:
self.stop()
wx.CallAfter(self.on_Play_mouseClick)
def play(self, uri=False):
if uri:
self.playinguri = uri
self.on_playAudioStream(uri)
else:
self.close(True)
def stop(self):
self.on_stopAudioStream()
def changeStream(self, uri):
if uri != self.playinguri:
self.stop()
self.replay=uri
def on_playAudioStream(self, uri):
#if not self.playing:
# self.components.Play.enable=False
print 'PLAYAUDIOSTREAM'
self.Bind(wx.media.EVT_MEDIA_LOADED, self.onMediaLoaded)
self.Bind(wx.media.EVT_MEDIA_FINISHED, self.onMediaFinished)
self.Bind(wx.media.EVT_MEDIA_PAUSE, self.onMediaPause)
self.Bind(wx.media.EVT_MEDIA_PLAY, self.onMediaPlay)
self.Bind(wx.media.EVT_MEDIA_STATECHANGED, self.onMediaStatechanged)
self.Bind(wx.media.EVT_MEDIA_STOP, self.onMediaStop)
proxy=self.parent.config.get_usrProxy()
if str(proxy['useProxy']).lower() in ['si', 'yes', 'true', True, 1]:
p = int(proxy['proxyPort'])
h = proxy['proxyUrl']
pxy="http://"+str(h)+":"+str(p)
if str(proxy['proxyAuth']).lower() in ['si', 'yes', 'true', True, 1]:
usr = proxy['proxyUsrName']
pwd = proxy['proxyUsrPsw']
pxy="http://"+str(usr)+":"+str(pwd)+"@"+str(h)+":"+str(p)
self.mc.LoadFromURI(uri, pxy)
else:
self.mc.LoadFromURI(uri)
#self.mc.LoadFromURI(uri)
self.components.Play.SetLabel("Loading")
def onMediaFinished(self, event):
print 'onMediaFinished'
event.Skip()
def onMediaPause(self, event):
print 'onMediaPause'
event.Skip()
def onMediaPlay(self, event):
print 'onMediaPlay'
event.Skip()
def onMediaStatechanged(self, event):
print 'onMediaStatechanged'
event.Skip()
def onMediaStop(self, event):
if self.replay:
self.play(self.replay)
self.replay=False
print 'onMediaStop'
event.Skip()
def onMediaLoaded(self, evt):
print 'onMediaLoaded'
#self.components.Play.enable=True
self.components.Play.SetLabel("Stop")
self.playing=True
self.mc.Play()
def on_stopAudioStream(self):
self.mc.Stop()
self.playing = False
self.components.Play.SetLabel("Play")
def stop(self):
self.on_stopAudioStream()
def on_close(self, event):
try:
self.stop()
except:
pass
self.parent.on_CloseStream(event)
event.skip()
def on_exit_command(self, event):
self.close()
def on_size(self, event):
self.panel.SetSize(self.size)
def on_Play_mouseClick(self, event=False):
if self.playing:
self.on_stopAudioStream()
else:
# Why we need to start the stream 2 times? fucking windows...
print 'PLAY'
self.play(self.getStream())
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'Stream',
'title':u'Streaming',
'size':(400, 300),
'components': [
{'type':'Slider',
'name':'Slider1',
'position':(514, 19),
'size':(-1, 161),
'backgroundColor':(211, 215, 207, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'labels':False,
'layout':'vertical',
'max':50,
'min':0,
'tickFrequency':0,
'ticks':False,
'value':25,
},
{'type':'Container',
'name':'Video',
'position':(320, 200),
'size':(320, 240),
},
{'type':'ComboBox',
'name':'StreamCombo',
'position':(289, 47),
'size':(103, -1),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'items':[u'stream1'],
'text':'stream1',
},
{'type':'Button',
'name':'Play',
'position':(298, 5),
'backgroundColor':(238, 238, 236, 255),
'font':{'faceName': u'Sans', 'family': 'sansSerif', 'size': 9},
'foregroundColor':(16, 16, 16, 255),
'label':'Play',
},
] # end components
,
'sizers':
[
{
'name' : 'ALL',
'typ' : 'i',
'children' : [
{
'name' : 'TOP SIZER',
'typ' : 'v',
'children' : [
{
'name' : 'versizer001',
'typ' : 'v',
'children' : [
{
'name' : 'horsizer001',
'typ' : 'h',
'children' : [
{
'name' : 'Play' },
{
'name' : 'StreamCombo' },
] # end of horsizer001
},
{
'name' : 'horsizer001',
'typ' : 'h',
'children' : [
{
'name' : 'Video' },
{
'name' : 'Slider1' },
] # end of horsizer001
},
] # end of versizer001
},
] # end of TOP SIZER
},
{
'name' : 'UNPLACED',
'typ' : 'i' },
] # end of ALL
},
] # end of sizers
} # end background
] # end backgrounds
} }
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard import model
class UserInfo(model.Background):
def on_initialize(self, event):
pass
{'application':{'type':'Application',
'name':'Template',
'backgrounds': [
{'type':'Background',
'name':'bgTemplate',
'title':u'Account Info',
'size':(400, 300),
'useSizers':0,
'menubar': {'type':'MenuBar',
'menus': [
{'type':'Menu',
'name':'menuFile',
'label':'&File',
'items': [
{'type':'MenuItem',
'name':'menuFileExit',
'label':'E&xit',
'command':'exit',
},
]
},
]
},
'components': [
] # end components
,
'sizers':
[
{
'name' : 'ALL',
'typ' : 'i',
'children' : [
{
'name' : 'TOP SIZER',
'typ' : 'v',
'horGrowth' : 1,
'verGrowth' : 1 },
{
'name' : 'UNPLACED',
'typ' : 'i' },
] # end of ALL
},
] # end of sizers
} # end background
] # end backgrounds
} }
#!/usr/bin/env python
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
__version__ = "$Revision: 0.1 $"
__date__ = "$Date: 2007/09/25 22:13:23 $"
"""
from gui.settings import proxyconf
if __name__ == "__main__":
proxyconf.run()
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="*.*.*" type="win32" />
<description>*</description>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls"
version="6.0.0.0" processorArchitecture="X86" publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly>
</dependency>
</assembly>
#!/usr/bin/env python
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
__version__ = "$Revision: 0.1 $"
__date__ = "$Date: 2007/09/25 22:13:23 $"
"""
import platform
import traceback
import sys, os
def myexcepthook(type, value, traceback):
#print 'ExceptHook: ', type, value, traceback
pass
#sys.excepthook = myexcepthook
from skylive.utils import genutils as utils
if platform.system() == 'Darwin' and utils.is_frozen():
# This is for osx 10.4. We need to wrap our
# updated versions here as we can't do it
# from a shell script in old osx versions, cause it
# complain that it need pythonw if we rename
# the app bundle executable.
sup = False
mydir = os.path.normpath(os.path.abspath(os.path.dirname(sys.executable)))
myexe = mydir+"/skylive-ng"
userhome = os.path.expanduser("~")
upexe = userhome+'/.SkyLIVE.app/Contents/MacOS/skylive-ng'
uppath = userhome+'/.SkyLIVE.app'
upv = uppath+"/Contents/MacOS/VERSION.txt"
myv = mydir+"/VERSION.txt"
if myexe != upexe:
if os.path.exists(upv):
if os.path.exists(myv):
f = open(myv, "r")
myn = int(f.read())
f.close()
f = open(upv, "r")
upn = int(f.read())
f.close()
if upn > myn:
sup = True
else:
sup = True
if sup:
import subprocess
subprocess.Popen(upexe, shell=True, preexec_fn = os.setsid)
sys.exit(0)
if platform.system() == 'Darwin':
import shutil
# This is for our Live Audio Streaming. OSX don't have vorbis codecs
# installed by default. Look if it is already installed, if not, install
# it.
installed=False
userhome = os.path.expanduser("~")
if os.path.isdir('/Library/QuickTime'):
if os.path.isdir('/Library/QuickTime/XiphQT.component'):
installed=True
if os.path.isdir('/Library/Components'):
if os.path.isdir('/Library/Components/XiphQT.component'):
installed=True
if os.path.isdir(userhome+'/Library/QuickTime'):
if os.path.isdir(userhome+'/Library/QuickTime/XiphQT.component'):
installed=True
if os.path.isdir(userhome+'/Library/Components'):
if os.path.isdir(userhome+'/Library/Components/XiphQT.component'):
installed=True
if not installed and (os.path.isdir(userhome+'/Library/QuickTime') or os.path.isdir('/Library/QuickTime')):
if utils.is_frozen():
mydir = os.path.normpath(os.path.abspath(os.path.dirname(sys.executable)))
try:
shutil.copytree(mydir+'/../../XiphQT.component', '/Library/QuickTime/XiphQT.component')
except:
shutil.copytree(mydir+'/../../XiphQT.component', userhome+'/Library/QuickTime/XiphQT.component')
else:
print "WARNING: Please install Vorbis Codecs for QuickTime if you want to have Audio Streaming!"
from Pycard import model, splash
from Pycard.twistedsupport import twistedThreadModel
from twisted.internet import reactor
try:
import psyco
psyco.cannotcompile(traceback.export_stack)
psyco.full()
except:
pass
from gui import main as guimain
from skylive import config, main
if __name__ == "__main__":
if platform.system() == 'Windows' or platform.system() == "Microsoft":
sys.stderr = open('errors.log', 'w')
if len(sys.argv) > 1:
debug=False
#for opt in sys.argv:
# if opt == '-d':
# debug=True
#sys.argv=[sys.argv[0]]
if debug:
# requested debug mode. We need to authenticate the user *before* to
# permit to use this mode, so, remove the config module!
import os
userhome = os.path.expanduser("~")
sys.argv.append('-d')
#app = twistedModel.TwistedApplication(main.skyLive, "./gui/main."+sysType+".rsrc.py")
#app = twistedThreadModel.TwistedApplication(main.skyLive, "./gui/main."+sysType+".rsrc.py")
wxapp = splash.PycardSplashedApp(guimain.skyLive, './gui/img/splash.jpg', 40)
app = twistedThreadModel.TwistedApplication(main.skyLive, wxapp, "./gui/main.rsrc.py")
#sys.excepthook = myexcepthook
app.MainLoop()
[Desktop Entry]
Value=1.0
Encoding=UTF-8
Icon=applications-science
Type=Directory
Name=Science
Name[af]=Wetenskap
Name[ar]=علوم
Name[be]=Навука
Name[bg]=Наука
Name[bn_IN]=বিজ্ঞান
Name[br]=Skiantoù
Name[ca]=Ciència
Name[cs]=Věda
Name[csb]=Ùczba
Name[da]=Naturvidenskab
Name[de]=Wissenschaft
Name[el]=Επιστήμη
Name[eo]=Scienco
Name[es]=Ciencia
Name[et]=Teadus
Name[eu]=Zientzia
Name[fa]=علم
Name[fi]=Luonnontieteet
Name[fy]=Wittenskiplik
Name[ga]=Eolaíocht
Name[gl]=Ciencia
Name[gu]=વિજ્ઞાન
Name[he]=מדע
Name[hi]=विज्ञान
Name[hr]=Znanost
Name[hu]=Tudományok
Name[is]=Vísindi
Name[it]=Scienza
Name[ja]=サイエンス
Name[kk]=Ғылым
Name[km]=វិទ្យាសាស្ត្រ​
Name[ko]=과학
Name[ku]=Zanist
Name[lt]=Mokslas
Name[lv]=Zinātne
Name[mk]=Наука
Name[ml]=ശാസ്ത്രം
Name[mr]=विज्ञाण
Name[nb]=Vitenskap
Name[nds]=Wetenschap
Name[ne]=विज्ञान
Name[nl]=Wetenschappelijk
Name[nn]=Vitskap
Name[oc]=Sciéncia
Name[pa]=ਵਿਗਿਆਨ
Name[pl]=Nauka
Name[pt]=Ciência
Name[pt_BR]=Ciência
Name[ro]=Știință
Name[ru]=Научные
Name[se]=Dieđa
Name[sl]=Znanost
Name[sr]=Наука
Name[sr@latin]=Nauka
Name[sv]=Vetenskap
Name[ta]=அறிவியல்
Name[tg]=Илм
Name[th]=วิทยาศาสตร์
Name[tr]=Bilim
Name[uk]=Наука
Name[uz]=Fan
Name[uz@cyrillic]=Фан
Name[vi]=Khoa học
Name[wa]=Siyince
Name[x-test]=xxSciencexx
Name[zh_CN]=科学
Name[zh_TW]=科學
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import re, cgi
urifinder = re.compile("(\s|\A)(((news|telnet|nttp|file|http|ftp|https|sip)://\S+)|((www|ftp)\.[a-zA-Z]+\.\S+))", re.IGNORECASE)
def _urlMatch(txt):
match=urifinder.finditer(txt)
if match:
for uri in match:
url=uri.groups()[1]
htmlurl="<a href=\""+url+"\">"+url+"</a>"
txt=txt.replace(url, htmlurl)
return txt
def toHtml(txt):
txt=cgi.escape(txt)
txt=_urlMatch(txt)
txt=txt.replace("\n", "<br />")
return txt
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import httplib
import time, os, sys, traceback
import protocol
from utils import genutils as utils
from gui import gui
from ConfigParser import SafeConfigParser
import platform
import string
from random import choice
#import md5, base64
import base64
try:
import hashlib
md5 = hashlib
md5.new = hashlib.md5
except:
import md5
class configFile(SafeConfigParser):
defaults = {
'Network': {
'transport': 'SSL'
},
'HTTPProxy':{
'useproxy': 'no',
'proxyurl': '',
'proxyport': '',
'proxyauth': 'no',
'proxyauthstr':'',
'proxyusr':'',
'proxypwd':''
},
'Main':
{
'version': '0.1',
'revision': '5.6'
},
'Login': {
'username': 'NOTSET',
'password': 'NOTSET'
},
'UsrPreference':
{
'chatcharsize': '1',
'listcharsize': '7',
'inputcharsize': '8',
'pointercolor': '#FF7700',
'ardecfile': 'False',
'indi': 'False',
'beep':'True',
'popup':'True',
'lang':'en',
'usrdefpath':'',
'lowres':'False',
},
'ExternalPrograms':
{
'indi': 'False',
'ardecfile': 'False',
},
'Streaming':
{
'enable': 'True',
'ask': 'True',
'index': '0'
}
}
def __init__(self):
# This seem to work on both win, linux, osx and also for FreeBSD.
# I hope that it will work also on other unixes
SafeConfigParser.__init__(self)
self.userhome = os.path.expanduser("~")
# We have a new config system. Remove all directory from oldest
# client installs. Maybe sometime in the future we will remove those
# lines.
for name in ['/.SkyliveNG', '/.SkyliveNG_Pref', '/skylive-ng_chat']:
dirname = os.path.normpath(self.userhome+name)
if os.path.exists(dirname):
try:
utils.rmdir(dirname)
except:
print 'I cant remove %s, please remove it manually!' % dirname
self.skyliveDir = os.path.normpath(self.userhome+"/SkyliveNG")
self.conffile = os.path.normpath(self.skyliveDir+"/skyliveng.conf")
self.savechatdir = os.path.normpath(self.skyliveDir+"/ChatLogs")
self.downloadDir = os.path.normpath(self.skyliveDir+"/downloads")
self.extraDir = os.path.normpath(self.skyliveDir+"/extra")
self.binDir = os.path.normpath(self.skyliveDir+"/bin")
for cdir in [self.skyliveDir, self.savechatdir, self.downloadDir, self.extraDir, self.binDir]:
if not os.path.exists(cdir):
try:
os.makedirs(cdir, 0700)
except:
print 'Cannot create directory %s. Please verify your permissions!' % cdir
sys.exit(0)
if utils.platform == 'Windows':
pathsep = ";"
else:
pathsep = ":"
if not self.binDir in os.environ["PATH"].split(pathsep):
os.environ["PATH"] = os.environ["PATH"]+pathsep+self.binDir
self.bootRead()
def readConfigFile(self):
print 'READ'
if not os.path.exists(self.conffile) or not os.path.isfile(self.conffile):
if utils.platform() in ('Windows', 'Microsoft'):
if int(sys.getwindowsversion()[0]) > 5:
self.defaults['Streaming']['index']='1'
self.createDefaultConfigFile()
else:
try:
tochange = True
if self.has_section('Main'):
if self.has_option('Main', 'version'):
if self.has_option('Main', 'revison'):
# This is for an old error on 1.x version...
self.remove_option('Main', 'revison')
else:
if self.has_option('Main', 'revision'):
if self.get('Main', 'version') == self.defaults['Main']['version']:
if self.get('Main', 'revision') == self.defaults['Main']['revision']:
tochange = False
#self.read(self.conffile)
if tochange:
changed = False
for s in self.defaults.keys():
if not s in self.sections():
self.add_section(s)
changed = True
for o in self.defaults[s].keys():
if s=='Main' and o in ['version', 'revision']:
if self.has_option(s, o):
if self.get(s, o) != self.defaults[s][o]:
self.set(s, o, self.defaults[s][o])
changed = True
else:
self.set(s, o, self.defaults[s][o])
else:
if not o in self.options(s):
self.set(s, o, self.defaults[s][o])
changed = True
# XXX An this is cause Windows Vista and Windows 7
# won't work good with ogg streaming...
# I hope it will change in future, as
# WMP and mp3 streaming have very high latency..
if s=='Streaming' and o=='index':
if utils.platform() in ('Windows', 'Microsoft'):
if int(sys.getwindowsversion()[0]) > 5:
self.defaults[s][o]='1'
self.set(s, o, self.defaults[s][o])
changed = True
# End of the windows Hack.
if s=='UsrPreference' and o=='chatcharsize':
if int(self.get(s, o)) > 4:
self.set(s, o, self.defaults[s][o])
changed = True
if changed:
self.saveConfigFile()
except:
print 'Error parsing config file'
def bootRead(self):
if os.path.exists(self.conffile) and os.path.isfile(self.conffile):
self.read(self.conffile)
def get(self, sect, var):
if os.path.exists(self.conffile) and os.path.isfile(self.conffile):
return SafeConfigParser.get(self, sect, var)
else:
return self.defaults[sect][var]
def saveConfigFile(self):
print 'SAVE CONFIG'
fd = open(self.conffile, "w")
self.write(fd)
fd.close()
def changeLoginInfos(self, counterlogin=0, runtime=False):
print 'CHANGE LOGIN INFO '
self.user=None
cleanpwd=None
while not self.user or not cleanpwd:
if counterlogin > 3:
sys.exit(0)
break
self.user, cleanpwd=gui.Login()
counterlogin=counterlogin+1
if self.user != "stoplogin" and cleanpwd != "stoplogin":
self.set('Login', 'username', self.user)
m = md5.new(cleanpwd)
self.pwd = str(m.hexdigest())
self.set('Login', 'password', self.pwd)
self.saveConfigFile()
else:
if runtime:
self.readConfigFile()
else:
sys.exit(0)
def createDefaultConfigFile(self):
for sect in self.defaults:
try:
self.add_section(sect)
except:
pass
for opt in self.defaults[sect]:
self.set(sect, opt, self.defaults[sect][opt])
self.set('UsrPreference', 'usrdefpath', self.downloadDir)
# Work around for OSX: we need a more bigger characters here!
if platform.system() == 'Darwin':
self.put_usrCharSizes('11', '10', '11')
# Ask for login infos
self.changeLoginInfos(1)
def put_usrProxy(self, args):
self.read(self.conffile)
self.set('HTTPProxy', 'useproxy', args['useProxy'])
self.set('HTTPProxy', 'proxyurl', args['proxyUrl'])
self.set('HTTPProxy', 'proxyport', args['proxyPort'])
self.set('HTTPProxy', 'proxyusr', args['proxyUsrName'])
self.set('HTTPProxy', 'proxypwd', args['proxyUsrPsw'])
if args['proxyAuth'] == 'yes':
proxyauthstr = base64.b64encode(args['proxyUsrName']+':'+args['proxyUsrPsw'])
self.set('HTTPProxy', 'proxyauthstr', proxyauthstr)
self.set('HTTPProxy', 'proxyauth', 'yes')
else:
self.set('HTTPProxy', 'proxyauthstr', "")
self.set('HTTPProxy', 'proxyauth', 'no')
self.saveConfigFile()
def put_usrDefaltPath(self, path):
self.set('UsrPreference', 'usrdefpath', path)
self.saveConfigFile()
def put_usrCharSizes(self, chatsize=False, listsize=False, inputsize=False):
if chatsize:
self.set('UsrPreference', 'chatcharsize', chatsize)
if listsize:
self.set('UsrPreference', 'listcharsize', listsize)
if inputsize:
self.set('UsrPreference', 'inputcharsize', inputsize)
if chatsize or listsize or inputsize:
self.saveConfigFile()
def put_usrPointerColor(self, color="#FF7700"):
if color:
self.set('UsrPreference', 'pointercolor', color)
self.saveConfigFile()
def put_extProgram(self, pref='False'):
self.set('ExternalPrograms', 'ardecfile', pref)
self.saveConfigFile()
def put_extINDIProgram(self, pref='False'):
self.set('ExternalPrograms', 'indi', pref)
self.saveConfigFile()
def put_usrLang(self, lang='en'):
self.set('UsrPreference', 'lang', lang)
self.saveConfigFile()
def get_usrLang(self):
try:
lang = self.get('UsrPreference', 'lang')
except:
lang = 'en'
return lang
def put_pvtPref(self, b=False, p=False):
if b:
self.set('UsrPreference', 'beep', str(b))
self.usrBeep = b
if p:
self.set('UsrPreference', 'popup', str(p))
self.usrPopup = p
if b or p:
self.saveConfigFile()
def put_lowResPref(self, pref='False'):
self.set('UsrPreference', 'lowres', pref)
self.saveConfigFile()
#########################################################################################
CFile = configFile()
def initialize():
CFile.readConfigFile()
def getUsername():
return CFile.get('Login', 'username')
def getPassword():
return 'HASH:'+CFile.get('Login', 'password')
def changeLoginCredentials(count=0):
if count == 0:
val=1
else:
val = count
return CFile.changeLoginInfos(val, runtime=True)
def get_usrDefaultPath():
return CFile.get('UsrPreference', 'usrdefpath')
def put_usrDefaultPath(path):
CFile.put_usrDefaltPath(path)
def get_usrCharSizes():
ret = {'chatsize' : CFile.get('UsrPreference', 'chatcharsize'),
'listsize': CFile.get('UsrPreference', 'listcharsize'),
'inputsize': CFile.get('UsrPreference', 'inputcharsize')}
return ret
def put_usrCharSizes(chat=False, list=False, input=False):
CFile.put_usrCharSizes(chat, list, input)
def get_usrProxy():
try:
usr = CFile.get('HTTPProxy','proxyusr')
pwd = CFile.get('HTTPProxy','proxypwd')
except:
CFile.set('HTTPProxy','proxyusr', '')
CFile.set('HTTPProxy','proxypwd', '')
ret = {'useProxy': CFile.get('HTTPProxy', 'useproxy'),
'proxyUrl': CFile.get('HTTPProxy', 'proxyurl'),
'proxyPort': CFile.get('HTTPProxy', 'proxyport'),
'proxyAuth': CFile.get('HTTPProxy', 'proxyauth'),
'proxyAuthStr': CFile.get('HTTPProxy','proxyauthstr'),
'proxyUsrName': CFile.get('HTTPProxy','proxyusr'),
'proxyUsrPsw': CFile.get('HTTPProxy','proxypwd')}
return ret
def put_usrProxy(args):
CFile.put_usrProxy(args)
def put_usrPointerColor(color):
CFile.put_usrPointerColor(color)
def get_usrPointerColor():
return CFile.get('UsrPreference', 'pointercolor')
def put_extProgram(pref='False'):
CFile.put_extProgram(pref)
def put_extINDIProgram(pref='False'):
CFile.put_extINDIProgram(pref)
def get_extProgram():
return CFile.get('ExternalPrograms', 'ardecfile')
def get_extINDIProgram():
return CFile.get('ExternalPrograms', 'indi')
def put_usrLang(arg):
CFile.put_usrLang(arg)
def get_usrLang():
return CFile.get_usrLang()
def put_pvtPref(b=False, p=False):
CFile.put_pvtPref(str(b), str(p))
def get_pvtPref():
if CFile.get('UsrPreference', 'beep') == 'True':
b = True
else:
b = False
if CFile.get('UsrPreference', 'popup') == 'True':
p = True
else:
p = False
return [b, p]
def get_lowResPref(when='normal'):
if CFile.get('UsrPreference', 'lowres') == 'True':
return True
return False
def put_lowResPref(pref=False):
toPut = 'False'
if pref:
toPut = 'True'
CFile.put_lowResPref(toPut)
def get_streamingPref():
enable = CFile.get('Streaming', 'enable')
ask = CFile.get('Streaming', 'ask')
return [enable, ask]
def get_streamingIndex():
return CFile.get('Streaming', 'index')
def set_streamingIndex(idx=0):
CFile.set('Streaming', 'index', str(idx))
CFile.saveConfigFile()
def put_streamingPref(enable='True', ask='True'):
e='False'
a='False'
if enable:
e='True'
if ask:
a='True'
CFile.set('Streaming','ask', a)
CFile.set('Streaming','enable', e)
CFile.saveConfigFile()
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import sys, string
import time, wx, os
import protocol, config
from utils import webutils
from utils import genutils as utils
from twisted.internet import reactor, ssl, task
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import ServerFactory, Protocol
import base64
import random
isConnected = False
# TODO Remove all globals!!
def is_jpeg(cont):
try:
if cont[0:4] == '\xff\xd8\xff\xe0' and cont[6:10] == 'JFIF':
return True
except:
pass
return False
def pageGet(url, **kwargs):
proxy=config.get_usrProxy()
if str(proxy['useProxy']).lower() in ['si', 'yes', 'true', True, 1]:
p = int(proxy['proxyPort'])
h = proxy['proxyUrl']
if str(proxy['proxyAuth']).lower() in ['si', 'yes', 'true', True, 1]:
headers = {'Proxy-authorization': 'Basic '+proxy['proxyAuthStr'].strip()}
return webutils.getPage(url, proxy_host=h, proxy_port=p, headers=headers, **kwargs)
return webutils.getPage(url, proxy_host=h, proxy_port=p, **kwargs)
return webutils.getPage(url, **kwargs)
class HTTPDownloader:
def __init__(self, parent, timing):
self._parent = parent
self.keepRunning = 1
self.checkUpdate = True
self.timing = timing
self.tscope="1"
self.tsdiff = 0
self.tsdiffchanged=False
self.last = time.time()
self.liveurilist = False
self.liveurilistsave = False
self.kojpeg = 0
self.okjpeg = 0
self.defuri = 'http://skylive.astronomix.org'
self.lastWakeUp = False
def setLiveUri(self, urilist=False):
self.liveurilist=urilist
self.liveurilistsave = False
self.kojpeg = 0
self.okjpeg = 0
def setTiming(self, timing=5):
self.timing = int(timing)
def setTSDiff(self, tsdiff):
self.tsdiff = tsdiff
self.tsdiffchanged = True
def oneUri(self, default=False):
try:
if self.liveurilist and len(self.liveurilist) > 0 and not default:
uri = self.liveurilist[random.randint(0, len(self.liveurilist)-1)]
if uri[-1] != '/':
uri=uri+'/'
return str(uri)
else:
return self.defuri+'/tele'+str(self.tscope)+'/'
except:
return self.defuri+'/tele'+str(self.tscope)+'/'
def getError(self, error=None):
#print 'Error in getPage: ', error
pass
def setLiveImage(self, result, *args):
try:
#if True:
if args[0]:
if not args[0] < self.lastWakeUp:
self._parent.callInGui('on_setLiveImage', result)
except:
pass
def setGuideImage(self, result, *args):
try:
if args[0]:
if not args[0] < self.lastWakeUp:
self._parent.callInGui('on_setGuideImage', result)
except:
pass
def wakeUp(self):
ret = {}
self.lastWakeUp=time.time()
try:
if globals()['isConnected'] and self.liveurilist:
self.getLiveImage(self.oneUri(), 'live640.jpg').addCallbacks(
self.setLiveImage, self.getError, [self.lastWakeUp]
)
self.getLiveImage(self.oneUri(), 'guida.jpg').addCallbacks(
self.setGuideImage, self.getError, [self.lastWakeUp]
)
elif globals()['isConnected'] and self.liveurilistsave:
self.getLiveImage(self.oneUri(True), 'live640.jpg').addCallbacks(
self.setLiveImage, self.getError, [self.lastWakeUp]
)
self.getLiveImage(self.oneUri(True), 'guida.jpg').addCallbacks(
self.setGuideImage, self.getError, [self.lastWakeUp]
)
except:
pass
def on_GetOk(self, result):
if is_jpeg(result):
self.kojpeg = 0
if self.okjpeg > 20 and not self.liveurilist and self.liveurilistsave:
self.liveurilist = self.liveurilistsave
self.liveurilistsave = False
self.okjpeg += 1
return result
else:
self.okjpeg = 0
if self.kojpeg >= 4:
print 'I can\'t get images with your indicated URL, so, i will fallback to defuri.'
# Uhmmm, it seem that our url won't work, so
# switch back to the fallback default uri.
self.liveurilistsave = self.liveurilist
self.liveurilist = False
else:
self.kojpeg+=1
def getLiveImage(self, baseuri, filename):
ret = False
addtime="?t="
if self.tsdiffchanged:
addtime="?tsok="
addt=str(int(round((int(time.time())-self.tsdiff)/self.timing)*self.timing))
addtime+=addt
uri = baseuri+filename+addtime
return pageGet(uri).addCallback(self.on_GetOk)
def progressBar(self, data, currentLength, totalLength, uniqueid):
#print 'ProgressBar', currentLength, totalLength, uniqueid
percent = "%d/%dK" % (currentLength/1000,
totalLength/1000)
percent += "- %i%%" % (
(currentLength/totalLength)*100)
self._parent.callInGui('on_downPopOpen', str(totalLength/1000), uniqueid)
msg = "Downloading "+str(currentLength/1000)+" kb of "+str(totalLength/1000)+" kb"
self._parent.callInGui('on_downPopUpdate', msg, (currentLength/totalLength)*100, uniqueid)
# we need to slowing down a bit the download to let's the download
# bar have enough time to refresh, only 5/100 of seconds for cicle...
time.sleep(.05)
#print percent
def putFitsFile(self, result):
fitdata=result[0]
uniqueid=result[1]
self._parent.callInGui('on_downPopClose', uniqueid)
tmpfile = os.tempnam()+".zip"
f = open(tmpfile,'wb')
f.write(fitdata)
f.close()
self._parent.callInGui('on_FitsDownloaded', tmpfile)
def getFitsFile(self, telescope):
uri = self.oneUri(True)+'SkyFrame.Sky?time=%s' % str(time.time())
return pageGet(uri, progress=self.progressBar, uniqueid=time.time()).addCallback(self.putFitsFile)
def getLastPhoto(self):
try:
self.getLiveImage(self.oneUri(True), 'foto.jpg').addCallbacks(
self.putLastPhoto, self.getError
)
except:
pass
def putLastPhoto(self, result):
try:
self._parent.callInGui('on_LastPhotoDone', result)
except:
pass
def putFitsFileScript(self, result):
fitdata=result[0]
uniqueid=result[1]
self._parent.callInGui('on_downPopClose', uniqueid)
tmpfile = os.tempnam()+".zip"
f = open(tmpfile,'wb')
f.write(fitdata)
f.close()
try:
self._parent.callInGui('script_Command', 'on_scriptFitsDownloaded', tmpfile)
except:
pass
def getFitsScript(self, telescope):
uri = self.oneUri(True)+'SkyFrame.Sky?time=%s' % str(time.time())
return pageGet(uri, progress=self.progressBar, uniqueid=time.time()).addCallback(self.putFitsFileScript)
def putDssFile(self, result, live=False):
filedata=result[0]
uniqueid=result[1]
self._parent.callInGui('on_downPopClose', uniqueid)
tmpfile = os.tempnam()+".zip"
f = open(tmpfile,'wb')
f.write(filedata)
f.close()
try:
self._parent.callInGui('on_dssGifDownloaded', tmpfile, live)
except:
pass
def getDssFile(self, ra, dec, x, y, live=False):
uri ='http://archive.stsci.edu/cgi-bin/dss_search?v=poss2ukstu_ir&r='+ra+'&d='+dec+'&e=J2000&h='+x+'&w='
uri +=y+'&f=gif&c=gz&fov=NONE&v3='
#return webutils.getPage(str(uri), progress=self.progressBar, uniqueid=time.time()).addCallback(self.putDssFile, live)
return pageGet(str(uri), progress=self.progressBar, uniqueid=time.time()).addCallback(self.putDssFile, live)
def putUpgrade(self, result, nmd5):
#import md5
try:
import hashlib
md5 = hashlib
md5.new = hashlib.md5
except:
import md5
try:
filedata = result[0]
uniqueid=result[1]
except:
filedata = 'NONE'
uniqueid='unknown'
self._parent.callInGui('on_downPopClose', uniqueid)
m = md5.new(filedata)
cmd5 = str(m.hexdigest())
print nmd5, cmd5
if cmd5 == nmd5.replace("\r", "").replace("\n", ""):
platform = utils.platform()
if platform == 'Windows':
ext = '.exe'
elif platform == 'Linux':
ext = '.run'
elif platform == 'Darwin':
ext = '.dmg'
tmpfile = os.tempnam()+ext
f = open(tmpfile,'wb')
f.write(filedata)
f.close()
self._parent.upgradeDownloadOk(tmpfile)
else:
self._parent.upgradeDownloadFailed()
def getUpgrade(self, upuri, nmd5):
return pageGet(str(upuri), progress=self.progressBar, uniqueid=time.time()).addCallback(self.putUpgrade, nmd5)
def run(self):
if self.keepRunning:
reactor.callLater(self.timing, self.run)
if globals()['isConnected']:
self.wakeUp()
def on_updateFile(self, result):
mver=int(protocol.VERSION)
nver = mver
upuri = ''
nvermd5 = ''
try:
lines = result.split("\n")
platform = utils.platform()
for line in lines:
vars = line.split("|")
if vars[0] == platform:
nver = int(vars[1])
upuri = vars[2]
nvermd5 = vars[3]
except:
pass
self._parent.callInGui('on_versionCheck', mver, nver, upuri, nvermd5)
def checkVersion(self, loop=True):
if self.keepRunning and (self.checkUpdate or not loop):
pageGet('http://skylive.astronomix.org/version.txt').addCallback(self.on_updateFile)
if loop:
reactor.callLater(3600, self.checkVersion)
class skyClientFactory(ClientFactory):
protocol = protocol.clientOldProtocol
autoreconnect = True
def __init__(self, parent, transport, *args, **kwargs):
self._parent = parent
self._transport = transport
self.checkTimer = task.LoopingCall(self.checkConnection)
def clientConnectionFailed(self, connector, reason):
try:
self.checkTimer.stop()
except:
pass
self._parent.connected = False
globals()['isConnected'] = False
#reactor.callLater(2, self._transport.run)
reactor.callLater(0, self._parent.notifyGuiReconnect)
def clientConnectionLost(self, connector, reason):
try:
self.checkTimer.stop()
except:
pass
self._parent.connected = False
globals()['isConnected'] = False
if self.autoreconnect:
reactor.callLater(0, self._parent.notifyGuiReconnect)
else:
reactor.callLater(0, self._parent.notifyGuiDisconnect)
def put(self, msg):
try:
return self.protocolinstance.put(msg)
except:
pass
def connectionMade(self):
self._parent.connected = True
self.checkTimer.start(2)
globals()['isConnected'] = True
def checkConnection(self):
try:
if int(time.time())-int(self.lastrec) > 120:
# Client is disconnected?
self.lastrec = time.time()
self.clientConnectionLost(False, False)
except:
pass
def buildProtocol(self, addr):
p = self.protocol(self)
self.protocolinstance = p
return p
class SSLTransport:
def __init__(self, parent, addr, port=10543):
self._parent = parent
self.addr = addr
self.port = port
self.sslContext = ssl.ClientContextFactory()
self.clientFactory = skyClientFactory(self._parent, self)
def run(self):
self.proxyData = config.get_usrProxy()
if str(self.proxyData['useProxy']).lower() in ['si', 'yes', 'true', True, 1]:
#self.interface = reactor.connectSSL("127.0.0.1", 43335, self.clientFactory, self.sslContext)
self.interface = reactor.connectTCP("127.0.0.1", 43335, self.clientFactory)
#self.interface = reactor.connectSSL(self.addr, self.port, self.clientFactory, self.sslContext)
else:
self.interface = reactor.connectSSL(self.addr, self.port, self.clientFactory, self.sslContext)
#self.interface = reactor.connectTCP(self.addr, 10444, self.clientFactory)
def put(self, msg):
return self.clientFactory.put(msg)
def disconnect(self):
self.clientFactory.autoreconnect = False
self.interface.disconnect()
self.interface = False
#self.interface.transport.loseConnection()
def restart(self):
self.clientFactory.autoreconnect = True
#self.interface.transport.loseConnection()
self.interface.disconnect()
self.interface = False
class skyClient:
connected=False
def __init__(self, parent, ip, transport='SSL'):
self.ip = ip
self.transport = transport
self.parent = parent
#self.gui = gui
def changeTransport(self, transport):
# XXX vediamo se la riconnessione
# e' automatica
# qui dovremmo prima aspettare la disconnessione in
# qualche modo...
if self.connected:
self.disconnect()
self.transport = transport
self.run()
def stop(self):
return self.disconnect()
def disconnect(self):
f=getattr(self, self.transport+'_disconnect')
if f and callable(f):
return f()
def reconnect(self):
f=getattr(self, self.transport+'_reconnect')
if f and callable(f):
return f()
def run(self):
if not self.connected:
f=getattr(self, self.transport+'_run')
if f and callable(f):
return f()
def transportPut(self, msg):
try:
return self.skytransport.put(msg)
except:
pass
def SSL_run(self):
self.skytransport = SSLTransport(self.parent, self.ip)
self.skytransport.run()
def SSL_disconnect(self):
try:
self.skytransport.disconnect()
except:
pass
def SSL_reconnect(self):
try:
self.skytransport.restart()
except:
pass
class ProxyProto(LineReceiver):
next=False
storedata=""
delimiter='\r\n'
def __init__(self, factory):
self.factory = factory
def connectionMade(self):
self.proxyData = config.get_usrProxy()
proxyauth=False
if str(self.proxyData['proxyAuth']).lower() in ['yes', 'si', 'true', True, '1', 1]:
proxyauth = 'Proxy-authorization: Basic '+self.proxyData['proxyAuthStr'].strip()
connect = "CONNECT skylive.astronomix.org:443 HTTP/1.0"
self.sendLine(connect)
if proxyauth:
self.sendLine(proxyauth)
useragent = "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)\r\n"
self.sendLine(useragent)
def lineReceived(self, line):
if self.next:
self.setRawMode()
if len(str(self.storedata)) > 0:
self.transport.write(self.storedata)
self.storedata=""
lines = line.split()
if len(lines) > 1:
if lines[1] == '200':
self.next=True
def rawDataReceived(self, data):
self.factory.receivedData(data)
def write(self, data):
if self.next:
if len(str(self.storedata)) > 0:
self.transport.write(self.storedata)
self.storedata=""
self.transport.write(data)
else:
self.storedata = self.storedata+data
class ProxyFactory(ClientFactory):
protocol = ProxyProto
autoreconnect = True
def __init__(self, parent, *args, **kwargs):
self._parent = parent
def clientConnectionFailed(self, connector, reason):
self._parent.connected = False
globals()['proxyisConnected'] = False
reactor.callLater(0, self._parent.start)
def clientConnectionLost(self, connector, reason):
self._parent.connected = False
globals()['proxyisConnected'] = False
if self.autoreconnect:
reactor.callLater(0, self._parent.start)
def put(self, msg):
try:
return self.protocolinstance.write(msg)
except:
pass
def receivedData(self, data):
self._parent.sendServer(data)
def connectionMade(self):
self._parent.connected = True
globals()['proxyisConnected'] = True
def buildProtocol(self, addr):
p = self.protocol(self)
self.protocolinstance = p
return p
class ProxyLocalServer(Protocol):
def __init__(self, factory):
self.factory = factory
def connectionMade(self):
if not self.factory.connected:
self.factory.startProxy()
self.factory.protocolinstance = self
else:
self.transport.loseConnection()
def connectionLost(self, reason):
self.factory.stopProxy()
def dataReceived(self, data):
self.factory.receivedData(data)
def write(self, data):
self.transport.write(data)
class ProxyLocalFactory(ServerFactory):
protocol=ProxyLocalServer
connected = False
def __init__(self, parent, *args, **kwargs):
self._parent = parent
def startProxy(self):
self.connected = True
self._parent.start()
def stopProxy(self):
self.connected = False
self._parent.stop()
def receivedData(self, data):
self._parent.sendProxy(data)
def buildProtocol(self, addr):
p = self.protocol(self)
self.protocolinstance = p
return p
def put(self, msg):
try:
return self.protocolinstance.write(msg)
except:
pass
class ConnectProxy:
proxy = False
server = False
def __init__(self):
self.proxyfactory = ProxyFactory(self)
self.serverfactory = ProxyLocalFactory(self)
def start(self):
self.proxyData = config.get_usrProxy()
if self.proxyData['proxyUrl'][:8] == 'https://':
self.sslContext = ssl.ClientContextFactory()
self.proxy = reactor.connectSSL(self.proxyData['proxyUrl'][8:], int(self.proxyData['proxyPort']),
self.proxyfactory, self.sslContext)
else:
self.proxy = reactor.connectTCP(self.proxyData['proxyUrl'], int(self.proxyData['proxyPort']), self.proxyfactory)
def stop(self):
if self.proxy:
self.proxyfactory.autoreconnect=False
self.proxy.disconnect()
self.proxy = False
def startServer(self):
self.server = reactor.listenTCP(43335, self.serverfactory)
def stopServer(self):
if self.server:
self.stop()
self.server.stopListening()
def sendProxy(self, data):
self.proxyfactory.put(data)
def sendServer(self, data):
self.serverfactory.put(data)
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
class FakeDriverProtocol(DatagramProtocol):
def datagramReceived(self, line, (host, port)):
try:
line = line.rstrip()[10:][:13]
if len(line) != 0:
self.TwistedLoop.fakeDriverMessage(line)
except:
pass
class FakeDriver:
connector=False
def __init__(self, TwistedLoop):
self.TwistedLoop = TwistedLoop
def startDriver(self):
self.factory = FakeDriverProtocol()
self.factory.TwistedLoop = self.TwistedLoop
self.connector = reactor.listenUDP(43333, self.factory) #, interface='127.0.0.1')
self.TwistedLoop.fakedstarted = True
def stopDriver(self):
if self.connector:
self.connector.stopListening()
self.connector = False
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import Image, ImageOps, ImageDraw, ImageFile
import platform
from skylive.utils import genutils as utils
import levels
import os
from cStringIO import StringIO
from Pycard import graphic
import numpy
class FitsImage:
"""
this class rappresent a fits file image, and provide usefull
functions to transform it to PIL for the viewer and others
to manage fits reductions and transormations
"""
canCompare = False
pilResized = False
def __init__(self, fits, remove=False, forceLowRes=False):
import pyfits
try:
print 'Forced LowRew : ',forceLowRes
self.fit = pyfits.open(fits)
self.fit[0].verify('fix')
if remove:
try:
os.unlink(fits)
except:
pass
except:
raise ValueError("Fits file "+str(fits)+" doesn't exists")
self._getHeaders()
self._getImageData()
self._setCanCompare()
self._setAutoLevels()
if (platform.system() == 'Linux') and (utils.is_eeepc()) or forceLowRes:
self._toPIL((400, 300))
else:
self._toPIL((800, 600))
print "AUTOLEVELS: ", self.autoMinLevel, self.autoMaxLevel
def _getHeaders(self):
self.headers = self.fit[0].header
try:
self.ra = str(self.headers['OBJCTRA']).replace(":", "%20").replace(".", "%20")
self.dec = str(self.headers['OBJCTDEC']).replace(".", "%20")
except:
self.ra = 0
self.dec = 0
try:
self.yfield, self.xfield = self.headers['FOV'].replace(" ","").split("x")
except:
self.yfield, self.xfield = 32, 24
def _getImageData(self):
self.image = self.fit[0].data
self.min = self.image.min()
self.max = self.image.max()
self.med = (self.min + self.max)/256
def _toPIL(self, maxsize=False, scaletype='linear'):
data = self.image
ysize, xsize = data.shape
ToResize = False
self.percresize=100
if maxsize:
xmsize, ymsize = maxsize
yresize = ysize
xresize = xsize
if xsize > xmsize:
xresize = xmsize
yresize = (ysize*xmsize)/xsize
self.percresize = (xmsize*100)/xsize
ToResize = True
if yresize > ymsize:
yresize = ymsize
xresize = (xsize*ymsize)/ysize
self.percresize = (ymsize*100)/ysize
ToResize = True
try:
imgOr = Image.fromarray(data.astype("int32"), 'I', 0, -1)
except:
imgOr = Image.frombuffer("I", (xsize, ysize), data.astype("int32"), "raw", "I", 0, -1)
# why all examples on internet show to get astype("b") (uint8) but we
# need to get it as int32?
#imgOr = Image.fromarray(data.astype("b"), 'L')
#imgOr = Image.frombuffer("L", (xsize, ysize), data.astype("b"), "raw", "L", 0, 0)
self.pilRaw = imgOr
min,max = self.min, self.max
med = self.med
#scale = med / (max - min)
#offset = -min * scale
# changed to use autostretch values!
#
scale = med / (self.autoMaxLevel - self.autoMinLevel)
offset = -self.autoMinLevel * scale
#
imgOrI = imgOr.point(lambda i: i * scale + offset)
imgOrI = ImageOps.grayscale(imgOrI)
self.pilOrI = imgOrI
if ToResize:
self.pilResized = True
img = imgOrI.resize((xresize,yresize))
img2 = imgOr #.resize((xresize,yresize))
xsizeBit = xresize
ysizeBit = yresize
else:
img = imgOrI
xsizeBit = xsize
ysizeBit = ysize
self.pilImage = img
self.xsizeBit = xsizeBit
self.ysizeBit = ysizeBit
def _setCanCompare(self):
try:
if 'OBJCTRA' in self.headers.ascardlist().keys():
self.canCompare = True
print 'CANCOMPARE TRUE'
except:
print 'EXCEPTION IN setCanCompare'
def _setAutoLevels(self):
self.autoMinLevel, self.autoMaxLevel = self.getAutoLevels()
def getAutoLevels(self, method="zscale"):
if method == 'zscale':
return levels.zscale_levels(self.image, 0.1)
elif method == 'percentile':
return levels.percentile_levels(self.image)
else:
return levels.histogram_levels(self.image)
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
zscale_levels and percentile_levels are directly derived ( if not entirely
copied ) from zscale_rande and percentile_range functions contained in the file
fitsimage.py from the wcs2kml project from google code.
Original URL for wcs2kml is http://code.google.com/p/wcs2kml.
For those two function declaration the original copyright, as reported
above, is applied.
Thanks to the Jeremy Brewer, original author of those functions.
Copyright (c) 2005, 2006, 2007, Jeremy Brewer
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* The names of the contributors may not be used to endorse or
promote products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import pointarray
import numpy
def zscale_levels(scidata, contrast=0.25, npoints=600, nrows=120):
"""
Zscale algorithm from Iraf to determine strmin and strmax
level values
scidata -> is a numpy.ndarray data type and shuld be an image,
contrast -> contrast level for zscale
npoints -> number of points of the sampled data
nrows -> number of points per row of the sampled data
Zscale work by using a sample of the total data for performance.
"""
if len(scidata.shape) != 2:
raise ValueError("scidata isn't an image!")
if contrast <= 0:
contrast = 1
if npoints > scidata.size or npoints <= 0:
npoints = int(scidata.size/2)
ncols = int(float(npoints)/float(nrows)+0.5)
xsize, ysize = scidata.shape
rskip = float(xsize-1)/float(nrows-1)
cskip = float(ysize-1)/float(ncols-1)
data=[]
for i in xrange(nrows):
x = int(i*rskip+0.5)
for a in xrange(ncols):
y = int(a*cskip+0.5)
data.append(scidata[x, y])
npixs = len(data)
data.sort()
dmin=min(data)
dmax=max(data)
cpixs=int((npixs+1)/2)
if dmin == dmax:
return dmin, dmax
if npixs % 2 == 0:
med = data[cpixs-1]
else:
med = 0.5*(data[cpixs-1]+data[cpixs])
pixind=map(float, xrange(npixs))
points=pointarray.PointArray(pixind, data, min_err=1.0e-4)
fit=points.sigmaIterate()
nallowed=0
for pt in points.allowedPoints():
nallowed += 1
if nallowed < int(int(npixs)/2):
return dmin, dmax
z1 = med-(cpixs-1)*(fit.slope/contrast)
z2 = med+(npixs-cpixs)*(fit.slope/contrast)
zmin=dmin
if z1 > dmin:
zmin = z1
zmax=dmax
if z2 < dmax:
zmax = z2
if zmin >= zmax:
return dmin, dmax
return zmin, zmax
def percentile_levels(image_data, min_percent=3.0, max_percent=99.0,
num_points=5000, num_per_row=250):
"""
Computes the range of pixel values to use when adjusting the contrast
of FITs images using a simple percentile cut. For efficiency reasons,
only a subsample of the input image data is used.
Input: image_data -- the array of data contained in the FITs image
(must have 2 dimensions)
min_percent -- min percent value between (0, 100)
max_percent -- max percent value between (0, 100)
num_points -- the number of points to use when sampling the
image data
num_per_row -- number of points per row when sampling
"""
if not 0 <= min_percent <= 100:
raise ValueError("invalid value for min percent '%s'" % min_percent)
elif not 0 <= max_percent <= 100:
raise ValueError("invalid value for max percent '%s'" % max_percent)
min_percent = float(min_percent) / 100.0
max_percent = float(max_percent) / 100.0
if len(image_data.shape) != 2:
raise ValueError("input data is not an image")
if num_points > numpy.size(image_data) or num_points < 0:
num_points = 0.5 * numpy.size(image_data)
num_per_col = int(float(num_points) / float(num_per_row) + 0.5)
xsize, ysize = image_data.shape
row_skip = float(xsize - 1) / float(num_per_row - 1)
col_skip = float(ysize - 1) / float(num_per_col - 1)
data = []
for i in xrange(num_per_row):
x = int(i * row_skip + 0.5)
for j in xrange(num_per_col):
y = int(j * col_skip + 0.5)
data.append(image_data[x, y])
data.sort()
zmin = data[int(min_percent * len(data))]
zmax = data[int(max_percent * len(data))]
return zmin, zmax
def histogram_levels(scidata, contrast=0.001):
csum = numpy.cumsum(numpy.histogram(scidata, int(scidata.max())+1, (0, int(scidata.max())+1))[0])
cmax = scidata.size
crange = cmax*contrast
searchParam = [crange, cmax-crange]
strminmax = csum.searchsorted(searchParam)
strmin = strminmax[0]
strmax = strminmax[1]
return strmin, strmax
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
The above part of this file is directly derived from the original authors
of wcs2kml, original URL: http://code.google.com/p/wcs2kml.
The original copyright is reported as in the original file.
"""
# Class for lines
# Copyright (c) 2005, 2006, 2007, Jeremy Brewer
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * The names of the contributors may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Changelog:
#
# 2/7/06 Updated documentation.
"""
Line class module
The Line class is a simple class for holding the slope and intercept of a
line. Line objects are callable -- when called, they evaluate at the given
x value, e.g. y = line(x) gives the value of line at x.
Example Usage.:
l = line.Line(2.0, 3.0)
x1, x2, x3 = 3.14, 0.0, 1.0
print "The line is %s" % l
print "f(%f) = %f" % (x1, l(x1))
print "f(%f) = %f" % (x2, l(x2))
print "f(%f) = %f" % (x3, l(x3))
lp = l.perpToAtX(0.0)
print "Line perpendicular to original at x = 0 is %s" % lp
lp = l.perpToAtY(3.0)
print "Line perpendicular to original at y = 3 is %s" % lp
flip = l.flipXY()
print "Line with flipped x, y is %s" % flip
fit = line.LinearFit(2.0, 3.0, 0.987)
print "Linear fit is %s" % fit
"""
__author__ = "Jeremy Brewer (jeremy.d.brewer@gmail.com)"
__copyright__ = "Copyright 2005, 2006, 2007 Jeremy Brewer"
__license__ = "BSD"
__version__ = "1.0"
class Line(object):
"""Class for describing lines"""
def __init__(self, slope=0.0, intercept=0.0):
"""
Initializes a line to have the given slope and intercept.
Input: slope -- slope of the line
intercept -- intercept of the line
"""
try:
self.slope = float(slope)
except ValueError:
raise TypeError("invalid slope value '%s'" % slope)
try:
self.intercept = float(intercept)
except ValueError:
raise TypeError("invalid intercept value '%s'" % intercept)
def __str__(self):
"""Returns a string representation of the line"""
return "y = %f * x + %f" % (self.slope, self.intercept)
def __call__(self, x):
"""Evaluates a line at a given position x"""
assert isinstance(x, float)
return self.slope * x + self.intercept
def perpToAtX(self, x):
"""Returns a line perpendicular to this line at the given x position"""
assert isinstance(x, float)
perpSlope = -1.0 / self.slope
perpIntercept = x * (self.slope + 1.0 / self.slope) + self.intercept
return Line(perpSlope, perpIntercept)
def perpToAtY(self, y):
"""Returns a line perpendicular to this line at the given x position"""
assert isinstance(y, float)
x = (y - self.intercept) / self.slope
return self.perpToAtX(x)
def flipXY(self):
"""Creates a line where x and y have been flipped"""
if self.slope == 0.0:
raise ZeroDivisionError("cannot flip line with slope = 0")
newSlope = 1.0 / self.slope
newIntercept = -self.intercept / self.slope
return Line(newSlope, newIntercept)
class LinearFit(Line):
"""Class for describing linear fits"""
def __init__(self, slope=0.0, intercept=0.0, r2=0.0):
"""
Initializes a linear fit to have the given slope, intercept, and
correlation coefficient.
Input: slope -- slope of the line
intercept -- intercept of the line
r2 -- correlation coefficient of the line
"""
Line.__init__(self, slope, intercept)
try:
self.r2 = float(r2)
except ValueError:
raise TypeError("invalid r2 value '%s'" % r2)
def __str__(self):
"""Returns a string representation of the linear fit"""
return "y = %f * x + %f, r^2 = %f" % (self.slope, self.intercept,
self.r2)
# testing code
if __name__ == "__main__":
l = Line(2.0, 3.0)
x1, x2, x3 = 3.14, 0.0, 1.0
print "The line is %s" % l
print "f(%f) = %f" % (x1, l(x1))
print "f(%f) = %f" % (x2, l(x2))
print "f(%f) = %f" % (x3, l(x3))
lp = l.perpToAtX(0.0)
print "Line perpendicular to original at x = 0 is %s" % lp
lp = l.perpToAtY(3.0)
print "Line perpendicular to original at y = 3 is %s" % lp
flip = l.flipXY()
print "Line with flipped x, y is %s" % flip
fit = LinearFit(2.0, 3.0, 0.987)
print "Linear fit is %s" % fit
"""
end of wcs2kml part
"""
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
The above part of this file is directly derived from the original authors
of wcs2kml, original URL: http://code.google.com/p/wcs2kml.
The original copyright is reported as in the original file.
"""
#########################################################################
# Class for performing least squares fits
# Copyright (c) 2005, 2006, 2007, Jeremy Brewer
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * The names of the contributors may not be used to endorse or
# promote products derived from this software without specific prior
# written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Changelog:
#
# 3/12/07 Fixed bug in sigmaIterate() where the perpendicular offset distance
# wasn't being used when deciding which points to reject when
# perp_offset=True. Wrote functions distance() and perp_distance()
# to fix this problem. This has a small (10^-3) effect on the final
# fit slope.
#
# 3/9/07 Fixed bug in sigmaIterate() where the max_sigma parameter was
# being ignored (it was always 3). Fixed bugs in how sigmaIterate()
# counted the number of rejections. Now the loop properly terminates
# when all or none of the points are rejected. Added an optional
# initial_fit parameter to sigmaIterate() that allows for
# specification of the first fit line to use when initially
# rejecting points.
"""
The PointArray class is designed for iterative least squares fitting routines
where points must be rejected on each pass. It makes it easy to perform
these fits and to report on which points were actually used in the fitting.
Example Usage:
num_points = 100
x = []
y = []
for i in xrange(num_points - 5):
x.append(float(i))
y.append(float(i + 1))
# create 5 bad points
x.append(15.2)
y.append(65.8)
x.append(56.7)
y.append(14.6)
x.append(23.5)
y.append(67.8)
x.append(12.1)
y.append(30.0)
x.append(4.0)
y.append(50.0)
# create a PointArray
p = pointarray.PointArray(x, y, min_err=1.0e-4)
print "Points:\n%s" % p
fit = p.sigmaIterate()
print "Iterative least squares fit: %s" % fit
print "Rejected points:"
for pt in p.rejectedPoints():
print pt
"""
__author__ = "Jeremy Brewer (jeremy.d.brewer@gmail.com)"
__copyright__ = "Copyright 2005, 2006, 2007 Jeremy Brewer"
__license__ = "BSD"
__version__ = "1.0"
import math
import line
def distance(point, line):
"""
Returns the delta y offset distance between a given point (x, y) and a
line evaluated at the x value of the point.
"""
return point.y - line(point.x)
def perp_distance(point, line):
"""
Returns the perpendicular offset distance between a given point (x, y)
and a line evaluated at the x value of the point.
"""
return (point.y - line(point.x)) / math.sqrt(1.0 + line.slope ** 2)
class Point(object):
"""Class for representing points"""
def __init__(self, x, y, y_err=0.0):
self.x = x
self.y = y
self.y_err = y_err
self.isRejected = False
def __str__(self):
if self.isRejected:
s = "(%f, %f +- %f) R" % (self.x, self.y, self.y_err)
else:
s = "(%f, %f +- %f)" % (self.x, self.y, self.y_err)
return s
def allow(self):
self.isRejected = False
def reject(self):
self.isRejected = True
class PointArray(object):
"""Class for arrays of points"""
def __init__(self, x, y, y_err=None, min_err=1.0e-14):
# check args
assert len(x) == len(y)
assert min_err > 0.0
if y_err:
assert len(x) == len(y_err)
# build a list of y errors that is filtered for the minimum err
err = []
for e in y_err:
if e >= min_err:
err.append(e)
else:
err.append(min_err)
else:
err = [min_err] * len(x)
# create a list of points
self.points = map(Point, x, y, err)
def __str__(self):
return "\n".join(map(str, self.points))
def __len__(self):
return len(self.points)
def __iter__(self):
"""Allows iteration in for statements"""
for point in self.points:
yield point
def allowedPoints(self):
"""Allows iteration over only allowed points"""
for pt in self.points:
if not pt.isRejected:
yield pt
def rejectedPoints(self):
"""Allows iteration over only rejected points"""
for pt in self.points:
if pt.isRejected:
yield pt
def __getitem__(self, i):
return self.points[i]
def __setitem__(self, i, value):
if not isinstance(value, Point):
raise TypeError("object to set is not a Point")
self.points[i] = value
def allowAll(self):
"""
Resets all points to be allowed.
"""
for pt in self.rejectedPoints():
pt.isRejected = False
def leastSquaresFit(self):
"""
Performs a least squares fit on the input data.
"""
S = 0.0
Sx = 0.0
Sy = 0.0
Sxy = 0.0
Sxx = 0.0
Syy = 0.0
# compute sums
for pt in self.allowedPoints():
variance = pt.y_err ** 2
S += 1.0 / variance
Sx += pt.x / variance
Sy += pt.y / variance
Sxx += (pt.x ** 2) / variance
Syy += (pt.y ** 2) / variance
Sxy += (pt.x * pt.y) / variance
# check for all points rejected
if S == 0.0:
return line.LinearFit()
# compute the slope using a technique to minimize roundoff (see
# Numerical Recipes for details)
Stt = 0.0
slope = 0.0
for pt in self.allowedPoints():
t = (pt.x - Sx / S) / pt.y_err
Stt += t ** 2
slope += (t * pt.y) / pt.y_err
slope /= Stt
intercept = (Sy - Sx * slope) / S
r2 = (Sxy * S - Sx * Sy) / \
math.sqrt((S * Sxx - Sx * Sx) * (S * Syy - Sy * Sy))
return line.LinearFit(slope, intercept, r2)
def perpLeastSquaresFit(self):
"""
Performs a perpendicular offset least squares fit on the input data.
"""
S = 0.0
Sx = 0.0
Sy = 0.0
Sxy = 0.0
Sxx = 0.0
Syy = 0.0
# compute sums
for pt in self.allowedPoints():
variance = pt.y_err ** 2
S += 1.0 / variance
Sx += pt.x / variance
Sy += pt.y / variance
Sxx += (pt.x ** 2) / variance
Syy += (pt.y ** 2) / variance
Sxy += (pt.x * pt.y) / variance
# check for all points rejected
if S == 0.0:
return line.LinearFit()
B = ((S * Syy - Sy * Sy) - (S * Sxx - Sx * Sx)) / \
(2.0 * (Sx * Sy - Sxy * S))
# there are two solutions for the slope
m = -B + math.sqrt(B * B + 1.0)
m2 = -B - math.sqrt(B * B + 1.0)
r2 = (Sxy * S - Sx * Sy) / \
math.sqrt((S * Sxx - Sx * Sx) * (S * Syy - Sy * Sy))
# slope for regular least squares fitting
delta = S * Sxx - Sx * Sx
ls_slope = (S * Sxy - Sx * Sy) / delta
# choose the slope that is closest to normal least squares fitting
diff = abs(ls_slope - m)
diff2 = abs(ls_slope - m2)
if diff <= diff2:
slope = m
else:
slope = m2
intercept = (Sy - slope * Sx) / S
return line.LinearFit(slope, intercept, r2)
def stddev(self, fit):
"""
Returns the standard deviation of the difference from the input fit
line for allowed points. Returns -1 if there are too few allowed
points to compute the standard deviation.
"""
count = 0
variance = 0.0
for pt in self.allowedPoints():
# take <y> as the value of the fit point at each point x
delta = pt.y - fit(pt.x)
variance += delta ** 2
count += 1
if count <= 1:
return -1.0
else:
# the variance is bias corrected
variance /= float(count - 1)
sigma = math.sqrt(variance)
return sigma
def perpStddev(self, fit):
"""
Returns the standard deviation of the perpendicular offset difference
from the input fit line for allowed points. Returns -1 if there are
too few allowed points to compute the standard deviation.
"""
count = 0
variance = 0.0
for pt in self.allowedPoints():
# take <y> as the value of the fit point at each point x
delta = (pt.y - fit(pt.x)) / math.sqrt(1.0 + fit.slope ** 2)
variance += delta ** 2
count += 1
if count <= 1:
return -1.0
else:
# the variance is bias corrected
variance /= float(count - 1)
sigma = math.sqrt(variance)
return sigma
def sigmaIterate(self, max_iter=5, max_sigma=3.0, perp_offset=False,
initial_fit=None):
"""
Performs an iterative sigma clipping fit on the input data set. A
least squares line is fit to the data, then points further than
max_sigma stddev away will be thrown out and the process repeated
until no more points are rejected, all points are rejected, or the
maximum number of iterations is passed.
The sigma clipping algorithm uses either standard or perpendicular
offset least squares fitting depending on the perp_offset flag. By
default normal least squares fitting is used.
An optional initial fit to use can be supplied via initial_fit. This
is useful for noisy data where the "true" fit is approximately known
beforehand.
"""
# determine fit algorithm to use
if perp_offset:
lsFit = self.perpLeastSquaresFit
stddev = self.perpStddev
dist = perp_distance
else:
lsFit = self.leastSquaresFit
stddev = self.stddev
dist = distance
# total number of rejected points
total = 0
for pt in self.points:
if pt.isRejected:
total += 1
# initial fit
if initial_fit is None:
fit = lsFit()
else:
fit = initial_fit
for i in xrange(max_iter):
# standard deviation from fit line
three_sigma = max_sigma * stddev(fit)
# number of newly rejected points on each pass
count = 0
# throw away outliers
for pt in self.allowedPoints():
diff = abs(dist(pt, fit))
if diff > three_sigma:
pt.isRejected = True
count += 1
total += count
# exit if none or all of the points were rejected
if count == 0:
break
elif total == len(self.points):
raise ValueError("all points were rejected")
# update the fit
fit = lsFit()
return fit
if __name__ == "__main__":
num_points = 100
x = []
y = []
for i in xrange(num_points - 5):
x.append(float(i))
y.append(float(i + 1))
# create 5 bad points
x.append(15.2)
y.append(65.8)
x.append(56.7)
y.append(14.6)
x.append(23.5)
y.append(67.8)
x.append(12.1)
y.append(30.0)
x.append(4.0)
y.append(50.0)
# create a PointArray
p = PointArray(x, y, min_err=1.0e-4)
#print "Points:\n%s" % p
fit = p.leastSquaresFit()
print "Least squares fit: %s" % fit
fit = p.perpLeastSquaresFit()
print "Perp least squares fit: %s" % fit
fit = p.sigmaIterate()
print "Iterative least squares fit: %s" % fit
print "Rejected points:"
for pt in p.rejectedPoints():
print pt
p.allowAll()
fit = p.sigmaIterate(perp_offset=True)
print "Iterative perp least squares fit: %s" % fit
p.allowAll()
fit = p.sigmaIterate(perp_offset=True, initial_fit=line.Line(1.0, 1.0))
print "Iterative perp least squares fit: %s" % fit
"""
end of the wcs2kml derived part
"""
###########################################################################
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
#import SocketServer
import math
from twisted.protocols.basic import LineReceiver
from twisted.internet.protocol import ServerFactory
from twisted.internet import reactor, main
import sys
try:
if int("".join(sys.version[0:3].split("."))) < 25:
import elementtree.ElementTree as elemtree
else:
import xml.etree.ElementTree as elemtree
except:
import lxml.etree as elemtree
device = """
<defSwitchVector
device='Skylive-NG'
name='CONNECTION'
label='Connection'
group='Communication'
state='Idle'
perm='rw'
rule='OneOfMany'
timeout='0'
>
<defSwitch
name='CONNECT'
label='Connect'>
On
</defSwitch>
<defSwitch
name='DISCONNECT'
label='Disconnect'>
Off
</defSwitch>
</defSwitchVector>
<defNumberVector
device='Skylive-NG'
name='EQUATORIAL_EOD_COORD'
label='Equatorial JNow'
group='Main Control'
state='Idle'
perm='rw'
timeout='0'
>
<defNumber
name='RA'
label='RA H:M:S'
format='%7.8m'
min='0'
max='24'
step='0'>
0
</defNumber>
<defNumber
name='DEC'
label='Dec D:M'
format='%6.8m'
min='-90'
max='90'
step='0'>
0
</defNumber>
</defNumberVector>
<defSwitchVector
device='Skylive-NG'
name='ON_COORD_SET'
label='On Set'
group='Main Control'
state='Idle'
perm='rw'
rule='OneOfMany'
timeout='0'
>
<defSwitch
name='SLEW'
label='Slew'>
On
</defSwitch>
</defSwitchVector>
"""
connected = False
def _DECtoINDI(text):
if text != '+00:00' and text != '-00:00' and text != '-':
d, m = text.split(':')
if (int(m)) != 0:
min = int(m)/60.0
else:
min = 0
if '-' in d:
output = str(int(d)-min)
else:
output = str(int(d)+min)
else:
output = 0
return str(output)
def _RAtoINDI(text):
if text != '00:00:0' and text != '-':
h, m, s = text.split(':')
sec = float('0.'+s)
if (sec+int(m)) != 0:
min = (sec+int(m))/60.0
else:
min = 0
output = str(int(h)+min)
else:
output = 0
return str(output)
def punta(coo):
#print "INDI: Punta "+str(coo)
try:
_parent.udpQueue.put({'udpcmd' : coo})
except:
pass
def _sexagesimal(r):
std = int( math.floor( r ));
r -= float( math.floor( r ));
r *= 60.0;
min = int (math.floor( r ));
r -= float( min);
#r *= 60.0;
sec = r;
output=''+ str(std).zfill(2)+":"+str(min).zfill(2)+"."+str(sec).split('.')[0]
return output;
def _dectext(r):
num = r.split('.')
degr = num[0]
first = str((float('0.'+num[1])*60.0)).split('.')[0]
sec = str(float('0.'+(str((float('0.'+num[1])*60.0)).split('.')[1]))*60.0)
if int(sec.split('.')[1]) > 50:
arr = 1
else:
arr = 0
second = str(int(sec.split('.')[0])+arr)
if int(second) > 60:
second = '00'
first = str(int(first)+1)
if int(first) > 60:
first = '00'
if '-' in degr:
degr = str(int(degr)-1)
else:
degr = str(int(degr)+1)
if '-' in degr:
degr = degr.zfill(3)
else:
degr = degr.zfill(2)
output = ''+degr+':'+first.zfill(2)
return output
# XXX
# This is a very bad and minimal implementation.
# We really need to redoit
#
class INDIProtocol(LineReceiver):
disconnect_forced = False
def lineReceived(self, line):
pass
def rawDataReceived(self, data):
#print 'RECEIVED:', data
tree = elemtree.fromstring('<indi>'+data+'</indi>')
nv = tree.find('newNumberVector')
if nv is not None:
on = nv.findall('oneNumber')
if len(on) == 2:
coo = {}
for num in on:
if num.get('name') in ['RA', 'DEC']:
coo[num.get('name')] = num.text.strip()
if len(coo) == 2:
RA=_sexagesimal(float(coo['RA']))
DEC=_dectext(coo['DEC'])
if '-' not in DEC and '+' not in DEC:
DEC = '+'+DEC
self.factory.TwistedLoop.indiDriverMessage(str(RA)+str(DEC))
def connectionMade(self):
if self.factory.indi_connected:
self.disconnect_forced = True
# only one connection is permitted!
self.transport.loseConnection()
self.__ignoreBuffer = True
self.transport.connectionLost(main.CONNECTION_DONE)
else:
self.factory.indi_connected = True
self.factory.indiclient = self
self.transport.write(device)
self.setRawMode()
self.factory.indiDriver.TwistedLoop.indistarted=True
def connectionLost(self, reason):
if not self.disconnect_forced:
self.factory.indi_connected = False
del self.factory.indiclient
self.disconnect_forced = False
def setTelePos(self, RA, DEC):
try:
telePos = """
<setNumberVector device='Skylive-NG' name='EQUATORIAL_EOD_COORD'>
<oneNumber name='RA' >"""+_RAtoINDI(RA)+"""</oneNumber>
<oneNumber name='DEC' >"""+_DECtoINDI(DEC.replace('*', ':'))+"""</oneNumber>
</setNumberVector>
"""
self.transport.write(telePos)
except:
pass
class INDIDriverFactory(ServerFactory):
indi_connected = False
protocol = INDIProtocol
def setIndiDriver(self, indiDriver):
self.indiDriver = indiDriver
class IndiDriver:
connector = False
def __init__(self, TwistedLoop):
self.TwistedLoop = TwistedLoop
def startDriver(self):
self.factory = INDIDriverFactory()
self.factory.TwistedLoop = self.TwistedLoop
self.factory.setIndiDriver(self)
# XXX Is there any way to get authentication on
# the indi protocol?
# If not, maybe we need to let's users configure a
# white/blacklist of ip or to change the default listen address.
self.connector = reactor.listenTCP(43334, self.factory)
def stopDriver(self):
if self.connector:
self.connector.stopListening()
self.connector = False
def setTelePos(self, RA, DEC):
try:
self.factory.indiclient.setTelePos(RA, DEC)
except:
pass
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
__all__ = ['language', 'it', 'en']
upgradeText="""
A new version of the SkyliveNG client is available.
Do you want to upgrade now?
"""
clientVerSources="""
You are using an install of the client
we can't manage (yet?) by the auto-upgrade system.
Please, proceed with the manual upgrade.
Thanks.
"""
lang = {
'skylive' : {
'menuCheckVersion':'Check upgrades',
'menuFile':'&File',
'menuSaveChat':'Save Chat',
'menuFileExit':'E&xit',
'menuSettings':'Settings',
'menuSettingsLogin':'Login info',
'menuSettingsPreference':'Preference',
'menuLanguages':'Languages',
'menuLanguagesEnglish':'English',
'menuLanguagesItalian':'Italiano',
'menuView':'View',
'menuFitsOpen':'F&its',
'menuMeteoOpen':'M&eteo',
'menuHelp':'Help',
'menuHelpAboutSkyliveNG':'About SkyliveNG',
'menuHelpHelpOnLine':'Online Help',
'Pointing':'Telescope Pointing',
'PhotoInputs':'Photo inputs',
'CCDBox':'Scripts GOTO and Photo',
'StatusBox':'Status',
'StaticBox4':'Guide Star',
'Telescope':'Telescope',
'TScopeCombo':'Telescope1',
'TScopeComboGen':'Telescope%s',
'ChatSend':'Send',
'ButtonN':'N',
'ButtonW':'W',
'ButtonE':'E',
'ButtonS':'S',
'ComboPlanets':'Select',
'PointPlanets':'Planets',
'ComboStars':'Select',
'PointStars':'Stars',
'ComboDouble':'Select',
'PointDouble':'Double',
'ComboMessier':'Select',
'PointMessier':'Messier',
'ComboIC':'Select',
'PointAR1':'RA',
'PointGOTO':'GOTO',
'PointSendToScript':'Send to script',
'PathChoose':'Path',
'LastPhoto':'Last photo',
'BigLive':'Live bigger',
'MakePhoto':'MAKE PHOTO',
'PhotoSendToScript':'Send to script',
'PhotoTXTRepeat':'Repeat',
'PhotoTXTStartnumber':'Start number',
'PhotoTXTFilename':'Filename',
'PhotoTXTGuide':'Guide',
'PhotoTXTFilter':'Filter',
'PhotoTXTExp':'Exp',
'ScriptLoad':'Load',
'ScriptSave':'Save',
'ScriptStart':'Start',
'ScriptStop':'Stop',
'ScriptContinue':'Continue',
'ScriptClear':'Clear',
'ScriptReset':'Reset',
'ScriptStatus':'Waiting for commands...',
'StatusRain':'Weather:',
'StatusDome':'Observatory Dome:',
'StatusObject':'Current object',
'TelescopeCCDTemp':'CCD Temp:',
'MoveRA':'RA:',
'TelescopeFilters':'Filters avaiable:',
'TelescopeGPS':'Telescope Pos: Lat:',
'TelescopeGPS2':'Lon:',
'TelescopeFOW':'Field of view:',
'TelescopeFocal':'FOCAL:',
'TelescopeMODEL':'MODEL:',
'Sponsor':'>> Click HERE <<',
'textHelpSkylive':'Help the skylive project, needs just one click a day!!!',
'lastphototitle':'SkyliveNG: Latest Photo on telescope ',
'fitviewertitle':'SkyliveNG: FIT Viewer',
'fitimagertitle1':'SkyliveNG: FIT Viewer (viewed at ',
'fitimagertitle2':'% of the orig. Size)',
'snapshottitle':'SkyliveNG: Snapshot of telescope ',
'savechattext1':'Save Text file as:',
'savechattext2':'Start pubblic chat text\n',
'savechattext3':'Pubblic chat text saved in ',
'poplivemenu1':'Center',
'poplivemenu2':'Show DSS',
'poplivemenu3':'Turn off Cross',
'poplivemenu4':'Turn on Cross',
'poplivemenu5':'Duplicate Live win.',
'pathchosetext':'Choose new path',
'scriptmenu1':'Delete script',
'scriptsavetext1':'Save Script file as:',
'scriptsavetext2':'Skylive Script Files:',
'scriptloadtext1':'Select Script file :',
'scriptloadtext2':'Skylive Script Files: ',
'downloadtitle':'Downloading ',
'downloadtext':'Downloading 0 kb of ',
'aboutTitle':'About SkyliveNG',
'filenameDialog1':'Choose a new filename',
'filenameDialog2':'Choose Filename',
'dssTitle':'Image From DSS Archive',
'privMenu':'Private message',
'privTitle':'Private Chat with ',
'privSendButton':'Send',
'domeclosed':'Closed',
'domeopen':'Open',
'weatherclean':'Clear',
'weathercloudy':'Cloudy',
'weathervcloudy':'Very Cloudy',
'weatherrain':'Rain',
'unknown':'Unknown',
'statusPhoto': 'Photo',
'statusFilter': 'filter',
'statusRemain': 'ETA',
'statusUpload': 'Uploading photo',
'clientUpdated': 'Your client is updated\nto latest available version.',
'clientVerSources':clientVerSources,
'upgradeFailed': 'Failed to download the upgrade.\nPlease try later.',
'osxUpgradeDone': 'Download aggiornamento riuscito.\nPer favore rilancia il client.',
}, #end skylive
'settings': {
'win1':'Text Pref.',
'win2':'Pointer',
'win3':'Extras',
'win4':'Languages',
'win5':'Proxy',
'win6':'PVT Pref.',
}, #end settings
'textsize': {
'inputsize':'Input Text Size:',
'listsize':'List Text Size:',
'chatsize':'Chat Text Size:',
'textbox':'Text Preference',
'defaultButton':'Default',
'applyButton':'Apply',
'closeButton':'Close',
}, #end textsize
'pointer': {
'colorButton':'Select',
'color':'Pointer Color:',
'pointerBox':'Pointer Preference',
'defaultColorButton':'Default',
'applyColorButton':'Apply',
'closeButton':'Close',
}, #end pointer
'extra' : {
'useARDEC':'Use Compatibility whit LX200 fake driver',
'useINDI':'Use Compatibility whit INDI capable progs',
'closeButton':'Close',
'defaultButton':'Default',
'applyButton':'Apply',
'extraBox':'Extras',
'enableStream':'enable A/V Streaming',
'askStream':'ask before Stream',
}, #end extra
'langs' : {
'langsAvaiableTXT':'Avaiable Languages:',
'closeButton':'Close',
'defaultButton':'Default',
'applyButton':'Apply',
'langsBox':'Languages',
},
'imager' : {
'menuFile':'File',
'menuFileExit':'E&xit',
'menuPhoto':'Adjust',
'menuAdjustPhoto':'A&djust',
'menuInfo':'Info',
'menuInfoPhoto':'Read H&eader',
'ButtonDownload':'Download FIT',
'ButtonSave_FIT':'Save FIT',
'ButtonSave_BMP':'Save BMP',
'ButtonClose':'Close',
'ButtonCompare':'Compare with DSS Search',
'SaveDialog_FIT':'Save FIT file as:',
'SaveDialog_BMP':'Save BMP file as:',
'SaveDialog_SaveAs':'Save Image as:',
'SaveDialog_alertSaveAs':'Please write complete filename with ext (eg: photo.jpg)',
'ButtonSaveAs':'Save as..',
}, #end imager
'downprog' : {
'downBox':'Download Progress',
'downpr':'Progress:'
}, #end downprog
'imageadj' : {
'luminanceTXT':'Luminance',
'contrastTXT':'Contrast',
'adjustBox':'Image Adjust',
'toolsBox':'Tools',
'resetButton':'Reset Change',
'negativeButton':'Negative',
'autoContrastButton':'AutoContrast',
'equalizeButton':'Equalize',
}, #end imageadj
'scriptsgui' : {
'title':'Scripts queue and Status',
'pauseScript':'Pause',
'restartScript':'Resume',
'stoppedScript':'Stopped, click Resume to Restart',
'startScript':'Start scripts',
'SGstatusBox':'Script Status',
'nExpTXT':'Number of Exposure',
'startNTXT':'StartNumber',
'pathTXT':'Path/Filename',
'guideTXT':'Guide',
'filterTXT':'Filter',
'expTXT':'Exp',
'runningBox':'Script Running',
'queueBox':'Scripts in queue',
'scriptExitWarning1':'Warning, you are script running! This action\nmaybe interrupt it!\nYou want close this application and stop script?',
'scriptExitWarning2':'Warning',
'scriptWarning1':'Warning : script loaded contain unmatched command! Please verify and retry',
'scriptStatus1':'acquiring server status....',
'scriptStatus2':'All Done.....',
'scriptStatus3':'No more script.... All Done...',
'scriptStatus4':'Ready.......',
'scriptStatus5':'Busy.....',
'scriptStatus6':"Telescope is Closed!!! Can't execute scripts!",
'scriptStatus7a':'Photo in progress... Making n.',
'scriptStatus7b':' of ',
'scriptStatus8':'Uploading Photo to server....',
'scriptStatus9':'Wait for telescope goto finish. Remains ',
'scriptStatus10':'Skipping saving file due web unselected',
'telestatus1':'Dome is open and Telescope OnLine',
'telestatus2':'Telescope OnLine but Dome is Closed',
'telestatus3':'Dome is Open but Telescope OffLine',
'telestatus4':'All Systems down ... Sorry!',
'telestatus5':'Telescope busy ... Please wait!!!',
'telestatus6':'Telescope Ready....',
'telestatus7':'Starting Scripts... please wait!!!',
'telestatus8':'Waiting for Telescope slew Done',
'telestatus9':'Verifing if Telescope slew Done',
}, #end scriptsgui
'pvt' : {
'pvtBox':'Private Chat Preference',
'useBeep':'Beep when new private message incoming',
'usePopup':'Popup the window when new msg incoming',
'closeButton':'Close',
'applyButton':'Apply',
'defaultButton':'Default',
}, #end pvt
'gui' : {
'upgradeText': upgradeText
}, #end gui
} #end lang
def getLang():
return lang
upgradeText="""
Una nuova versione di SkyliveNG e' disponibile.
Vuoi aggiornare ora?
"""
clientVerSources="""
Stai usando una installazione che non siamo
(ancora?) in grado di gestire in
con autoaggiornamento automatico.
Sei pregato di procedere all'aggiornamento
manualmente. Grazie.
"""
lang = {
'skylive' : {
'menuCheckVersion':'Verifica aggiornamenti',
'menuFile':'&File',
'menuSaveChat':'Salva Chat',
'menuFileExit':'E&sci',
'menuSettings':'Settaggi',
'menuSettingsLogin':'Dati login',
'menuSettingsPreference':'Preferenze',
'menuLanguages':'Lingue',
'menuLanguagesEnglish':'English',
'menuLanguagesItalian':'Italiano',
'menuView':'Apri',
'menuFitsOpen':'F&its',
'menuMeteoOpen':'M&eteo',
'menuHelp':'Aiuto',
'menuHelpAboutSkyliveNG':'Riguardo SkyliveNG',
'menuHelpHelpOnLine':'Help in Linea',
'Pointing':'Puntamento Telescopio',
'PhotoInputs':'Imp. Foto',
'CCDBox':'GOTO e Foto Scripts',
'StatusBox':'Stato',
'StaticBox4':'Stella Guida',
'Telescope':'Telescopio',
'TScopeCombo':'Telescopio1',
'TScopeComboGen':'Telescopio%s',
'ChatSend':'Invia',
'ButtonN':'N',
'ButtonW':'O',
'ButtonE':'E',
'ButtonS':'S',
'ComboPlanets':'Selez.',
'PointPlanets':'Pianeti',
'ComboStars':'Selez.',
'PointStars':'Stelle',
'ComboDouble':'Selez.',
'PointDouble':'Doppie',
'ComboMessier':'Selez.',
'PointMessier':'Messier',
'ComboIC':'Selez.',
'PointAR1':'AR',
'PointGOTO':'GOTO',
'PointSendToScript':'Invia a script',
'PathChoose':'Path',
'LastPhoto':'Foto ultima',
'BigLive':'Live grande',
'MakePhoto':'Avvia Foto',
'PhotoSendToScript':'Invia a script',
'PhotoTXTRepeat':'Ripeti',
'PhotoTXTStartnumber':'Num.Iniz.',
'PhotoTXTFilename':'NomeFile',
'PhotoTXTGuide':'Guida',
'PhotoTXTFilter':'Filtro',
'PhotoTXTExp':'Esp.',
'ScriptLoad':'Carica',
'ScriptSave':'Salva',
'ScriptStart':'Avvia',
'ScriptStop':'Stop',
'ScriptContinue':'Continua',
'ScriptClear':'Pulisci',
'ScriptReset':'Reset',
'ScriptStatus':'In attesa di comandi...',
'StatusRain':'Tempo:',
'StatusDome':'Tetto Osservatorio:',
'StatusObject':'Oggetto attuale',
'TelescopeCCDTemp':'Temp.CCD:',
'MoveRA':'AR:',
'TelescopeFilters':'Filtri dispon.:',
'TelescopeGPS':'Pos. Telescopio: Lat:',
'TelescopeGPS2':'Lon:',
'TelescopeFOW':'Campo :',
'TelescopeFocal':'Focale:',
'TelescopeMODEL':'Modello:',
'Sponsor':'>> Clicca Qui <<',
'textHelpSkylive':'Aiuta il progetto Skylive, basta un click al giorno!!',
'lastphototitle':'SkyliveNG: Ultima foto del tele ',
'fitviewertitle':'SkyliveNG: Visualizzatore di FIT',
'fitimagertitle1':'SkyliveNG: Visualizzatore di FIT (vista al ',
'fitimagertitle2':'% delle dim. originali)',
'snapshottitle':'SkyliveNG: Istantanea del tele ',
'savechattext1':'Salva file di testo con nome:',
'savechattext2':'Inizio testo chat pubblica\n',
'savechattext3':'Testo della chat salvato in ',
'poplivemenu1':'Centra',
'poplivemenu2':'Vedi DSS',
'poplivemenu3':'Puntatore OFF',
'poplivemenu4':'Puntatore ON',
'poplivemenu5':'duplica finestra live',
'pathchosetext':'Scegli un nuovo percorso',
'scriptmenu1':'Elimina script',
'scriptsavetext1':'Salva script con nome:',
'scriptsavetext2':'Skylive Script File:',
'scriptloadtext1':'Seleziona file script:',
'scriptloadtext2':'Skylive Script File: ',
'downloadtitle':'Scaricamento di ',
'downloadtext':'Scaricati 0 kb di ',
'aboutTitle':'Riguardo SkyliveNG',
'filenameDialog1':'Scegli un nuovo nome file',
'filenameDialog2':'Nome file',
'dssTitle':'Immagine da archivio DSS',
'privMenu':'Messaggio privato',
'privTitle':'Chat privata con ',
'privSendButton':'Invia',
'domeclosed':'Chiuso',
'domeopen':'Aperto',
'weatherclean':'Sereno',
'weathercloudy':'Nuvoloso',
'weathervcloudy':'Molto Nuvoloso',
'weatherrain':'Piove',
'unknown':'Sconosciuto',
'statusPhoto': 'Foto',
'statusFilter': 'filtro',
'statusRemain': 'Rimangono',
'statusUpload': 'Attesa invio foto',
'clientUpdated': 'Il tuo client risulta aggiornato\nall\'ultima versione disponibile',
'clientVerSources':clientVerSources,
'upgradeFailed': 'Download aggiornamento fallito.\nPer favore riprovate piu\' tardi.',
'osxUpgradeDone': 'Download aggiornamento riuscito.\nPer favore rilancia il client.',
}, #end skylive
'settings': {
'win1':'Pref.Testo',
'win2':'Puntatore',
'win3':'Extra',
'win4':'Lingue',
}, #end settings
'textsize': {
'inputsize':'Dim Testo Input:',
'listsize':'Dim Test0 Lista:',
'chatsize':'Dim.Testo Chat:',
'textbox':'Preferenze Testo',
'defaultButton':'Predef.',
'applyButton':'Applica',
'closeButton':'Chiudi',
}, #end textsize
'pointer': {
'colorButton':'Scegli',
'color':'Colore Puntatore:',
'pointerBox':'Preferenze Puntatore Live',
'defaultColorButton':'Predef.',
'applyColorButton':'Applica',
'closeButton':'Chiudi',
}, #end pointer
'extra' : {
'useARDEC':'Abilita driver adattati per Skymap/CDC',
'useINDI':'Abilita comp. con programmi INDI',
'closeButton':'Chiudi',
'defaultButton':'Predef.',
'applyButton':'Applica',
'extraBox':'Extra',
'enableStream':'abilita A/V Streaming',
'askStream':'conferma Streaming',
}, #end extra
'langs' : {
'langsAvaiableTXT':'Lingue disponibili:',
'closeButton':'Chiudi',
'defaultButton':'Predef.',
'applyButton':'Applica',
'langsBox':'Lingue',
}, #end langs
'imager' : {
'menuFile':'File',
'menuFileExit':'E&sci',
'menuPhoto':'Regola',
'menuAdjustPhoto':'R&egola',
'menuInfo':'Info',
'menuInfoPhoto':'Leggi H&eader',
'ButtonDownload':'Scarica FIT',
'ButtonSave_FIT':'Salva FIT',
'ButtonSave_BMP':'Salva BMP',
'ButtonClose':'Chiudi',
'ButtonCompare':'Compara con DSS Search',
'SaveDialog_FIT':'Salva FIT con nome:',
'SaveDialog_BMP':'Salva BMP con nome:',
'SaveDialog_SaveAs':'Salva Immagine con nome:',
'SaveDialog_alertSaveAs':'Prego, inserisci il nome del file completo di estensione (es: foto.jpg)',
'ButtonSaveAs':'Salva come..',
}, #end imager
'downprog' : {
'downBox':'Progressione Scaricamento',
'downpr':'Scaricati:'
},
'imageadj' : {
'luminanceTXT':'Luminanza',
'contrastTXT':'Contrasto',
'adjustBox':'Regolazioni immagine',
'toolsBox':'Strumenti',
'resetButton':'Ripristina',
'negativeButton':'Negativo',
'autoContrastButton':'AutoContrasto',
'equalizeButton':'Equalizza',
}, #end imageadj
'scriptsgui' : {
'title':'Script in coda e Status',
'pauseScript':'Pausa',
'startScript':'Avvia scripts',
'SGstatusBox':'Status degli Script',
'nExpTXT':'Numero di foto',
'startNTXT':'Numero iniz.',
'pathTXT':'Path/NomeFile',
'guideTXT':'Guida',
'filterTXT':'Filtro',
'expTXT':'Esp',
'runningBox':'Script in esecuzione',
'queueBox':'Script in coda',
'scriptExitWarning1':'Attenzione, hai ancora in esecuzione degli script.\n Chiudendo li interromperai!\nVuoi chiudere questa finestra ed interrompere gli script?',
'scriptExitWarning2':'Attenzione',
'scriptWarning1':'Attenzione, lo script contiene dei comandi sconosciuti\nPer favore verifica e ritenta!',
'scriptStatus1':'Acquisizione stato telescopio...',
'scriptStatus2':'Tutto completato...',
'scriptStatus3':'Non ci sono script... Tutto completato...',
'scriptStatus4':'Pronto.....',
'scriptStatus5':'Occupato.....',
'scriptStatus6':"Telescopio chiuso! Impossibile eseguire script!",
'scriptStatus7a':'Foto in corso.. Scatto n.',
'scriptStatus7b':' di ',
'scriptStatus8':'Caricamento foto sul server...',
'scriptStatus9':'Attendere che il tele si fermi. Rimangono ',
'scriptStatus10':'File non salvato in quanto selezionato Web',
'telestatus1':'Tetto aperto e Telescopio OnLine',
'telestatus2':'Telescopio OnLine ma Tetto Chiuso',
'telestatus3':'Tetto Aperto ma Telescopio OffLine',
'telestatus4':'Spiacenti : Sistema Spento!',
'telestatus5':'Telescopio occupato... Attendere Prego!',
'telestatus6':'Telescopio Pronto.....',
'telestatus7':'Avvio Scripts in Corso... Attendere!',
'telestatus8':'Posizionamento Telescopio in Corso .. Attendere!',
'telestatus9':'Verifica fine posizionamento..',
}, #end scriptsgui
'pvt' : {
'pvtBox':'Preferenze Chat Privata',
'useBeep':"Beep all'arrivo di un nuovo messaggio",
'usePopup':"Popup all'arrivo di un nuovo messaggio",
'closeButton':'Chiudi',
'applyButton':'Applica',
'defaultButton':'Predef.',
}, #end pvt
'gui' : {
'upgradeText': upgradeText
}, #end gui
} #end lang
def getLang():
return lang
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import en
import os, sys
class Language:
def on_initialize(self, event):
pass
def setLang(self, select):
try:
path = os.path.normpath('skylive/lang')
if not path in sys.path:
sys.path.append(path)
#usrLang = __import__(select)
langmod = __import__('skylive.lang', globals(), locals(), [select], -1)
usrLang = getattr(langmod, select)
self.langDict = usrLang.getLang()
except:
self.langDict = en.getLang()
self.excLang = en.getLang()
def findGui(self, gui):
if self.langDict[gui]:
guiDict = self.langDict[gui]
else:
guiDict = self.excLang[gui]
return guiDict
def findItemText(self, lang= False, gui=False, item=False):
if lang and gui and item:
self.setLang(lang)
try:
itemText = self.findGui(gui)[item]
except:
itemText = self.excLang[gui][item]
return itemText
else:
return False
Lang = Language()
def getItemText(lang=False, gui=False, item=False):
return Lang.findItemText(lang, gui, item)
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from Pycard.twistedsupport.twistedThreadModel import TwistedThreadApplication
import conn, config #, audio
import fakedriver, indidriver
from twisted.internet import reactor
import time
import protocol
from utils import genutils as utils
import subprocess
import sys, os
class skyLive(TwistedThreadApplication):
skyClient = False
tsdiff = 0
def __init__(self, *args, **kwargs):
TwistedThreadApplication.__init__(self, *args, **kwargs)
self.HTTPDownloader = conn.HTTPDownloader(self, 5)
#self.AudioStream = audio.AudioStream()
#self.AudioStream.play("http://skylive3.astronomix.org:8000/skylive.ogg")
#self.AudioStream.play("http://giss.tv:8000/pablito.ogg")
self.srvproto = protocol.ServerComm(self)
self.srvproto.AuthString(str(config.getUsername()), str(config.getPassword()))
def on_skyClientCommand(self, cmd, *args, **kwargs):
try:
f = getattr(self, cmd)
except:
f = False
if f and callable(f):
return f(*args, **kwargs)
else:
self.callInGui('on_'+cmd, *args, **kwargs)
def on_scriptCommand(self, cmd, *args, **kwargs):
try:
f = getattr(self, cmd)
except:
f = False
if f and callable(f):
return f(*args, **kwargs)
else:
self.callInGui('script_Command', 'on_'+cmd, *args, **kwargs)
def setTelescopeLiveUri(self, *args, **kwargs):
urilist = args[0][0]
interval = args[0][1]
try:
self.HTTPDownloader.setLiveUri(urilist)
self.HTTPDownloader.setTiming(int(interval))
self.HTTPDownloader.wakeUp()
except:
pass
def imgDownloader(self, cmd='start'):
if cmd in ['start', 'stop']:
if cmd == 'start':
self.HTTPDownloader.keepRunning = True
self.HTTPDownloader.run()
else:
self.HTTPDownloader.keepRunning = False
def checkUpgrade(self, loop=True):
try:
self.HTTPDownloader.checkVersion(loop)
except:
pass
def stopCheckUpgrade(self):
try:
self.HTTPDownloader.checkUpdate = False
except:
pass
def PingReq(self, tsserver):
#print 'PING', tsserver
now = int(time.time())
self.tsdiff = now-int(tsserver)
try:
self.HTTPDownloader.setTSDiff(self.tsdiff)
except:
pass
self.sendNetworkData(self.srvproto.sendPong())
def changeTelescope(self, tscope):
self.HTTPDownloader.tscope=tscope
#self.HTTPDownloader.wakeUp()
def getLastPhoto(self):
self.HTTPDownloader.getLastPhoto()
def downloadFits(self, telescope):
self.HTTPDownloader.getFitsFile(telescope)
def downloadUpgrade(self, upuri, nvermd5):
self.HTTPDownloader.getUpgrade(upuri, nvermd5)
def upgradeDownloadFailed(self):
self.callInGui('upgradeDownloadFailed')
def upgradeDownloadOk(self, installer):
plat = utils.platform()
if plat == 'Windows':
mydir = os.path.normpath(os.path.abspath(os.path.dirname(sys.executable)))
subprocess.Popen(installer+" /SP- /SILENT /SUPPRESSMSGBOXES /DIR=\""+mydir+"\"")
elif plat == 'Linux':
subprocess.Popen("sh "+installer+" UPGRADE", shell=True, preexec_fn = os.setsid)
self.callInGui('on_StopClient')
elif plat == 'Darwin':
hdu = subprocess.Popen("hdiutil attach "+installer, shell=True, stdout=subprocess.PIPE)
out = hdu.communicate()[0]
lines = out.split("\n")
imagepath = False
for line in lines:
if len(line.split()) >= 3 and len(line.split()[2]) > 9 and line.split()[2][:9] == '/Volumes/':
imagepath = line.split()[2].replace("\n", "")
if imagepath:
try:
tmpfile = os.tempnam()+".sh"
f = open(imagepath+"/UPGRADE.sh", "r")
c = f.read()
f.close()
f = open(tmpfile, "w")
f.write(c)
f.close()
subprocess.Popen("sh "+tmpfile+" "+imagepath, shell=True, preexec_fn = os.setsid)
#subprocess.Popen("cp "+imagepath+"/UPGRADE.sh /tmp/", shell=True, stdout=subprocess.PIPE)
#subprocess.Popen("sh /tmp/UPGRADE.sh "+imagepath, shell=True, preexec_fn = os.setsid)
self.callInGui('on_StopClient')
except:
print 'UPGRADE FAILED'
self.callInGui('upgradeDownloadFailed')
#sascript = 'exec osascript <<\EOF\ndo shell script "sh '+tmpfile+'" with administrator privileges'
#sascript +="\nEOF\nrm -f "+tmpfile+" "+tmpfile2
#sascript +="\nhdiutil detach "+imagepath+"\nrm -f "+installer
#sascript +="\nmydir+"/Contents/MacOS/skylive-ng
else:
self.callInGui('upgradeDownloadFailed')
else:
print 'I CAN\'T UPGRADE, SORRY.'
def downloadDss(self, ra, dec, x, y, live=False):
self.HTTPDownloader.getDssFile(ra, dec, x, y, live)
def serverConnect(self, addr, timeout=0):
self.skyProxyServer = conn.ConnectProxy()
self.proxyData = config.get_usrProxy()
if str(self.proxyData['useProxy']).lower() in ['si', 'yes', 'true', True, 1]:
try:
self.skyProxyServer.startServer()
if int(timeout) < 3:
timeout=1
except:
pass
if self.skyClient:
self.skyClient.stop()
self.skyClient = conn.skyClient(self, addr)
if timeout == 0:
self.skyClient.run()
else:
reactor.callLater(timeout, self.skyClient.run)
def serverDisconnect(self):
try:
self.skyProxyServer.stopServer()
except:
pass
print 'Disconnect called'
try:
self.skyClient.stop()
except:
pass
self.skyClient = False
def forcedExit(self):
self.ExitLoop()
def serverReconnect(self):
print 'Reconnect called'
self.skyClient.reconnect()
def sendNetworkData(self, data):
self.skyClient.transportPut(data)
def scriptGetFitFile(self, tscope):
self.HTTPDownloader.getFitsScript(tscope)
def startFakeDriver(self):
print 'Starting SkyMap Fakedriver'
if not hasattr(self, 'faked'):
self.faked = fakedriver.FakeDriver(self)
if not hasattr(self, 'fakedstarted'):
self.fakedstarted = False
if not self.fakedstarted:
self.faked.startDriver()
def stopFakeDriver(self):
print 'Stopping SkyMap Fakedriver'
if hasattr(self, 'faked'):
if self.fakedstarted:
self.faked.stopDriver()
def fakeDriverMessage(self, msg):
#self.WxLoop.on_udpcmd(msg)
self.callInGui('on_udpcmd', msg)
def startINDIDriver(self):
print 'Starting INDI support'
if not hasattr(self, 'indi'):
self.indi = indidriver.IndiDriver(self)
if not hasattr(self, 'indistarted'):
self.indistarted = False
if not self.indistarted:
self.indi.startDriver()
def stopINDIDriver(self):
print 'Stopping INDI support'
if hasattr(self, 'indi'):
if self.indistarted:
self.indi.stopDriver()
def sendINDITelePos(self, ra, dec):
if hasattr(self, 'indi'):
if self.indistarted:
self.indi.setTelePos(ra, dec)
def indiDriverMessage(self, msg):
#self.WxLoop.on_indicmd(msg)
self.callInGui('on_indicmd', msg)
def notifyGuiReconnect(self):
self.callInGui('on_LoseConnection', True)
def notifyGuiDisconnect(self):
try:
self.callInGui('on_LoseConnection', False)
except:
pass
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import wx
import platform
from twisted.protocols.basic import LineReceiver
import time
VERSION="156"
class ProtoParser:
def __init__(self):
self.separator="#^#"
self.terminator="\r\n"
def ParseTelescopeConf(self, str):
tscope = {}
exploded = self._explode(str)
tscope["model"] = exploded[0]
tscope["focal"] = exploded[1]
tscope["field"] = exploded[2]
tscope["ccd"] = exploded[3]
tscope["filters"] = exploded[4]
tscope["BOH"] = exploded[5]
tscope["archiveurl"] = exploded[6]
tscope["statusurl"] = exploded[7]
return tscope
def ParseConfigList(self, filecont):
return filecont.replace("\r", "").split("*\n")
def ParseLX200CatalogFromSkylive(self, catlist):
res = {}
for entry in catlist:
res[entry.replace(entry[len(entry)-4:], '')]=entry.replace(entry[:len(entry)-4], '')
return res
def parseCommand(self, string):
expl = self._explode(string)
args = []
for arg in expl[2:]:
args.append(arg)
return {'cmd': expl[1], 'args': args, 'from': expl[0]}
def _explode(self, string):
return string.split(self.separator)
class ServerComm:
def __init__(self, parent):
self._parent = parent
self.parser = ProtoParser()
self.separator = self.parser.separator
def AuthString(self, user="", pwd=""):
self.user = user
self.pwd = pwd
self.msginit = self.user + self.separator + self.pwd + self.separator
def ParseServerMsg(self, msg):
#print msg
cmd = self.parser.parseCommand(msg)
ret = False
ret2 = False
if cmd['cmd'] == 'Autorizzazione':
if cmd['args'][0] == 'NonTrovato':
ret = {'AuthFromServer': None}
else:
ret = {'AuthFromServer': True}
if cmd['args'][1] == 'Admin':
self._parent.on_skyClientCommand('setAdminPriv', 'Admin')
elif cmd['cmd'] == 'UserList':
ret = {'updateUserList': cmd['args'][0].split("*!*")}
elif cmd['cmd'] == 'YourName':
ret = {'setMyUsername': cmd['args'][0]}
elif cmd['cmd'] == 'ChatMessage':
ret = {'incomingChat': [cmd['from'], cmd['args'][0]]}
elif cmd['cmd'] == 'OpenWebLink':
ret = {'incomingWebLink': [cmd['args'][0]]}
elif cmd['cmd'] == 'BigLive':
ret = {'incomingBigLive': True}
elif cmd['cmd'] == 'Messaggio':
ret = {'incomingPrivChat': [cmd['from'], cmd['args'][0]]}
elif cmd['cmd'] == 'HtmlMessage':
ret = {'incomingHtmlMessage': [cmd['from'], cmd['args'][0], cmd['args'][1], cmd['args'][2]]}
elif cmd['cmd'] == 'Status':
try:
ret = {'statusMessageFromServer': [cmd['args'][0].split("**")[0],
cmd['args'][0].split("**")[1].split("+")[0],
"+"+cmd['args'][0].split("**")[1].split("+")[1]]}
#ret2 = ret
except:
ret = {'statusMessageFromServer': [cmd['args'][0].split("**")[0],
cmd['args'][0].split("**")[1].split("-")[0],
"-"+cmd['args'][0].split("**")[1].split("-")[1]]}
#ret2 = ret
elif cmd['cmd'] == 'CCDTEMP':
ret = {'CCDTemp': cmd['args'][0]}
elif cmd['cmd'] == 'PhotoReadyNO':
# This message shuld be generated when an exposition is
# terminated and the file is to be uploaded to the web server
ret = {'photoStatus': 'notReady'}
ret2 = ret
elif cmd['cmd'] == 'PhotoReadyYES':
# when we get this message the photo is ready to be downloaded
ret = {'photoStatus': 'Ready'}
ret2 = ret
elif cmd['cmd'] == 'RequestData':
ret = {'requestData': True}
#to fit new server messages the follow strings
elif cmd['cmd'] == 'TelescopeFeat':
ret = {'telescopeFeat': cmd['args'][0]}
elif cmd['cmd'] == 'Dome':
ret = {'domeStatus' : cmd['args'][0]}
elif cmd['cmd'] == 'Wheather':
ret = {'rainStatus' : cmd['args'][0]}
elif cmd['cmd'] == 'Object':
ret = {'objName' : cmd['args'][0]}
elif cmd['cmd'] == 'Ping':
ret = {'PingReq' : cmd['args'][0]}
elif cmd['cmd'] == 'LonLat':
ret = {'LonLat' : cmd['args'][0]}
elif cmd['cmd'] == 'availableStars':
ret = {'setStars' : cmd['args'][0]}
elif cmd['cmd'] == 'availableDoubles':
ret = {'setDoubles' : cmd['args'][0]}
elif cmd['cmd'] == 'GuideError':
ret = {'setError' : [cmd['args'][0], cmd['args'][1]]}
elif cmd['cmd'] == 'NTel':
ret = {'setTscopeCombo' : cmd['args'][0]}
elif cmd['cmd'] == 'setCross':
ret = {'activeCicerone' : [cmd['args'][0], cmd['args'][1]]}
elif cmd['cmd'] == 'TeleON':
ret = {'TeleLink' : 'TeleON'}
ret2 = ret
elif cmd['cmd'] == 'TeleOFF':
ret = {'TeleLink' : 'TeleOFF'}
ret2 = ret
elif cmd['cmd'] == 'TeleFree':
ret2 = {'TeleStatus' : 'Free'}
elif cmd['cmd'] == 'TeleBusy':
ret2 = {'TeleStatus' : 'Busy'}
elif cmd['cmd'] == 'TeleBinning':
ret = {'setBins' : cmd['args'][0]}
elif cmd['cmd'] == 'StopClient':
ret = {'StopClient': True}
elif cmd['cmd'] == 'TelescopeLiveUri':
ret = {'setTelescopeLiveUri': [cmd['args'][0].split("**"), cmd['args'][1]]}
elif cmd['cmd'] == 'ExposureNone':
ret = {'setExposureNone': True}
elif cmd['cmd'] == 'ExposureUpload':
ret = {'setExposureUpload': [cmd['args'][1]]+cmd['args'][0].split("**")}
elif cmd['cmd'] == 'ExposureRunning':
ret = {'setExposureRunning': [cmd['args'][1]]+cmd['args'][0].split("**")}
elif cmd['cmd'] == 'setFWHM':
ret = {'setFWHM': cmd['args'][0]}
elif cmd['cmd'] == 'Streaming':
ret = {'Streaming': cmd['args'][0]}
elif cmd['cmd'] == 'ForceStreaming':
ret = {'ForceStreaming': cmd['args'][0]}
#end new messages
if ret:
self._parent.on_skyClientCommand(ret.keys()[0], ret[ret.keys()[0]])
if ret2:
self._parent.on_scriptCommand(ret2.keys()[0], ret2[ret2.keys()[0]])
return msg
def MsgFormat(self, command, args=[]):
msg = self.msginit + command
for arg in args:
msg = msg + self.separator + arg.encode('iso-8859-16')
return msg
def MsgLogin(self):
return self.MsgFormat('InvioDati', [VERSION, ' '.join(platform.uname())+platform.platform()])
def changeTelescope(self, tscope):
return self.MsgFormat('CambioTele', [tscope, 'NULL'])
def chatSendPublic(self, msg):
return self.MsgFormat('MSGTOALL', [msg, 'NULL'])
def chatSendPrivate(self, touser, msg):
return self.MsgFormat('MSGPRIVATO', [msg, touser])
def makePhoto(self, exp="001", filter="R", guide="0", bin="1", aflat="0", adark="0", web="0"):
photostring = str(exp).zfill(3)+filter+str(guide)+str(bin)+str(aflat)+str(adark)+str(web)
return self.MsgFormat('COMANDO', ['FOTO'+photostring, 'NULL'])
def KillUser(self, user):
return self.MsgFormat('ADMINACTION', ['KILL', user])
def BanUser(self, user):
return self.MsgFormat('ADMINACTION', ['BAN', user])
def MuteUser(self, user):
return self.MsgFormat('ADMINACTION', ['MUTE', user])
def StopUser(self, user):
return self.MsgFormat('ADMINACTION', ['STOP', user])
def sendPong(self):
return self.MsgFormat('Pong', ['null', 'NULL'])
def stopPhoto(self):
return self.makePhoto()
def moveNorth(self):
return self.MsgFormat('COMANDO', ['NORD', 'NULL'])
def moveSouth(self):
return self.MsgFormat('COMANDO', ['SUD', 'NULL'])
def moveEast(self):
return self.MsgFormat('COMANDO', ['EST', 'NULL'])
def moveWest(self):
return self.MsgFormat('COMANDO', ['WEST', 'NULL'])
def moveCenter(self, movestr):
return self.MsgFormat('COMANDO', ['CENTRA', movestr])
def moveToTarget(self, target):
try:
planets={'Mercury': 'Pianeta0901Mercury',
'Venus': 'Pianeta0902Venus',
'Moon': 'Pianeta0903Moon',
'Mars': 'Pianeta0904Mars',
'Jupiter': 'Pianeta0905Jupiter',
'Saturn': 'Pianeta0906Saturn',
'Uranus': 'Pianeta0907Uranus',
'Neptune': 'Pianeta0908Neptune',
'Pluto': 'Pianeta0909Pluto'}
if target[0] and target[1]:
if target[1] != 'Select':
if target[0] == 'Planets':
moveto=planets[target[1]]
elif target[0] == 'Messier':
moveto='messier'+target[1]
elif target[0] == 'NGC':
moveto='CNGC'+target[1]
elif target[0] == 'IC':
moveto='IC'+target[1]
elif target[0] == 'Double':
moveto='Pianeta'+self._parent.doublelist[target[1]]+target[1]
elif target[0] == 'Stars':
moveto='Pianeta'+self._parent.starlist[target[1]]+target[1]
elif target[0] == 'AR':
moveto='MUOVI'+target[1]
else:
moveto=None
if moveto:
return self.MsgFormat('COMANDO', [moveto, 'NULL'])
return False
except:
return False
def sendCross(self, x, y):
return self.MsgFormat('crossOn', [str(x), str(y)])
def sendTeleStatus(self):
return self.MsgFormat('TeleStatus', ['null', 'NULL'])
def sendPhotoRunning(self, tnum):
return self.MsgFormat('PhotoRunning', [str(tnum), 'NULL'])
def sendFocus(self, type):
#print "SENDFOCUS", type
return self.MsgFormat('Focus', [type, 'NULL'])
def sendSync(self):
return self.MsgFormat('SYNC', ['null', 'NULL'])
class clientOldProtocol(LineReceiver):
delimiter = chr(222)
def __init__(self, factory):
#LineReceiver.__init__(self, *args, **kwargs)
self.factory = factory
self.parser = ServerComm(self.factory._parent)
def lineReceived(self, data):
#import thread
self.factory.lastrec = time.time()
datain = data.replace(chr(221), '')
self.parser.ParseServerMsg(unicode(datain, 'iso-8859-16', errors='replace')).encode('iso-8859-16', 'ignore')
def write(self, str=None, noTerminator=False):
if str is not None:
realstr = str
if not noTerminator:
realstr = str+"\r\n"
try:
# XXX Fucking protocol. We have a terminator on the server side,
# and we don't have the same one on the client side.
# I hope to remove very SOON this protocol.
#self.sendLine(realstr)
self.transport.write(realstr)
except:
print time.time(), ' exception in push message on asynchat (conn.py)'
def put(self, msg):
if msg == 'STOP':
self.close()
else:
noTerminator=False
try:
# ONLY because MSGPRIVATO isn't "standard"
if msg.split("#^#")[2] == 'MSGPRIVATO':
noTerminator=True
except:
pass
self.write(msg, noTerminator)
def connectionMade(self):
self.factory.protocolinstance = self
self.factory.connectionMade()
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
import os
def rmdir(dir):
for root, dirs, files in os.walk(dir, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
def is_eeepc():
# xandros seem to don't have hald... how we can do?
#return True
if os.path.isfile('/sys/class/dmi/id/board_serial'):
try:
# hal-get-property --udi '/org/freedesktop/Hal/devices/computer'
# --key system.hardware.serial
f=os.popen4('hal-get-property --udi "/org/freedesktop/Hal/devices/computer" --key system.hardware.serial')
res = f[1].read(5)
f[1].close()
f[0].close()
if res == 'EeePC':
return True
except:
pass
return False
def is_frozen():
import imp, sys
return (hasattr(sys, "importers")
or imp.is_frozen("__main__")
or hasattr(sys, "frozen")
)
def platform():
import wx
plat = wx.PlatformInfo
if '__WXMAC__' in plat:
return 'Darwin'
if '__WXGTK__' in plat:
# And other gtk?
return 'Linux'
if '__WXMSW__' in plat:
return 'Windows'
else:
# By default get Linux
return 'Linux'
"""
Copyright (C) 2007-2009 Franco Lanza <nextime@nexlab.it>
Copyright (C) 2007-2009 Sandro Aliano <ita595@hotmail.com>
Copyright (C) 2007-2009 Ivan Bellia <skylive@skylive.it>
Web site: http://www.astronomix.org/trac/Skylive-NG
This file is part of Skylive-NG.
Skylive-NG is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Skylive-NG is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Skylive-NG. If not, see <http://www.gnu.org/licenses/>.
"""
from twisted.web import client, error
from twisted.internet import reactor, defer, task
from twisted.python import failure
import gzip
import StringIO
import time
class HTTPPageGetter(client.HTTPPageGetter):
rectimeout = 15
checkTimeout = False
# XXX Serve per farlo diventare 1.1??
#def sendCommand(self, command, path):
# self.transport.write('%s %s HTTP/1.1\r\n' % (command, path))
def lineReceived(self, *args, **kwargs):
self.lastrec = time.time()
return client.HTTPPageGetter.lineReceived(self, *args, **kwargs)
def rawDataReceived(self, *args, **kwargs):
self.lastrec = time.time()
return client.HTTPPageGetter.rawDataReceived(self, *args, **kwargs)
def connectionMade(self, *args, **kwargs):
self.lastrec = time.time()
if self.checkTimeout:
try:
self.checkTimeout.stop()
except:
pass
self.checkTimeout = task.LoopingCall(self.timeoutCheck)
self.checkTimeout.start(1)
return client.HTTPPageGetter.connectionMade(self, *args, **kwargs)
def timeoutCheck(self):
now = time.time()
if int(now)-int(self.lastrec) > self.rectimeout:
self.transport.loseConnection()
def connectionLost(self, *args, **kwargs):
if self.checkTimeout:
try:
self.checkTimeout.stop()
except:
pass
return client.HTTPPageGetter.connectionLost(self, *args, **kwargs)
def handleStatus_301(self):
l = self.headers.get('location')
if not l:
self.handleStatusDefault()
return
url = l[0]
if self.followRedirect:
scheme, host, port, path = \
client. _parse(url, defaultPort=self.transport.getPeer().port)
self.factory.setURL(url)
if self.factory.scheme == 'https':
from twisted.internet import ssl
contextFactory = ssl.ClientContextFactory()
reactor.connectSSL(self.factory.host, self.factory.port,
self.factory, contextFactory)
else:
if self.factory.proxy_host:
if not self.factory.proxy_port:
proxy_port = 80
reactor.connectTCP(self.factory.proxy_host, self.factory.proxy_port, self.factory)
else:
reactor.connectTCP(self.factory.host, self.factory.port,
self.factory)
else:
self.handleStatusDefault()
self.factory.noPage(
failure.Failure(
error.PageRedirect(
self.status, self.message, location = url)))
self.quietLoss = 1
self.transport.loseConnection()
handleStatus_302 = lambda self: self.handleStatus_301()
class HTTPPageGetterProgress(HTTPPageGetter):
trasmittingPage = 0
pageData = ""
def handleStatus_200(self, partialContent=0):
HTTPPageGetter.handleStatus_200(self)
self.trasmittingPage = 1
def handleStatus_206(self):
self.handleStatus_200(partialContent=1)
def handleResponsePart(self, data):
self.pageData += data
if self.trasmittingPage:
try:
self.factory.pagePart(data)
except:
pass
def handleResponseEnd(self):
if self.trasmittingPage:
self.trasmittingPage = 0
self.factory.page(self.pageData)
self.factory.pageData = ""
if self.failed:
self.factory.noPage(
failure.Failure(
error.Error(
self.status, self.message, None)))
self.transport.loseConnection()
class HTTPPageGetterProgressStream(HTTPPageGetterProgress):
def handleResponsePart(self, data):
#self.pageData += data
if self.trasmittingPage:
try:
self.factory.pagePart(data)
except:
pass
class HTTPClientFactory(client.HTTPClientFactory):
protocol = HTTPPageGetter
def __init__(self, url, method='GET', postdata=None, headers=None,
agent="SkyliveNG Client (http://www.skylive.it)", timeout=0, cookies=None,
followRedirect=1, proxy_host = None, proxy_port = 80):
if proxy_host:
self.has_proxy = True
else:
self.has_proxy = False
self.proxy_host = proxy_host
self.proxy_port = proxy_port
self.myurl = url
client.HTTPClientFactory.__init__(self, url, method, postdata, headers,
agent, timeout, cookies,
followRedirect)
def setURL(self, url):
client.HTTPClientFactory.setURL(self, url)
if self.has_proxy:
self.path = url
def page(self, page):
encoding = self.response_headers.get("content-encoding")
if encoding:
io = StringIO.StringIO(page)
fp = gzip.GzipFile(fileobj = io)
page = fp.read()
fp.close()
#client.HTTPClientFactory.page(self, page)
if self.waiting:
self.waiting=0
res=page
if self.uniqueid:
res=(page, self.uniqueid)
self.deferred.callback(res)
class HTTPClientFactoryProgress(HTTPClientFactory):
protocol = HTTPPageGetterProgress
def __init__(self, url, progresscall=False, *args, **kwargs):
self.progresscall = progresscall
HTTPClientFactory.__init__(self, url, *args, **kwargs)
def gotHeaders(self, headers):
if self.status == '200':
if headers.has_key('content-length'):
self.totalLength = int(headers['content-length'][0])
else:
self.totalLength= 0
self.currentLength = 0.0
return HTTPClientFactory.gotHeaders(self, headers)
def pagePart(self, data):
if self.status=='200':
self.currentLength += len(data)
if self.totalLength and int(self.totalLength) > 0:
percent = "%d/%dK" % (self.currentLength/1000,
self.totalLength/1000)
if self.totalLength:
percent += "- %i%%" % (
(self.currentLength/self.totalLength)*100)
else:
self.totalLength = 0
if callable(self.progresscall):
try:
if self.uniqueid:
self.progresscall(data, self.currentLength, self.totalLength, self.uniqueid)
else:
self.progresscall(data, self.currentLength, self.totalLength)
except:
pass
else:
print 'PERCENT: ', percent
class HTTPClientFactoryProgressStream(HTTPClientFactoryProgress):
protocol = HTTPPageGetterProgressStream
def getPage(url, progress=False, stream=False, proxy_host = None, proxy_port = None,
contextFactory = None, uniqueid = False, *args, **kwargs):
scheme, host, port, path = client._parse(url)
if not progress:
factory = HTTPClientFactory(url, proxy_host = proxy_host, proxy_port = proxy_port, *args, **kwargs)
else:
if stream:
factory = HTTPClientFactoryProgressStream(url, progresscall = progress,
proxy_host = proxy_host, proxy_port = proxy_port, *args, **kwargs)
else:
factory = HTTPClientFactoryProgress(url, progresscall = progress,
proxy_host = proxy_host, proxy_port = proxy_port, *args, **kwargs)
factory.uniqueid=uniqueid
if scheme == 'https':
from twisted.internet import ssl
if contextFactory is None:
contextFactory = ssl.ClientContextFactory()
reac = reactor.connectSSL(host, port, factory, contextFactory)
else:
if proxy_host:
if not proxy_port:
proxy_port = 80
reac = reactor.connectTCP(proxy_host, proxy_port, factory)
else:
reac = reactor.connectTCP(host, port, factory)
if not stream:
return factory.deferred
else:
return reac, factory.deferred
[Desktop Entry]
Value=1.0
Type=Application
Name=SkyLiveNG
Categories=Science;Astronomy;Education;
Exec=/usr/bin/skylive
Icon=/usr/share/skylive/ICONA.ico
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment