You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2584 lines
80 KiB
C++
2584 lines
80 KiB
C++
/***************************************************************************
|
|
kstarsdata.cpp - Trinity Desktop Planetarium
|
|
-------------------
|
|
begin : Sun Jul 29 2001
|
|
copyright : (C) 2001 by Heiko Evermann
|
|
email : heiko@evermann.de
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <tqregexp.h>
|
|
#include <tqdir.h>
|
|
#include <tqfile.h>
|
|
|
|
#include <tdeapplication.h>
|
|
#include <tdemessagebox.h>
|
|
#include <kdebug.h>
|
|
#include <tdelocale.h>
|
|
#include <kstandarddirs.h>
|
|
|
|
#include "kstarsdata.h"
|
|
|
|
#include "Options.h"
|
|
#include "dms.h"
|
|
#include "skymap.h"
|
|
#include "ksutils.h"
|
|
#include "ksnumbers.h"
|
|
#include "skypoint.h"
|
|
#include "skyobject.h"
|
|
#include "starobject.h"
|
|
#include "deepskyobject.h"
|
|
#include "skyobjectname.h"
|
|
#include "ksplanet.h"
|
|
#include "ksasteroid.h"
|
|
#include "kscomet.h"
|
|
#include "ksmoon.h"
|
|
#include "jupitermoons.h"
|
|
|
|
#include "simclock.h"
|
|
#include "timezonerule.h"
|
|
#include "filesource.h"
|
|
#include "stardatasink.h"
|
|
#include "ksfilereader.h"
|
|
#include "indidriver.h"
|
|
#include "indi/lilxml.h"
|
|
#include "indistd.h"
|
|
#include "detaildialog.h"
|
|
#include "csegment.h"
|
|
#include "customcatalog.h"
|
|
|
|
TQPtrList<GeoLocation> KStarsData::geoList = TQPtrList<GeoLocation>();
|
|
TQMap<TQString, TimeZoneRule> KStarsData::Rulebook = TQMap<TQString, TimeZoneRule>();
|
|
TQStringList KStarsData::CustomColumns = TQStringList::split( " ", "ID RA Dc Tp Nm Mg Mj Mn PA Ig" );
|
|
int KStarsData::objects = 0;
|
|
|
|
KStarsData::KStarsData() : stdDirs(0), locale(0),
|
|
LST(0), HourAngle(0),
|
|
PCat(0), Moon(0), jmoons(0),
|
|
starFileReader(0), initTimer(0),
|
|
source(0), loader(0), pump(0)
|
|
{
|
|
startupComplete = false;
|
|
objects++;
|
|
|
|
//standard directories and locale objects
|
|
stdDirs = new TDEStandardDirs();
|
|
locale = new TDELocale( "kstars" );
|
|
|
|
//Check to see if config file already exists. If not, set
|
|
//useDefaultOptions = true
|
|
TQString fname = locateLocal( "config", "kstarsrc" );
|
|
useDefaultOptions = ! ( TQFile(fname).exists() );
|
|
|
|
//Instantiate LST and HourAngle
|
|
LST = new dms();
|
|
HourAngle = new dms();
|
|
|
|
//Instantiate planet catalog
|
|
PCat = new PlanetCatalog(this);
|
|
|
|
//initialize FOV symbol
|
|
fovSymbol = FOV();
|
|
|
|
//set AutoDelete property for TQPtrLists. Most are set TRUE,
|
|
//but some 'meta-lists' need to be FALSE.
|
|
starList.setAutoDelete( TRUE );
|
|
ADVtreeList.setAutoDelete( TRUE );
|
|
geoList.setAutoDelete( TRUE );
|
|
deepSkyList.setAutoDelete( TRUE ); // list of all deep space objects
|
|
|
|
//separate lists for each deep-sky catalog. The objects are duplicates of
|
|
//deepSkyList, so do not delete them twice!
|
|
deepSkyListMessier.setAutoDelete( FALSE );
|
|
deepSkyListNGC.setAutoDelete( FALSE );
|
|
deepSkyListIC.setAutoDelete( FALSE );
|
|
deepSkyListOther.setAutoDelete( FALSE );
|
|
|
|
//ObjLabelList does not construct new objects, so no autoDelete needed
|
|
ObjLabelList.setAutoDelete( FALSE );
|
|
|
|
cometList.setAutoDelete( TRUE );
|
|
asteroidList.setAutoDelete( TRUE );
|
|
|
|
//Constellation lines are now pointers to existing StarObjects;
|
|
//these are already auto-deleted by starList.
|
|
clineList.setAutoDelete( FALSE );
|
|
clineModeList.setAutoDelete( TRUE );
|
|
cnameList.setAutoDelete( TRUE );
|
|
csegmentList.setAutoDelete( TRUE );
|
|
|
|
Equator.setAutoDelete( TRUE );
|
|
Ecliptic.setAutoDelete( TRUE );
|
|
Horizon.setAutoDelete( TRUE );
|
|
for ( unsigned int i=0; i<11; ++i ) MilkyWay[i].setAutoDelete( TRUE );
|
|
|
|
VariableStarsList.setAutoDelete(TRUE);
|
|
INDIHostsList.setAutoDelete(TRUE);
|
|
INDITelescopeList.setAutoDelete(TRUE);
|
|
|
|
//Initialize object type strings
|
|
TypeName[0] = i18n( "star" );
|
|
TypeName[1] = i18n( "multiple star" );
|
|
TypeName[2] = i18n( "planet" );
|
|
TypeName[3] = i18n( "open cluster" );
|
|
TypeName[4] = i18n( "globular cluster" );
|
|
TypeName[5] = i18n( "gaseous nebula" );
|
|
TypeName[6] = i18n( "planetary nebula" );
|
|
TypeName[7] = i18n( "supernova remnant" );
|
|
TypeName[8] = i18n( "galaxy" );
|
|
TypeName[9] = i18n( "comet" );
|
|
TypeName[10] = i18n( "asteroid" );
|
|
TypeName[11] = i18n( "constellation" );
|
|
|
|
// at startup times run forward
|
|
setTimeDirection( 0.0 );
|
|
|
|
//The StoredDate is used when saving user settings in a script; initialize to invalid date
|
|
StoredDate.setDJD( (long double)INVALID_DAY );
|
|
|
|
temporaryTrail = false;
|
|
}
|
|
|
|
KStarsData::~KStarsData() {
|
|
objects--;
|
|
checkDataPumpAction();
|
|
|
|
// the list items do not need to be removed by hand.
|
|
// all lists are set to AutoDelete = true
|
|
|
|
delete stdDirs;
|
|
delete Moon;
|
|
delete locale;
|
|
delete PCat;
|
|
delete jmoons;
|
|
delete initTimer;
|
|
}
|
|
|
|
bool KStarsData::readMWData( void ) {
|
|
TQFile file;
|
|
|
|
for ( unsigned int i=0; i<11; ++i ) {
|
|
TQString snum, fname, szero;
|
|
snum = snum.setNum( i+1 );
|
|
if ( i+1 < 10 ) szero = "0"; else szero = "";
|
|
fname = "mw" + szero + snum + ".dat";
|
|
|
|
if ( KSUtils::openDataFile( file, fname ) ) {
|
|
KSFileReader fileReader( file ); // close file is included
|
|
while ( fileReader.hasMoreLines() ) {
|
|
TQString line;
|
|
double ra, dec;
|
|
|
|
line = fileReader.readLine();
|
|
|
|
ra = line.mid( 0, 8 ).toDouble();
|
|
dec = line.mid( 9, 8 ).toDouble();
|
|
|
|
SkyPoint *o = new SkyPoint( ra, dec );
|
|
MilkyWay[i].append( o );
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool KStarsData::readADVTreeData(void)
|
|
{
|
|
|
|
TQFile file;
|
|
TQString Interface;
|
|
|
|
if (!KSUtils::openDataFile(file, "advinterface.dat"))
|
|
return false;
|
|
|
|
TQTextStream stream(&file);
|
|
TQString Line;
|
|
|
|
while (!stream.atEnd())
|
|
{
|
|
TQString Name, Link, subName;
|
|
int Type, interfaceIndex;
|
|
|
|
Line = stream.readLine();
|
|
|
|
if (Line.startsWith("[KSLABEL]"))
|
|
{
|
|
Name = Line.mid(9);
|
|
Type = 0;
|
|
}
|
|
else if (Line.startsWith("[END]"))
|
|
Type = 1;
|
|
else if (Line.startsWith("[KSINTERFACE]"))
|
|
{
|
|
Interface = Line.mid(13);
|
|
continue;
|
|
}
|
|
|
|
else
|
|
{
|
|
Name = Line.mid(0, Line.find(":"));
|
|
Link = Line.mid(Line.find(":") + 1);
|
|
|
|
// Link is empty, using Interface instead
|
|
if (Link.isEmpty())
|
|
{
|
|
Link = Interface;
|
|
subName = Name;
|
|
interfaceIndex = Link.find("KSINTERFACE");
|
|
Link.remove(interfaceIndex, 11);
|
|
Link = Link.insert(interfaceIndex, subName.replace( TQRegExp(" "), "+"));
|
|
|
|
}
|
|
|
|
Type = 2;
|
|
}
|
|
|
|
ADVTreeData *ADVData = new ADVTreeData;
|
|
|
|
ADVData->Name = Name;
|
|
ADVData->Link = Link;
|
|
ADVData->Type = Type;
|
|
|
|
ADVtreeList.append(ADVData);
|
|
}
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
bool KStarsData::readVARData(void)
|
|
{
|
|
TQString varFile("valaav.txt");
|
|
TQFile localeFile;
|
|
TQFile file;
|
|
|
|
file.setName( locateLocal( "appdata", varFile ) );
|
|
if ( !file.open( IO_ReadOnly ) )
|
|
{
|
|
// Open default variable stars file
|
|
if ( KSUtils::openDataFile( file, varFile ) )
|
|
{
|
|
// we found urlfile, we need to copy it to locale
|
|
localeFile.setName( locateLocal( "appdata", varFile ) );
|
|
|
|
if (localeFile.open(IO_WriteOnly))
|
|
{
|
|
TQTextStream readStream(&file);
|
|
TQTextStream writeStream(&localeFile);
|
|
writeStream << readStream.read();
|
|
localeFile.close();
|
|
file.reset();
|
|
}
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
stream.readLine();
|
|
|
|
while (!stream.atEnd())
|
|
{
|
|
TQString Name;
|
|
TQString Designation;
|
|
TQString Line;
|
|
|
|
Line = stream.readLine();
|
|
|
|
if (Line[0] == TQChar('*'))
|
|
break;
|
|
|
|
Designation = Line.mid(0,8).stripWhiteSpace();
|
|
Name = Line.mid(10,20).simplifyWhiteSpace();
|
|
|
|
VariableStarInfo *VInfo = new VariableStarInfo;
|
|
|
|
VInfo->Designation = Designation;
|
|
VInfo->Name = Name;
|
|
VariableStarsList.append(VInfo);
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
bool KStarsData::readINDIHosts(void)
|
|
{
|
|
TQString indiFile("indihosts.xml");
|
|
TQFile localeFile;
|
|
TQFile file;
|
|
char errmsg[1024];
|
|
signed char c;
|
|
LilXML *xmlParser = newLilXML();
|
|
XMLEle *root = NULL;
|
|
XMLAtt *ap;
|
|
|
|
file.setName( locate( "appdata", indiFile ) );
|
|
if ( file.name().isEmpty() || !file.open( IO_ReadOnly ) )
|
|
return false;
|
|
|
|
while ( (c = (signed char) file.getch()) != -1)
|
|
{
|
|
root = readXMLEle(xmlParser, c, errmsg);
|
|
|
|
if (root)
|
|
{
|
|
|
|
// Get host name
|
|
ap = findXMLAtt(root, "name");
|
|
if (!ap) {
|
|
delLilXML(xmlParser);
|
|
return false;
|
|
}
|
|
|
|
INDIHostsInfo *VInfo = new INDIHostsInfo;
|
|
|
|
VInfo->name = TQString(valuXMLAtt(ap));
|
|
|
|
// Get host name
|
|
ap = findXMLAtt(root, "hostname");
|
|
|
|
if (!ap) {
|
|
delLilXML(xmlParser);
|
|
return false;
|
|
}
|
|
|
|
VInfo->hostname = TQString(valuXMLAtt(ap));
|
|
|
|
ap = findXMLAtt(root, "port");
|
|
|
|
if (!ap) {
|
|
delLilXML(xmlParser);
|
|
return false;
|
|
}
|
|
|
|
VInfo->portnumber = TQString(valuXMLAtt(ap));
|
|
|
|
VInfo->isConnected = false;
|
|
VInfo->mgrID = -1;
|
|
|
|
INDIHostsList.append(VInfo);
|
|
|
|
delXMLEle(root);
|
|
}
|
|
|
|
else if (errmsg[0])
|
|
kdDebug() << errmsg << endl;
|
|
|
|
}
|
|
|
|
delLilXML(xmlParser);
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
bool KStarsData::readCLineData( void ) {
|
|
//The constellation lines data file (clines.dat) contains lists
|
|
//of abbreviated genetive star names in the same format as they
|
|
//appear in the star data files (hipNNN.dat).
|
|
//
|
|
//Each constellation consists of a TQPtrList of SkyPoints,
|
|
//corresponding to the stars at each "node" of the constellation.
|
|
//These are pointers to the starobjects themselves, so the nodes
|
|
//will automatically be fixed to the stars even as the star
|
|
//positions change due to proper motions. In addition, each node
|
|
//has a corresponding flag that determines whether a line should
|
|
//connect this node and the previous one.
|
|
|
|
TQFile file;
|
|
if ( KSUtils::openDataFile( file, "clines.dat" ) ) {
|
|
TQTextStream stream( &file );
|
|
|
|
while ( !stream.eof() ) {
|
|
TQString line, name;
|
|
TQChar *mode;
|
|
|
|
line = stream.readLine();
|
|
|
|
//ignore lines beginning with "#":
|
|
if ( line.at( 0 ) != '#' ) {
|
|
name = line.mid( 2 ).stripWhiteSpace();
|
|
|
|
//Find the star with the same abbreviated genitive name ( name2() )
|
|
//increase efficiency by searching the list of named objects, rather than the
|
|
//full list of all stars.
|
|
bool starFound( false );
|
|
for ( SkyObjectName *oname = ObjNames.first(); oname; oname = ObjNames.next() ) {
|
|
if ( oname->skyObject()->type() == SkyObject::STAR &&
|
|
oname->skyObject()->name2() == name ) {
|
|
starFound = true;
|
|
clineList.append( (SkyPoint *)( oname->skyObject() ) );
|
|
|
|
mode = new TQChar( line.at( 0 ) );
|
|
clineModeList.append( mode );
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ! starFound )
|
|
kdWarning() << i18n( "No star named %1 found." ).arg(name) << endl;
|
|
}
|
|
}
|
|
file.close();
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool KStarsData::readCNameData( void ) {
|
|
TQFile file;
|
|
cnameFile = "cnames.dat";
|
|
|
|
if ( KSUtils::openDataFile( file, cnameFile ) ) {
|
|
TQTextStream stream( &file );
|
|
|
|
while ( !stream.eof() ) {
|
|
TQString line, name, abbrev;
|
|
int rah, ram, ras, dd, dm, ds;
|
|
TQChar sgn;
|
|
|
|
line = stream.readLine();
|
|
|
|
rah = line.mid( 0, 2 ).toInt();
|
|
ram = line.mid( 2, 2 ).toInt();
|
|
ras = line.mid( 4, 2 ).toInt();
|
|
|
|
sgn = line.at( 6 );
|
|
dd = line.mid( 7, 2 ).toInt();
|
|
dm = line.mid( 9, 2 ).toInt();
|
|
ds = line.mid( 11, 2 ).toInt();
|
|
|
|
abbrev = line.mid( 13, 3 );
|
|
name = line.mid( 17 ).stripWhiteSpace();
|
|
|
|
dms r; r.setH( rah, ram, ras );
|
|
dms d( dd, dm, ds );
|
|
|
|
if ( sgn == "-" ) { d.setD( -1.0*d.Degrees() ); }
|
|
|
|
SkyObject *o = new SkyObject( SkyObject::CONSTELLATION, r, d, 0.0, name, abbrev );
|
|
cnameList.append( o );
|
|
ObjNames.append( o );
|
|
}
|
|
file.close();
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool KStarsData::readCBoundData( void ) {
|
|
TQFile file;
|
|
|
|
if ( KSUtils::openDataFile( file, "cbound.dat" ) ) {
|
|
TQTextStream stream( &file );
|
|
|
|
unsigned int nn(0);
|
|
double ra(0.0), dec(0.0);
|
|
TQString d1, d2;
|
|
bool ok(false), comment(false);
|
|
|
|
//read the stream one field at a time. Individual segments can span
|
|
//multiple lines, so our normal readLine() is less convenient here.
|
|
//Read fields into strings and then attempt to recast them as ints
|
|
//or doubles..this lets us do error checking on the stream.
|
|
while ( !stream.eof() ) {
|
|
stream >> d1;
|
|
if ( d1.at(0) == '#' ) {
|
|
comment = true;
|
|
ok = true;
|
|
} else {
|
|
comment = false;
|
|
nn = d1.toInt( &ok );
|
|
}
|
|
|
|
if ( !ok || comment ) {
|
|
d1 = stream.readLine();
|
|
|
|
if ( !ok )
|
|
kdWarning() << i18n( "Unable to parse boundary segment." ) << endl;
|
|
|
|
} else {
|
|
CSegment *seg = new CSegment();
|
|
|
|
for ( unsigned int i=0; i<nn; ++i ) {
|
|
stream >> d1 >> d2;
|
|
ra = d1.toDouble( &ok );
|
|
if ( ok ) dec = d2.toDouble( &ok );
|
|
if ( !ok ) break;
|
|
|
|
seg->addPoint( ra, dec );
|
|
}
|
|
|
|
if ( !ok ) {
|
|
//uh oh, this entry was not parsed. Skip to the next line.
|
|
kdWarning() << i18n( "Unable to parse boundary segment." ) << endl;
|
|
delete seg;
|
|
d1 = stream.readLine();
|
|
|
|
} else {
|
|
stream >> d1; //this should always equal 2
|
|
|
|
nn = d1.toInt( &ok );
|
|
//error check
|
|
if ( !ok || nn != 2 ) {
|
|
kdWarning() << i18n( "Bad Constellation Boundary data." ) << endl;
|
|
delete seg;
|
|
d1 = stream.readLine();
|
|
}
|
|
}
|
|
|
|
if ( ok ) {
|
|
stream >> d1 >> d2;
|
|
ok = seg->setNames( d1, d2 );
|
|
if ( ok ) csegmentList.append( seg );
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool KStarsData::openStarFile( int i ) {
|
|
if (starFileReader != 0) delete starFileReader;
|
|
TQFile file;
|
|
TQString snum, fname;
|
|
snum = TQString().sprintf("%03d", i);
|
|
fname = "hip" + snum + ".dat";
|
|
if (KSUtils::openDataFile(file, fname)) {
|
|
starFileReader = new KSFileReader(file); // close file is included
|
|
} else {
|
|
starFileReader = 0;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool KStarsData::readStarData( void ) {
|
|
bool ready = false;
|
|
|
|
float loadUntilMag = MINDRAWSTARMAG;
|
|
if (Options::magLimitDrawStar() > loadUntilMag) loadUntilMag = Options::magLimitDrawStar();
|
|
|
|
for (unsigned int i=1; i<NHIPFILES+1; ++i) {
|
|
emit progressText( i18n( "Loading Star Data (%1%)" ).arg( int(100.*float(i)/float(NHIPFILES)) ) );
|
|
|
|
if (openStarFile(i) == true) {
|
|
while (starFileReader->hasMoreLines()) {
|
|
TQString line;
|
|
float mag;
|
|
|
|
line = starFileReader->readLine();
|
|
if ( line.left(1) != "#" ) { //ignore comments
|
|
// check star magnitude
|
|
mag = line.mid( 46,5 ).toFloat();
|
|
if ( mag > loadUntilMag ) {
|
|
ready = true;
|
|
break;
|
|
}
|
|
|
|
processStar(&line);
|
|
}
|
|
} // end of while
|
|
|
|
} else { //one of the star files could not be read.
|
|
if ( starList.count() ) return true;
|
|
else return false;
|
|
}
|
|
// magnitude level is reached
|
|
if (ready == true) break;
|
|
}
|
|
|
|
//Store the max set magnitude of current session. Will increase in KStarsData::appendNewData()
|
|
maxSetMagnitude = Options::magLimitDrawStar();
|
|
delete starFileReader;
|
|
starFileReader = 0;
|
|
return true;
|
|
}
|
|
|
|
void KStarsData::processStar( TQString *line, bool reloadMode ) {
|
|
TQString name, gname, SpType;
|
|
int rah, ram, ras, ras2, dd, dm, ds, ds2;
|
|
bool mult, var;
|
|
TQChar sgn;
|
|
double mag, bv, dmag, vper;
|
|
double pmra, pmdec, plx;
|
|
|
|
name = ""; gname = "";
|
|
|
|
//parse coordinates
|
|
rah = line->mid( 0, 2 ).toInt();
|
|
ram = line->mid( 2, 2 ).toInt();
|
|
ras = int(line->mid( 4, 5 ).toDouble());
|
|
ras2 = int(60.0*(line->mid( 4, 5 ).toDouble()-ras) + 0.5); //add 0.5 to get nearest integer with int()
|
|
|
|
sgn = line->at(10);
|
|
dd = line->mid(11, 2).toInt();
|
|
dm = line->mid(13, 2).toInt();
|
|
ds = int(line->mid(15, 4).toDouble());
|
|
ds2 = int(60.0*(line->mid( 15, 5 ).toDouble()-ds) + 0.5); //add 0.5 to get nearest integer with int()
|
|
|
|
//parse proper motion and parallax
|
|
pmra = line->mid( 20, 9 ).toDouble();
|
|
pmdec = line->mid( 29, 9 ).toDouble();
|
|
plx = line->mid( 38, 7 ).toDouble();
|
|
|
|
//parse magnitude, B-V color, and spectral type
|
|
mag = line->mid( 46, 5 ).toDouble();
|
|
bv = line->mid( 51, 5 ).toDouble();
|
|
SpType = line->mid(56, 2);
|
|
|
|
//parse multiplicity
|
|
mult = line->mid( 59, 1 ).toInt();
|
|
|
|
//parse variablility...currently not using dmag or var
|
|
var = false; dmag = 0.0; vper = 0.0;
|
|
if ( line->at( 62 ) == '.' ) {
|
|
var = true;
|
|
dmag = line->mid( 61, 4 ).toDouble();
|
|
vper = line->mid( 66, 6 ).toDouble();
|
|
}
|
|
|
|
//parse name(s)
|
|
name = line->mid( 72 ).stripWhiteSpace(); //the rest of the line
|
|
if (name.contains( ':' )) { //genetive form exists
|
|
gname = name.mid( name.find(':')+1 ).stripWhiteSpace();
|
|
name = name.mid( 0, name.find(':') ).stripWhiteSpace();
|
|
}
|
|
|
|
// HEV: look up star name in internationalization filesource
|
|
name = i18n("star name", name.local8Bit().data());
|
|
|
|
bool starIsUnnamed( false );
|
|
if (name.isEmpty() && gname.isEmpty()) { //both names are empty
|
|
starIsUnnamed = true;
|
|
}
|
|
|
|
dms r;
|
|
r.setH(rah, ram, ras, ras2);
|
|
dms d(dd, dm, ds, ds2);
|
|
|
|
if (sgn == "-") { d.setD( -1.0*d.Degrees() ); }
|
|
|
|
StarObject *o = new StarObject(r, d, mag, name, gname, SpType, pmra, pmdec, plx, mult, var );
|
|
starList.append(o);
|
|
|
|
// get horizontal coordinates when object will loaded while running the application
|
|
// first run doesn't need this because updateTime() will called after loading all data
|
|
if (reloadMode) {
|
|
o->EquatorialToHorizontal( LST, geo()->lat() );
|
|
}
|
|
|
|
//STAR_SIZE
|
|
// StarObject *p = new StarObject(r, d, mag, name, gname, SpType, pmra, pmdec, plx, mult, var );
|
|
// starList.append(p);
|
|
|
|
// add named stars to list
|
|
if (starIsUnnamed == false) {
|
|
ObjNames.append(o);
|
|
}
|
|
}
|
|
|
|
bool KStarsData::readAsteroidData( void ) {
|
|
TQFile file;
|
|
|
|
if ( KSUtils::openDataFile( file, "asteroids.dat" ) ) {
|
|
KSFileReader fileReader( file );
|
|
|
|
while( fileReader.hasMoreLines() ) {
|
|
TQString line, name;
|
|
int mJD;
|
|
double a, e, dble_i, dble_w, dble_N, dble_M, H;
|
|
long double JD;
|
|
KSAsteroid *ast = 0;
|
|
|
|
line = fileReader.readLine();
|
|
name = line.mid( 6, 17 ).stripWhiteSpace();
|
|
mJD = line.mid( 24, 5 ).toInt();
|
|
a = line.mid( 30, 9 ).toDouble();
|
|
e = line.mid( 41, 10 ).toDouble();
|
|
dble_i = line.mid( 52, 9 ).toDouble();
|
|
dble_w = line.mid( 62, 9 ).toDouble();
|
|
dble_N = line.mid( 72, 9 ).toDouble();
|
|
dble_M = line.mid( 82, 11 ).toDouble();
|
|
H = line.mid( 94, 5 ).toDouble();
|
|
|
|
JD = double( mJD ) + 2400000.5;
|
|
|
|
ast = new KSAsteroid( this, name, "", JD, a, e, dms(dble_i), dms(dble_w), dms(dble_N), dms(dble_M), H );
|
|
ast->setAngularSize( 0.005 );
|
|
asteroidList.append( ast );
|
|
ObjNames.append( ast );
|
|
}
|
|
|
|
if ( asteroidList.count() ) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool KStarsData::readCometData( void ) {
|
|
TQFile file;
|
|
|
|
if ( KSUtils::openDataFile( file, "comets.dat" ) ) {
|
|
KSFileReader fileReader( file );
|
|
|
|
while( fileReader.hasMoreLines() ) {
|
|
TQString line, name;
|
|
int mJD;
|
|
double q, e, dble_i, dble_w, dble_N, Tp;
|
|
long double JD;
|
|
KSComet *com = 0;
|
|
|
|
line = fileReader.readLine();
|
|
name = line.mid( 3, 35 ).stripWhiteSpace();
|
|
mJD = line.mid( 38, 5 ).toInt();
|
|
q = line.mid( 44, 10 ).toDouble();
|
|
e = line.mid( 55, 10 ).toDouble();
|
|
dble_i = line.mid( 66, 9 ).toDouble();
|
|
dble_w = line.mid( 76, 9 ).toDouble();
|
|
dble_N = line.mid( 86, 9 ).toDouble();
|
|
Tp = line.mid( 96, 14 ).toDouble();
|
|
|
|
JD = double( mJD ) + 2400000.5;
|
|
|
|
com = new KSComet( this, name, "", JD, q, e, dms(dble_i), dms(dble_w), dms(dble_N), Tp );
|
|
com->setAngularSize( 0.005 );
|
|
|
|
cometList.append( com );
|
|
ObjNames.append( com );
|
|
}
|
|
|
|
if ( cometList.count() ) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//02/2003: NEW: split data files, using Heiko's new KSFileReader.
|
|
bool KStarsData::readDeepSkyData( void ) {
|
|
TQFile file;
|
|
|
|
for ( unsigned int i=0; i<NNGCFILES; ++i ) {
|
|
TQString snum, fname;
|
|
snum = TQString().sprintf( "%02d", i+1 );
|
|
fname = "ngcic" + snum + ".dat";
|
|
|
|
emit progressText( i18n( "Loading NGC/IC Data (%1%)" ).arg( int(100.*float(i)/float(NNGCFILES)) ) );
|
|
|
|
if ( KSUtils::openDataFile( file, fname ) ) {
|
|
KSFileReader fileReader( file ); // close file is included
|
|
while ( fileReader.hasMoreLines() ) {
|
|
TQString line, con, ss, name, name2, longname;
|
|
TQString cat, cat2;
|
|
float mag(1000.0), ras, a, b;
|
|
int type, ingc, imess(-1), rah, ram, dd, dm, ds, pa;
|
|
int pgc, ugc;
|
|
TQChar sgn, iflag;
|
|
|
|
line = fileReader.readLine();
|
|
//Ignore comment lines
|
|
while ( line.at(0) == '#' && fileReader.hasMoreLines() ) line = fileReader.readLine();
|
|
//Ignore lines with no coordinate values
|
|
while ( line.mid(6,8).stripWhiteSpace().isEmpty() ) line = fileReader.readLine();
|
|
|
|
iflag = line.at( 0 ); //check for NGC/IC catalog flag
|
|
if ( iflag == 'I' ) cat = "IC";
|
|
else if ( iflag == 'N' ) cat = "NGC";
|
|
|
|
ingc = line.mid( 1, 4 ).toInt(); // NGC/IC catalog number
|
|
if ( ingc==0 ) cat = ""; //object is not in NGC or IC catalogs
|
|
|
|
//coordinates
|
|
rah = line.mid( 6, 2 ).toInt();
|
|
ram = line.mid( 8, 2 ).toInt();
|
|
ras = line.mid( 10, 4 ).toFloat();
|
|
sgn = line.at( 15 );
|
|
dd = line.mid( 16, 2 ).toInt();
|
|
dm = line.mid( 18, 2 ).toInt();
|
|
ds = line.mid( 20, 2 ).toInt();
|
|
|
|
//B magnitude
|
|
ss = line.mid( 23, 4 );
|
|
if (ss == " " ) { mag = 99.9; } else { mag = ss.toFloat(); }
|
|
|
|
//object type
|
|
type = line.mid( 29, 1 ).toInt();
|
|
|
|
//major and minor axes
|
|
ss = line.mid( 31, 5 );
|
|
if (ss == " " ) { a = 0.0; } else { a = ss.toFloat(); }
|
|
ss = line.mid( 37, 5 );
|
|
if (ss == " " ) { b = 0.0; } else { b = ss.toFloat(); }
|
|
//position angle. The catalog PA is zero when the Major axis
|
|
//is horizontal. But we want the angle measured from North, so
|
|
//we set PA = 90 - pa.
|
|
ss = line.mid( 43, 3 );
|
|
if (ss == " " ) { pa = 90; } else { pa = 90 - ss.toInt(); }
|
|
|
|
//PGC number
|
|
ss = line.mid( 47, 6 );
|
|
if (ss == " " ) { pgc = 0; } else { pgc = ss.toInt(); }
|
|
|
|
//UGC number
|
|
if ( line.mid( 54, 3 ) == "UGC" ) {
|
|
ugc = line.mid( 58, 5 ).toInt();
|
|
} else {
|
|
ugc = 0;
|
|
}
|
|
|
|
//Messier number
|
|
if ( line.at( 70 ) == 'M' ) {
|
|
cat2 = cat;
|
|
if ( ingc==0 ) cat2 = "";
|
|
cat = "M";
|
|
imess = line.mid( 72, 3 ).toInt();
|
|
}
|
|
|
|
longname = line.mid( 76, line.length() ).stripWhiteSpace();
|
|
|
|
dms r;
|
|
r.setH( rah, ram, int(ras) );
|
|
dms d( dd, dm, ds );
|
|
|
|
if ( sgn == "-" ) { d.setD( -1.0*d.Degrees() ); }
|
|
|
|
// TQString snum;
|
|
if ( cat=="IC" || cat=="NGC" ) {
|
|
snum.setNum( ingc );
|
|
name = cat + " " + snum;
|
|
} else if ( cat=="M" ) {
|
|
snum.setNum( imess );
|
|
name = cat + " " + snum;
|
|
if ( cat2=="NGC" ) {
|
|
snum.setNum( ingc );
|
|
name2 = cat2 + " " + snum;
|
|
} else if ( cat2=="IC" ) {
|
|
snum.setNum( ingc );
|
|
name2 = cat2 + " " + snum;
|
|
} else {
|
|
name2 = "";
|
|
}
|
|
} else {
|
|
if ( longname.isEmpty() ) name = i18n( "Unnamed Object" );
|
|
else name = longname;
|
|
}
|
|
|
|
// create new deepskyobject
|
|
DeepSkyObject *o = 0;
|
|
if ( type==0 ) type = 1; //Make sure we use CATALOG_STAR, not STAR
|
|
o = new DeepSkyObject( type, r, d, mag, name, name2, longname, cat, a, b, pa, pgc, ugc );
|
|
|
|
// keep object in deep sky objects' list
|
|
deepSkyList.append( o );
|
|
// plus: keep objects separated for performance reasons. Switching the colors during
|
|
// paint is too expensive.
|
|
if ( o->isCatalogM()) {
|
|
deepSkyListMessier.append( o );
|
|
} else if (o->isCatalogNGC() ) {
|
|
deepSkyListNGC.append( o );
|
|
} else if ( o->isCatalogIC() ) {
|
|
deepSkyListIC.append( o );
|
|
} else {
|
|
deepSkyListOther.append( o );
|
|
}
|
|
|
|
// list of object names
|
|
ObjNames.append( (SkyObject*)o );
|
|
|
|
//Add longname to objList, unless longname is the same as name
|
|
if ( !o->longname().isEmpty() && o->name() != o->longname() && o->hasName() ) {
|
|
ObjNames.append( o, true ); // append with longname
|
|
}
|
|
} //end while-filereader
|
|
} else { //one of the files could not be opened
|
|
return false;
|
|
}
|
|
} //end for-loop through files
|
|
|
|
return true;
|
|
}
|
|
|
|
bool KStarsData::openURLFile(TQString urlfile, TQFile & file) {
|
|
//TQFile file;
|
|
TQString localFile;
|
|
bool fileFound = false;
|
|
TQFile localeFile;
|
|
|
|
if ( locale->language() != "en_US" )
|
|
localFile = locale->language() + "/" + urlfile;
|
|
|
|
if ( ! localFile.isEmpty() && KSUtils::openDataFile( file, localFile ) ) {
|
|
fileFound = true;
|
|
} else {
|
|
// Try to load locale file, if not successful, load regular urlfile and then copy it to locale.
|
|
file.setName( locateLocal( "appdata", urlfile ) );
|
|
if ( file.open( IO_ReadOnly ) ) {
|
|
//local file found. Now, if global file has newer timestamp, then merge the two files.
|
|
//First load local file into TQStringList
|
|
bool newDataFound( false );
|
|
TQStringList urlData;
|
|
TQTextStream lStream( &file );
|
|
while ( ! lStream.eof() ) urlData.append( lStream.readLine() );
|
|
|
|
//Find global file(s) in findAllResources() list.
|
|
TQFileInfo fi_local( file.name() );
|
|
TQStringList flist = TDEGlobal::instance()->dirs()->findAllResources( "appdata", urlfile );
|
|
for ( unsigned int i=0; i< flist.count(); i++ ) {
|
|
if ( flist[i] != file.name() ) {
|
|
TQFileInfo fi_global( flist[i] );
|
|
|
|
//Is this global file newer than the local file?
|
|
if ( fi_global.lastModified() > fi_local.lastModified() ) {
|
|
//Global file has newer timestamp than local. Add lines in global file that don't already exist in local file.
|
|
//be smart about this; in some cases the URL is updated but the image is probably the same if its
|
|
//label string is the same. So only check strings up to last ":"
|
|
TQFile globalFile( flist[i] );
|
|
if ( globalFile.open( IO_ReadOnly ) ) {
|
|
TQTextStream gStream( &globalFile );
|
|
while ( ! gStream.eof() ) {
|
|
TQString line = gStream.readLine();
|
|
|
|
//If global-file line begins with "XXX:" then this line should be removed from the local file.
|
|
if ( line.left( 4 ) == "XXX:" && urlData.contains( line.mid( 4 ) ) ) {
|
|
urlData.remove( urlData.find( line.mid( 4 ) ) );
|
|
} else {
|
|
//does local file contain the current global file line, up to second ':' ?
|
|
|
|
bool linefound( false );
|
|
for ( unsigned int j=0; j< urlData.count(); ++j ) {
|
|
if ( urlData[j].contains( line.left( line.find( ':', line.find( ':' ) + 1 ) ) ) ) {
|
|
//replace line in urlData with its equivalent in the newer global file.
|
|
urlData.remove( urlData.at(j) );
|
|
urlData.insert( urlData.at(j), line );
|
|
if ( !newDataFound ) newDataFound = true;
|
|
linefound = true;
|
|
break;
|
|
}
|
|
}
|
|
if ( ! linefound ) {
|
|
urlData.append( line );
|
|
if ( !newDataFound ) newDataFound = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
file.close();
|
|
|
|
//(possibly) write appended local file
|
|
if ( newDataFound ) {
|
|
if ( file.open( IO_WriteOnly ) ) {
|
|
TQTextStream outStream( &file );
|
|
for ( unsigned int i=0; i<urlData.count(); i++ ) {
|
|
outStream << urlData[i] << endl;
|
|
}
|
|
file.close();
|
|
}
|
|
}
|
|
|
|
if ( file.open( IO_ReadOnly ) ) fileFound = true;
|
|
|
|
} else {
|
|
if ( KSUtils::openDataFile( file, urlfile ) ) {
|
|
if ( locale->language() != "en_US" ) kdDebug() << i18n( "No localized URL file; using default English file." ) << endl;
|
|
// we found urlfile, we need to copy it to locale
|
|
localeFile.setName( locateLocal( "appdata", urlfile ) );
|
|
if (localeFile.open(IO_WriteOnly)) {
|
|
TQTextStream readStream(&file);
|
|
TQTextStream writeStream(&localeFile);
|
|
while ( ! readStream.eof() ) {
|
|
TQString line = readStream.readLine();
|
|
if ( line.left( 4 ) != "XXX:" ) //do not write "deleted" lines
|
|
writeStream << line << endl;
|
|
}
|
|
|
|
localeFile.close();
|
|
file.reset();
|
|
} else {
|
|
kdDebug() << i18n( "Failed to copy default URL file to locale folder, modifying default object links is not possible" ) << endl;
|
|
}
|
|
fileFound = true;
|
|
}
|
|
}
|
|
}
|
|
return fileFound;
|
|
}
|
|
|
|
bool KStarsData::readUserLog(void)
|
|
{
|
|
TQFile file;
|
|
TQString buffer;
|
|
TQString sub, name, data;
|
|
|
|
if (!KSUtils::openDataFile( file, "userlog.dat" )) return false;
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
if (!stream.eof()) buffer = stream.read();
|
|
|
|
while (!buffer.isEmpty()) {
|
|
int startIndex, endIndex;
|
|
|
|
startIndex = buffer.find("[KSLABEL:");
|
|
sub = buffer.mid(startIndex);
|
|
endIndex = sub.find("[KSLogEnd]");
|
|
|
|
// Read name after KSLABEL identifer
|
|
uint uiFirstNewline = sub.find("\n", startIndex + 9);
|
|
name = sub.mid(startIndex + 9, sub.findRev( "]", uiFirstNewline ) - (startIndex + 9) );
|
|
// Read data and skip new line
|
|
data = sub.mid( uiFirstNewline + 1, endIndex - (uiFirstNewline + 1));
|
|
buffer = buffer.mid(endIndex + 11);
|
|
|
|
//Find the sky object named 'name'.
|
|
//Note that ObjectNameList::find() looks for the ascii representation
|
|
//of star genetive names, so stars are identified that way in the user log.
|
|
SkyObjectName *sonm = ObjNames.find(name);
|
|
if (sonm == 0) {
|
|
kdWarning() << k_funcinfo << name << " not found" << endl;
|
|
} else {
|
|
sonm->skyObject()->userLog = data;
|
|
}
|
|
|
|
} // end while
|
|
file.close();
|
|
return true;
|
|
}
|
|
|
|
bool KStarsData::readURLData( TQString urlfile, int type, bool deepOnly ) {
|
|
TQFile file;
|
|
if (!openURLFile(urlfile, file)) return false;
|
|
|
|
TQTextStream stream(&file);
|
|
|
|
while ( !stream.eof() ) {
|
|
TQString line = stream.readLine();
|
|
|
|
//ignore comment lines
|
|
if ( line.left(1) != "#" ) {
|
|
TQString name = line.mid( 0, line.find(':') );
|
|
TQString sub = line.mid( line.find(':')+1 );
|
|
TQString title = sub.mid( 0, sub.find(':') );
|
|
TQString url = sub.mid( sub.find(':')+1 );
|
|
|
|
SkyObjectName *sonm = ObjNames.find(name);
|
|
|
|
if (sonm == 0) {
|
|
kdWarning() << k_funcinfo << name << " not found" << endl;
|
|
} else {
|
|
if ( ! deepOnly || ( sonm->skyObject()->type() > 2 && sonm->skyObject()->type() < 9 ) ) {
|
|
if ( type==0 ) { //image URL
|
|
sonm->skyObject()->ImageList.append( url );
|
|
sonm->skyObject()->ImageTitle.append( title );
|
|
} else if ( type==1 ) { //info URL
|
|
sonm->skyObject()->InfoList.append( url );
|
|
sonm->skyObject()->InfoTitle.append( title );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
file.close();
|
|
return true;
|
|
}
|
|
|
|
bool KStarsData::readCustomCatalogs() {
|
|
bool result = false;
|
|
|
|
for ( uint i=0; i < Options::catalogFile().count(); i++ ) {
|
|
bool thisresult = addCatalog( Options::catalogFile()[i] );
|
|
//Make result = true if at least one catalog is added
|
|
result = ( result || thisresult );
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool KStarsData::addCatalog( TQString filename ) {
|
|
CustomCatalog *newCat = createCustomCatalog( filename, false );
|
|
if ( newCat ) {
|
|
CustomCatalogs.append( newCat );
|
|
|
|
// add object names to ObjNames list
|
|
for ( uint i=0; i < newCat->objList().count(); i++ ) {
|
|
// for ( SkyObject *o=newCat->objList().first(); o; o = newCat->objList().next() ) {
|
|
SkyObject *o = newCat->objList().at(i);
|
|
ObjNames.append( o );
|
|
if ( o->hasLongName() && o->longname() != o->name() )
|
|
ObjNames.append( o, true ); //Add long name
|
|
// PdV
|
|
//if (reloadMode) {
|
|
// o->EquatorialToHorizontal( LST, geo()->lat() );
|
|
//}
|
|
|
|
}
|
|
|
|
return true;
|
|
} else
|
|
kdWarning() << k_funcinfo << i18n("Error adding catalog: %1").arg( filename ) << endl;
|
|
|
|
return false;
|
|
}
|
|
|
|
bool KStarsData::removeCatalog( int i ) {
|
|
if ( ! CustomCatalogs.at(i) ) return false;
|
|
|
|
TQPtrList<SkyObject> cat = CustomCatalogs.at(i)->objList();
|
|
|
|
for ( SkyObject *o=cat.first(); o; o=cat.next() ) {
|
|
ObjNames.remove( o->name() );
|
|
if ( o->hasLongName() && o->longname() != o->name() )
|
|
ObjNames.remove( o->longname() );
|
|
}
|
|
|
|
CustomCatalogs.remove(i);
|
|
|
|
return true;
|
|
}
|
|
|
|
CustomCatalog* KStarsData::createCustomCatalog( TQString filename, bool showerrs ) {
|
|
TQDir::setCurrent( TQDir::homeDirPath() ); //for files with relative path
|
|
TQPtrList<SkyObject> objList;
|
|
TQString CatalogName, CatalogPrefix, CatalogColor;
|
|
float CatalogEpoch;
|
|
|
|
//If the filename begins with "~", replace the "~" with the user's home directory
|
|
//(otherwise, the file will not successfully open)
|
|
if ( filename.at(0)=='~' )
|
|
filename = TQDir::homeDirPath() + filename.mid( 1, filename.length() );
|
|
TQFile ccFile( filename );
|
|
|
|
if ( ccFile.open( IO_ReadOnly ) ) {
|
|
int iStart(0); //the line number of the first non-header line
|
|
TQStringList errs; //list of error messages
|
|
TQStringList Columns; //list of data column descriptors in the header
|
|
|
|
TQTextStream stream( &ccFile );
|
|
TQStringList lines = TQStringList::split( "\n", stream.read() );
|
|
|
|
if ( parseCustomDataHeader( lines, Columns, CatalogName, CatalogPrefix,
|
|
CatalogColor, CatalogEpoch, iStart, showerrs, errs ) ) {
|
|
|
|
TQStringList::Iterator it = lines.begin();
|
|
TQStringList::Iterator itEnd = lines.end();
|
|
it += iStart; //jump ahead past header
|
|
|
|
for ( uint i=iStart; i < lines.count(); i++ ) {
|
|
TQStringList d = TQStringList::split( " ", lines[i] );
|
|
|
|
//Now, if one of the columns is the "Name" field, the name may contain spaces.
|
|
//In this case, the name field will need to be surrounded by quotes.
|
|
//Check for this, and adjust the d list accordingly
|
|
int iname = Columns.findIndex( "Nm" );
|
|
if ( iname >= 0 && d[iname].left(1) == "\"" ) { //multi-word name in quotes
|
|
d[iname] = d[iname].mid(1); //remove leading quote
|
|
//It's possible that the name is one word, but still in quotes
|
|
if ( d[iname].right(1) == "\"" ) {
|
|
d[iname] = d[iname].left( d[iname].length() - 1 );
|
|
} else {
|
|
int iend = iname + 1;
|
|
while ( d[iend].right(1) != "\"" ) {
|
|
d[iname] += " " + d[iend];
|
|
++iend;
|
|
}
|
|
d[iname] += " " + d[iend].left( d[iend].length() - 1 );
|
|
|
|
//remove the entries from d list that were the multiple words in the name
|
|
for ( int j=iname+1; j<=iend; j++ ) {
|
|
d.remove( d.at(iname + 1) ); //index is *not* j, because next item becomes "iname+1" after remove
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( d.count() == Columns.count() ) {
|
|
processCustomDataLine( i, d, Columns, CatalogPrefix, objList, showerrs, errs );
|
|
} else {
|
|
if ( showerrs ) errs.append( i18n( "Line %1 does not contain %2 fields. Skipping it." ).arg( i ).arg( Columns.count() ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( objList.count() ) {
|
|
if ( errs.count() > 0 ) { //some data parsed, but there are errs to report
|
|
TQString message( i18n( "Some lines in the custom catalog could not be parsed; see error messages below." ) + "\n" +
|
|
i18n( "To reject the file, press Cancel. " ) +
|
|
i18n( "To accept the file (ignoring unparsed lines), press Accept." ) );
|
|
if ( KMessageBox::warningContinueCancelList( 0, message, errs,
|
|
i18n( "Some Lines in File Were Invalid" ), i18n( "Accept" ) ) != KMessageBox::Continue ) {
|
|
return 0; //User pressed Cancel, return NULL pointer
|
|
}
|
|
}
|
|
} else { //objList.count() == 0
|
|
if ( showerrs ) {
|
|
TQString message( i18n( "No lines could be parsed from the specified file, see error messages below." ) );
|
|
KMessageBox::informationList( 0, message, errs,
|
|
i18n( "No Valid Data Found in File" ) );
|
|
}
|
|
return 0; //no valid catalog data parsed, return NULL pointer
|
|
}
|
|
|
|
} else { //Error opening catalog file
|
|
if ( showerrs )
|
|
KMessageBox::sorry( 0, i18n( "Could not open custom data file: %1" ).arg( filename ),
|
|
i18n( "Error opening file" ) );
|
|
else
|
|
kdDebug() << i18n( "Could not open custom data file: %1" ).arg( filename ) << endl;
|
|
}
|
|
|
|
//Return the catalog
|
|
if ( objList.count() )
|
|
return new CustomCatalog( CatalogName, CatalogPrefix, CatalogColor, CatalogEpoch, objList );
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool KStarsData::processCustomDataLine( int lnum, TQStringList d, TQStringList Columns,
|
|
TQString Prefix, TQPtrList<SkyObject> &objList, bool showerrs, TQStringList &errs ) {
|
|
|
|
//object data
|
|
unsigned char iType(0);
|
|
dms RA, Dec;
|
|
float mag(0.0), a(0.0), b(0.0), PA(0.0);
|
|
TQString name(""); TQString lname("");
|
|
|
|
for ( uint i=0; i<Columns.count(); i++ ) {
|
|
if ( Columns[i] == "ID" )
|
|
name = Prefix + " " + d[i];
|
|
|
|
if ( Columns[i] == "Nm" )
|
|
lname = d[i];
|
|
|
|
if ( Columns[i] == "RA" ) {
|
|
if ( ! RA.setFromString( d[i], false ) ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Line %1, field %2: Unable to parse RA value: %3" )
|
|
.arg(lnum).arg(i).arg(d[i]) );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( Columns[i] == "Dc" ) {
|
|
if ( ! Dec.setFromString( d[i], true ) ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Line %1, field %2: Unable to parse Dec value: %3" )
|
|
.arg(lnum).arg(i).arg(d[i]) );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( Columns[i] == "Tp" ) {
|
|
bool ok(false);
|
|
iType = d[i].toUInt( &ok );
|
|
if ( ok ) {
|
|
if ( iType == 2 || iType > 8 ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Line %1, field %2: Invalid object type: %3" )
|
|
.arg(lnum).arg(i).arg(d[i]) +
|
|
i18n( "Must be one of 0, 1, 3, 4, 5, 6, 7, 8." ) );
|
|
return false;
|
|
}
|
|
} else {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Line %1, field %2: Unable to parse Object type: %3" )
|
|
.arg(lnum).arg(i).arg(d[i]) );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( Columns[i] == "Mg" ) {
|
|
bool ok(false);
|
|
mag = d[i].toFloat( &ok );
|
|
if ( ! ok ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Line %1, field %2: Unable to parse Magnitude: %3" )
|
|
.arg(lnum).arg(i).arg(d[i]) );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( Columns[i] == "Mj" ) {
|
|
bool ok(false);
|
|
a = d[i].toFloat( &ok );
|
|
if ( ! ok ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Line %1, field %2: Unable to parse Major Axis: %3" )
|
|
.arg(lnum).arg(i).arg(d[i]) );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( Columns[i] == "Mn" ) {
|
|
bool ok(false);
|
|
b = d[i].toFloat( &ok );
|
|
if ( ! ok ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Line %1, field %2: Unable to parse Minor Axis: %3" )
|
|
.arg(lnum).arg(i).arg(d[i]) );
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( Columns[i] == "PA" ) {
|
|
bool ok(false);
|
|
PA = d[i].toFloat( &ok );
|
|
if ( ! ok ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Line %1, field %2: Unable to parse Position Angle: %3" )
|
|
.arg(lnum).arg(i).arg(d[i]) );
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( iType == 0 ) { //Add a star
|
|
StarObject *o = new StarObject( RA, Dec, mag, lname );
|
|
objList.append( o );
|
|
} else { //Add a deep-sky object
|
|
DeepSkyObject *o = new DeepSkyObject( iType, RA, Dec, mag,
|
|
name, "", lname, Prefix, a, b, PA );
|
|
objList.append( o );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool KStarsData::parseCustomDataHeader( TQStringList lines, TQStringList &Columns,
|
|
TQString &CatalogName, TQString &CatalogPrefix, TQString &CatalogColor, float &CatalogEpoch,
|
|
int &iStart, bool showerrs, TQStringList &errs ) {
|
|
|
|
bool foundDataColumns( false ); //set to true if description of data columns found
|
|
int ncol( 0 );
|
|
|
|
TQStringList::Iterator it = lines.begin();
|
|
TQStringList::Iterator itEnd = lines.end();
|
|
|
|
CatalogName = "";
|
|
CatalogPrefix = "";
|
|
CatalogColor = "";
|
|
CatalogEpoch = 0.;
|
|
for ( ; it != itEnd; it++ ) {
|
|
TQString d( *it ); //current data line
|
|
if ( d.left(1) != "#" ) break; //no longer in header!
|
|
|
|
int iname = d.find( "# Name: " );
|
|
int iprefix = d.find( "# Prefix: " );
|
|
int icolor = d.find( "# Color: " );
|
|
int iepoch = d.find( "# Epoch: " );
|
|
|
|
if ( iname == 0 ) { //line contains catalog name
|
|
iname = d.find(":")+2;
|
|
if ( CatalogName.isEmpty() ) {
|
|
CatalogName = d.mid( iname );
|
|
} else { //duplicate name in header
|
|
if ( showerrs )
|
|
errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "Extra Name field in header: %1. Will be ignored" ).arg( d.mid(iname) ) );
|
|
}
|
|
} else if ( iprefix == 0 ) { //line contains catalog prefix
|
|
iprefix = d.find(":")+2;
|
|
if ( CatalogPrefix.isEmpty() ) {
|
|
CatalogPrefix = d.mid( iprefix );
|
|
} else { //duplicate prefix in header
|
|
if ( showerrs )
|
|
errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "Extra Prefix field in header: %1. Will be ignored" ).arg( d.mid(iprefix) ) );
|
|
}
|
|
} else if ( icolor == 0 ) { //line contains catalog prefix
|
|
icolor = d.find(":")+2;
|
|
if ( CatalogColor.isEmpty() ) {
|
|
CatalogColor = d.mid( icolor );
|
|
} else { //duplicate prefix in header
|
|
if ( showerrs )
|
|
errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "Extra Color field in header: %1. Will be ignored" ).arg( d.mid(icolor) ) );
|
|
}
|
|
} else if ( iepoch == 0 ) { //line contains catalog epoch
|
|
iepoch = d.find(":")+2;
|
|
if ( CatalogEpoch == 0. ) {
|
|
bool ok( false );
|
|
CatalogEpoch = d.mid( iepoch ).toFloat( &ok );
|
|
if ( !ok ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "Could not convert Epoch to float: %1. Using 2000. instead" ).arg( d.mid(iepoch) ) );
|
|
CatalogEpoch = 2000.; //adopt default value
|
|
}
|
|
} else { //duplicate epoch in header
|
|
if ( showerrs )
|
|
errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "Extra Epoch field in header: %1. Will be ignored" ).arg( d.mid(iepoch) ) );
|
|
}
|
|
} else if ( ! foundDataColumns ) { //don't try to parse data column descriptors if we already found them
|
|
//Chomp off leading "#" character
|
|
d = d.replace( TQRegExp( "#" ), "" );
|
|
|
|
TQStringList fields = TQStringList::split( " ", d ); //split on whitespace
|
|
|
|
//we need a copy of the master list of data fields, so we can
|
|
//remove fields from it as they are encountered in the "fields" list.
|
|
//this allows us to detect duplicate entries
|
|
TQStringList master( KStarsData::CustomColumns );
|
|
|
|
TQStringList::Iterator itf = fields.begin();
|
|
TQStringList::Iterator itfEnd = fields.end();
|
|
|
|
for ( ; itf != itfEnd; itf++ ) {
|
|
TQString s( *itf );
|
|
if ( master.contains( s ) ) {
|
|
//add the data field
|
|
Columns.append( s );
|
|
|
|
// remove the field from the master list and inc the
|
|
// count of "good" columns (unless field is "Ignore")
|
|
if ( s != "Ig" ) {
|
|
master.remove( master.find( s ) );
|
|
ncol++;
|
|
}
|
|
} else if ( fields.contains( s ) ) { //duplicate field
|
|
fields.append( "Ig" ); //skip this column
|
|
if ( showerrs )
|
|
errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "Duplicate data field descriptor \"%1\" will be ignored" ).arg( s ) );
|
|
} else { //Invalid field
|
|
fields.append( "Ig" ); //skip this column
|
|
if ( showerrs )
|
|
errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "Invalid data field descriptor \"%1\" will be ignored" ).arg( s ) );
|
|
}
|
|
}
|
|
|
|
if ( ncol ) foundDataColumns = true;
|
|
}
|
|
}
|
|
|
|
if ( ! foundDataColumns ) {
|
|
if ( showerrs )
|
|
errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "No valid column descriptors found. Exiting" ) );
|
|
return false;
|
|
}
|
|
|
|
if ( it == itEnd ) {
|
|
if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "No data lines found after header. Exiting." ) );
|
|
return false; //fatal error
|
|
} else {
|
|
//Make sure Name, Prefix, Color and Epoch were set
|
|
if ( CatalogName.isEmpty() ) {
|
|
if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "No Catalog Name specified; setting to \"Custom\"" ) );
|
|
CatalogName = i18n("Custom");
|
|
}
|
|
if ( CatalogPrefix.isEmpty() ) {
|
|
if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "No Catalog Prefix specified; setting to \"CC\"" ) );
|
|
CatalogPrefix = "CC";
|
|
}
|
|
if ( CatalogColor.isEmpty() ) {
|
|
if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "No Catalog Color specified; setting to Red" ) );
|
|
CatalogColor = "#CC0000";
|
|
}
|
|
if ( CatalogEpoch == 0. ) {
|
|
if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
|
|
i18n( "No Catalog Epoch specified; assuming 2000." ) );
|
|
CatalogEpoch = 2000.;
|
|
}
|
|
|
|
//the it iterator now points to the first line past the header
|
|
iStart = lines.findIndex( TQString( *it ) );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool KStarsData::processCity( TQString& line ) {
|
|
TQString totalLine;
|
|
TQString name, province, country;
|
|
TQStringList fields;
|
|
TimeZoneRule *TZrule;
|
|
bool intCheck = true;
|
|
char latsgn, lngsgn;
|
|
int lngD, lngM, lngS;
|
|
int latD, latM, latS;
|
|
double TZ;
|
|
float lng, lat;
|
|
|
|
totalLine = line;
|
|
|
|
// separate fields
|
|
fields = TQStringList::split( ":", line );
|
|
|
|
for ( unsigned int i=0; i< fields.count(); ++i )
|
|
fields[i] = fields[i].stripWhiteSpace();
|
|
|
|
if ( fields.count() < 11 ) {
|
|
kdDebug()<< i18n( "Cities.dat: Ran out of fields. Line was:" ) <<endl;
|
|
kdDebug()<< totalLine.local8Bit() <<endl;
|
|
return false;
|
|
} else if ( fields.count() < 12 ) {
|
|
// allow old format (without TZ) for mycities.dat
|
|
fields.append("");
|
|
fields.append("--");
|
|
} else if ( fields.count() < 13 ) {
|
|
// Set TZrule to "--"
|
|
fields.append("--");
|
|
}
|
|
|
|
name = fields[0];
|
|
province = fields[1];
|
|
country = fields[2];
|
|
|
|
latD = fields[3].toInt( &intCheck );
|
|
if ( !intCheck ) {
|
|
kdDebug() << fields[3] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
|
|
latM = fields[4].toInt( &intCheck );
|
|
if ( !intCheck ) {
|
|
kdDebug() << fields[4] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
|
|
latS = fields[5].toInt( &intCheck );
|
|
if ( !intCheck ) {
|
|
kdDebug() << fields[5] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
|
|
TQChar ctemp = fields[6].at(0);
|
|
latsgn = ctemp;
|
|
if (latsgn != 'N' && latsgn != 'S') {
|
|
kdDebug() << latsgn << i18n( "\nCities.dat: Invalid latitude sign. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
|
|
lngD = fields[7].toInt( &intCheck );
|
|
if ( !intCheck ) {
|
|
kdDebug() << fields[7] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
|
|
lngM = fields[8].toInt( &intCheck );
|
|
if ( !intCheck ) {
|
|
kdDebug() << fields[8] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
|
|
lngS = fields[9].toInt( &intCheck );
|
|
if ( !intCheck ) {
|
|
kdDebug() << fields[9] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
|
|
ctemp = fields[10].at(0);
|
|
lngsgn = ctemp;
|
|
if (lngsgn != 'E' && lngsgn != 'W') {
|
|
kdDebug() << latsgn << i18n( "\nCities.dat: Invalid longitude sign. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
|
|
lat = (float)latD + ((float)latM + (float)latS/60.0)/60.0;
|
|
lng = (float)lngD + ((float)lngM + (float)lngS/60.0)/60.0;
|
|
|
|
if ( latsgn == 'S' ) lat *= -1.0;
|
|
if ( lngsgn == 'W' ) lng *= -1.0;
|
|
|
|
// find time zone. Use value from Cities.dat if available.
|
|
// otherwise use the old approximation: int(lng/15.0);
|
|
if ( fields[11].isEmpty() || ('x' == fields[11].at(0)) ) {
|
|
TZ = int(lng/15.0);
|
|
} else {
|
|
bool doubleCheck = true;
|
|
TZ = fields[11].toDouble( &doubleCheck);
|
|
if ( !doubleCheck ) {
|
|
kdDebug() << fields[11] << i18n( "\nCities.dat: Bad time zone. Line was:\n" ) << totalLine << endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//last field is the TimeZone Rule ID.
|
|
TZrule = &( Rulebook[ fields[12] ] );
|
|
|
|
// if ( fields[12]=="--" )
|
|
// kdDebug() << "Empty rule start month: " << TZrule->StartMonth << endl;
|
|
geoList.append ( new GeoLocation( lng, lat, name, province, country, TZ, TZrule )); // appends city names to list
|
|
return true;
|
|
}
|
|
|
|
bool KStarsData::readTimeZoneRulebook( void ) {
|
|
TQFile file;
|
|
TQString id;
|
|
|
|
if ( KSUtils::openDataFile( file, "TZrules.dat" ) ) {
|
|
TQTextStream stream( &file );
|
|
|
|
while ( !stream.eof() ) {
|
|
TQString line = stream.readLine().stripWhiteSpace();
|
|
if ( line.left(1) != "#" && line.length() ) { //ignore commented and blank lines
|
|
TQStringList fields = TQStringList::split( " ", line );
|
|
id = fields[0];
|
|
TQTime stime = TQTime( fields[3].left( fields[3].find(':')).toInt() ,
|
|
fields[3].mid( fields[3].find(':')+1, fields[3].length()).toInt() );
|
|
TQTime rtime = TQTime( fields[6].left( fields[6].find(':')).toInt(),
|
|
fields[6].mid( fields[6].find(':')+1, fields[6].length()).toInt() );
|
|
|
|
Rulebook[ id ] = TimeZoneRule( fields[1], fields[2], stime, fields[4], fields[5], rtime );
|
|
}
|
|
}
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool KStarsData::readCityData( void ) {
|
|
TQFile file;
|
|
bool citiesFound = false;
|
|
|
|
// begin new code
|
|
if ( KSUtils::openDataFile( file, "Cities.dat" ) ) {
|
|
KSFileReader fileReader( file ); // close file is included
|
|
while ( fileReader.hasMoreLines() ) {
|
|
citiesFound |= processCity( fileReader.readLine() );
|
|
}
|
|
}
|
|
// end new code
|
|
|
|
//check for local cities database, but don't require it.
|
|
file.setName( locate( "appdata", "mycities.dat" ) ); //determine filename in local user KDE directory tree.
|
|
if ( file.exists() && file.open( IO_ReadOnly ) ) {
|
|
TQTextStream stream( &file );
|
|
|
|
while ( !stream.eof() ) {
|
|
TQString line = stream.readLine();
|
|
citiesFound |= processCity( line );
|
|
} // while ( !stream.eof() )
|
|
file.close();
|
|
} // if ( fileopen() )
|
|
|
|
return citiesFound;
|
|
}
|
|
|
|
void KStarsData::setMagnitude( float newMagnitude, bool forceReload ) {
|
|
// only reload data if not loaded yet
|
|
// if checkDataPumpAction() detects that new magnitude is higher than the
|
|
// loaded, it can force a reload
|
|
if ( newMagnitude > maxSetMagnitude || forceReload ) {
|
|
maxSetMagnitude = newMagnitude; // store new highest magnitude level
|
|
|
|
if (reloadingData() == false) { // if not already reloading data
|
|
source = new FileSource(this, newMagnitude);
|
|
loader = new StarDataSink(this);
|
|
connect(loader, TQ_SIGNAL(done()), this, TQ_SLOT(checkDataPumpAction()));
|
|
connect(loader, TQ_SIGNAL(updateSkymap()), this, TQ_SLOT(updateSkymap()));
|
|
connect(loader, TQ_SIGNAL(clearCache()), this, TQ_SLOT(sendClearCache()));
|
|
// start reloading
|
|
pump = new TQDataPump (source, (TQDataSink*) loader);
|
|
}
|
|
} /*else if ( newMagnitude < maxSetMagnitude ) {
|
|
StarObject *lastStar = starList.last();
|
|
while ( lastStar->mag() > newMagnitude && starList.count() ) {
|
|
//check if star is named. If so, remove it from ObjNames
|
|
if ( ! lastStar->name().isEmpty() ) {
|
|
ObjNames.remove( lastStar->name() );
|
|
}
|
|
starList.removeLast();
|
|
lastStar = starList.last();
|
|
|
|
//Need to recompute names of objects
|
|
sendClearCache();
|
|
}
|
|
}*/
|
|
|
|
// change current magnitude level in KStarsOptions
|
|
Options::setMagLimitDrawStar( newMagnitude );
|
|
}
|
|
|
|
void KStarsData::checkDataPumpAction() {
|
|
// it will set to true if new data should be reloaded
|
|
bool reloadMoreData = false;
|
|
if (source != 0) {
|
|
// check if a new reload must be started
|
|
if (source->magnitude() < maxSetMagnitude) reloadMoreData = true;
|
|
delete source;
|
|
source = 0;
|
|
}
|
|
if (pump != 0) { // if pump exists
|
|
delete pump;
|
|
pump = 0;
|
|
}
|
|
if (loader != 0) { // if loader exists
|
|
delete loader;
|
|
loader = 0;
|
|
}
|
|
// If magnitude was changed while reloading data start a new reload of data.
|
|
if (reloadMoreData == true) {
|
|
setMagnitude(maxSetMagnitude, true);
|
|
}
|
|
}
|
|
|
|
bool KStarsData::reloadingData() {
|
|
return ( pump || loader || source ); // true if variables != 0
|
|
}
|
|
|
|
void KStarsData::updateSkymap() {
|
|
emit update();
|
|
}
|
|
|
|
void KStarsData::sendClearCache() {
|
|
emit clearCache();
|
|
}
|
|
|
|
void KStarsData::initialize() {
|
|
if (startupComplete) return;
|
|
|
|
initTimer = new TQTimer;
|
|
TQObject::connect(initTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT( slotInitialize() ) );
|
|
initCounter = 0;
|
|
initTimer->start(1);
|
|
}
|
|
|
|
void KStarsData::initError(TQString s, bool required = false) {
|
|
TQString message, caption;
|
|
initTimer->stop();
|
|
if (required) {
|
|
message = i18n( "The file %1 could not be found. "
|
|
"KStars cannot run properly without this file. "
|
|
"To continue loading, place the file in one of the "
|
|
"following locations, then press Retry:\n\n" ).arg( s )
|
|
+ TQString( "\t$(TDEDIR)/share/apps/kstars/%1\n" ).arg( s )
|
|
+ TQString( "\t~/.trinity/share/apps/kstars/%1\n\n" ).arg( s )
|
|
+ i18n( "Otherwise, press Cancel to shutdown." );
|
|
caption = i18n( "Critical File Not Found: %1" ).arg( s );
|
|
} else {
|
|
message = i18n( "The file %1 could not be found. "
|
|
"KStars can still run without this file. "
|
|
"However, to avoid seeing this message in the future, you can "
|
|
"place the file in one of the following locations, then press Retry:\n\n" ).arg( s )
|
|
+ TQString( "\t$(TDEDIR)/share/apps/kstars/%1\n" ).arg( s )
|
|
+ TQString( "\t~/.trinity/share/apps/kstars/%1\n\n" ).arg( s )
|
|
+ i18n( "Otherwise, press Cancel to continue loading without this file." ).arg( s );
|
|
caption = i18n( "Non-Critical File Not Found: %1" ).arg( s );
|
|
}
|
|
|
|
if ( KMessageBox::warningContinueCancel( 0, message, caption, i18n( "Retry" ) ) == KMessageBox::Continue ) {
|
|
initCounter--;
|
|
initTimer->start(1);
|
|
} else {
|
|
if (required) {
|
|
delete initTimer;
|
|
initTimer = 0L;
|
|
emit initFinished(false);
|
|
} else {
|
|
initTimer->start(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void KStarsData::slotInitialize() {
|
|
TQFile imFile;
|
|
TQString ImageName;
|
|
|
|
kapp->flush(); // flush all paint events before loading data
|
|
|
|
switch ( initCounter )
|
|
{
|
|
case 0: //Load Time Zone Rules//
|
|
emit progressText( i18n("Reading Time Zone Rules") );
|
|
|
|
if (objects==1) {
|
|
// timezone rules
|
|
if ( !readTimeZoneRulebook( ) )
|
|
initError( "TZrules.dat", true );
|
|
}
|
|
|
|
// read INDI hosts file, not required
|
|
readINDIHosts();
|
|
break;
|
|
|
|
case 1: //Load Cities//
|
|
{
|
|
if (objects>1) break;
|
|
|
|
emit progressText( i18n("Loading City Data") );
|
|
|
|
if ( !readCityData( ) )
|
|
initError( "Cities.dat", true );
|
|
|
|
break;
|
|
}
|
|
|
|
case 2: //Load stellar database//
|
|
|
|
emit progressText(i18n("Loading Star Data (%1%)" ).arg(0) );
|
|
if ( !readStarData( ) )
|
|
initError( "hipNNN.dat", true );
|
|
if (!readVARData())
|
|
initError( "valaav.dat", false);
|
|
if (!readADVTreeData())
|
|
initError( "advinterface.dat", false);
|
|
break;
|
|
|
|
case 3: //Load NGC/IC database and custom catalogs//
|
|
|
|
emit progressText( i18n("Loading NGC/IC Data (%1%)" ).arg(0) );
|
|
if ( !readDeepSkyData( ) )
|
|
initError( "ngcicN.dat", true );
|
|
|
|
emit progressText( i18n("Loading Custom catalogs" ) );
|
|
readCustomCatalogs( );
|
|
// if ( !readCustomCatalogs( ) )
|
|
// initError( "<custom catalog>", true );
|
|
break;
|
|
|
|
case 4: //Load Constellation lines//
|
|
|
|
emit progressText( i18n("Loading Constellations" ) );
|
|
if ( !readCLineData( ) )
|
|
initError( "clines.dat", true );
|
|
break;
|
|
|
|
case 5: //Load Constellation names//
|
|
|
|
emit progressText( i18n("Loading Constellation Names" ) );
|
|
if ( !readCNameData( ) )
|
|
initError( cnameFile, true );
|
|
break;
|
|
|
|
case 6: //Load Constellation boundaries//
|
|
|
|
emit progressText( i18n("Loading Constellation Boundaries" ) );
|
|
if ( !readCBoundData( ) )
|
|
initError( "cbound.dat", true );
|
|
break;
|
|
|
|
case 7: //Load Milky Way//
|
|
|
|
emit progressText( i18n("Loading Milky Way" ) );
|
|
if ( !readMWData( ) )
|
|
initError( "mw*.dat", true );
|
|
break;
|
|
|
|
case 8: //Initialize the Planets//
|
|
|
|
emit progressText( i18n("Creating Planets" ) );
|
|
if (PCat->initialize())
|
|
PCat->addObject( ObjNames );
|
|
|
|
jmoons = new JupiterMoons();
|
|
break;
|
|
|
|
case 9: //Initialize Asteroids & Comets//
|
|
|
|
emit progressText( i18n( "Creating Asteroids and Comets" ) );
|
|
if ( !readAsteroidData() )
|
|
initError( "asteroids.dat", false );
|
|
if ( !readCometData() )
|
|
initError( "comets.dat", false );
|
|
|
|
break;
|
|
|
|
case 10: //Initialize the Moon//
|
|
|
|
emit progressText( i18n("Creating Moon" ) );
|
|
Moon = new KSMoon(this);
|
|
ObjNames.append( Moon );
|
|
Moon->loadData();
|
|
break;
|
|
|
|
case 11: //Load Image URLs//
|
|
|
|
emit progressText( i18n("Loading Image URLs" ) );
|
|
if ( !readURLData( "image_url.dat", 0 ) ) {
|
|
initError( "image_url.dat", false );
|
|
}
|
|
//if ( !readURLData( "myimage_url.dat", 0 ) ) {
|
|
//Don't do anything if the local file is not found.
|
|
//}
|
|
// doesn't belong here, only temp
|
|
readUserLog();
|
|
|
|
break;
|
|
|
|
case 12: //Load Information URLs//
|
|
|
|
emit progressText( i18n("Loading Information URLs" ) );
|
|
if ( !readURLData( "info_url.dat", 1 ) ) {
|
|
initError( "info_url.dat", false );
|
|
}
|
|
//if ( !readURLData( "myinfo_url.dat", 1 ) ) {
|
|
//Don't do anything if the local file is not found.
|
|
//}
|
|
break;
|
|
|
|
default:
|
|
initTimer->stop();
|
|
delete initTimer;
|
|
initTimer = 0L;
|
|
startupComplete = true;
|
|
emit initFinished(true);
|
|
break;
|
|
} // switch ( initCounter )
|
|
|
|
initCounter++;
|
|
}
|
|
|
|
void KStarsData::initGuides(KSNumbers *num)
|
|
{
|
|
// Define the Celestial Equator
|
|
for ( unsigned int i=0; i<NCIRCLE; ++i ) {
|
|
SkyPoint *o = new SkyPoint( i*24./NCIRCLE, 0.0 );
|
|
o->EquatorialToHorizontal( LST, geo()->lat() );
|
|
Equator.append( o );
|
|
}
|
|
|
|
// Define the horizon.
|
|
// Use the celestial Equator as a convenient starting point, but instead of RA and Dec,
|
|
// interpret the coordinates as azimuth and altitude, and then convert to RA, dec.
|
|
// The horizon will be redefined whenever the positions of sky objects are updated.
|
|
dms temp( 0.0 );
|
|
for (SkyPoint *point = Equator.first(); point; point = Equator.next()) {
|
|
double sinlat, coslat, sindec, cosdec, sinAz, cosAz;
|
|
double HARad;
|
|
dms dec, HA, RA, Az;
|
|
Az = dms(*(point->ra()));
|
|
|
|
Az.SinCos( sinAz, cosAz );
|
|
geo()->lat()->SinCos( sinlat, coslat );
|
|
|
|
dec.setRadians( asin( coslat*cosAz ) );
|
|
dec.SinCos( sindec, cosdec );
|
|
|
|
HARad = acos( -1.0*(sinlat*sindec)/(coslat*cosdec) );
|
|
if ( sinAz > 0.0 ) { HARad = 2.0*dms::PI - HARad; }
|
|
HA.setRadians( HARad );
|
|
RA = LST->Degrees() - HA.Degrees();
|
|
|
|
SkyPoint *o = new SkyPoint( RA, dec );
|
|
o->setAlt( 0.0 );
|
|
o->setAz( Az );
|
|
|
|
Horizon.append( o );
|
|
|
|
//Define the Ecliptic (use the same ListIteration; interpret coordinates as Ecliptic long/lat)
|
|
o = new SkyPoint( 0.0, 0.0 );
|
|
o->setFromEcliptic( num->obliquity(), point->ra(), &temp );
|
|
o->EquatorialToHorizontal( LST, geo()->lat() );
|
|
Ecliptic.append( o );
|
|
}
|
|
}
|
|
|
|
void KStarsData::resetToNewDST(const GeoLocation *geo, const bool automaticDSTchange) {
|
|
// reset tzrules data with local time, timezone offset and time direction (forward or backward)
|
|
// force a DST change with option true for 3. parameter
|
|
geo->tzrule()->reset_with_ltime( LTime, geo->TZ0(), TimeRunsForward, automaticDSTchange );
|
|
// reset next DST change time
|
|
setNextDSTChange( geo->tzrule()->nextDSTChange() );
|
|
//reset LTime, because TZoffset has changed
|
|
LTime = geo->UTtoLT( ut() );
|
|
}
|
|
|
|
void KStarsData::updateTime( GeoLocation *geo, SkyMap *skymap, const bool automaticDSTchange ) {
|
|
// sync LTime with the simulation clock
|
|
LTime = geo->UTtoLT( ut() );
|
|
syncLST();
|
|
|
|
//Only check DST if (1) TZrule is not the empty rule, and (2) if we have crossed
|
|
//the DST change date/time.
|
|
if ( !geo->tzrule()->isEmptyRule() ) {
|
|
if ( TimeRunsForward ) {
|
|
// timedirection is forward
|
|
// DST change happens if current date is bigger than next calculated dst change
|
|
if ( ut() > NextDSTChange ) resetToNewDST(geo, automaticDSTchange);
|
|
} else {
|
|
// timedirection is backward
|
|
// DST change happens if current date is smaller than next calculated dst change
|
|
if ( ut() < NextDSTChange ) resetToNewDST(geo, automaticDSTchange);
|
|
}
|
|
}
|
|
|
|
KSNumbers num( ut().djd() );
|
|
|
|
bool needNewCoords = false;
|
|
if ( fabs( ut().djd() - LastNumUpdate.djd() ) > 1.0 ) {
|
|
//update time-dependent variables once per day
|
|
needNewCoords = true;
|
|
LastNumUpdate = ut().djd();
|
|
}
|
|
|
|
// Update positions of objects, if necessary
|
|
if ( fabs( ut().djd() - LastPlanetUpdate.djd() ) > 0.01 ) {
|
|
LastPlanetUpdate = ut().djd();
|
|
|
|
if ( Options::showPlanets() ) PCat->findPosition( &num, geo->lat(), LST );
|
|
|
|
//Asteroids
|
|
if ( Options::showPlanets() && Options::showAsteroids() )
|
|
for ( KSAsteroid *ast = asteroidList.first(); ast; ast = asteroidList.next() )
|
|
ast->findPosition( &num, geo->lat(), LST, earth() );
|
|
|
|
//Comets
|
|
if ( Options::showPlanets() && Options::showComets() )
|
|
for ( KSComet *com = cometList.first(); com; com = cometList.next() )
|
|
com->findPosition( &num, geo->lat(), LST, earth() );
|
|
|
|
//Recompute the Ecliptic
|
|
if ( Options::showEcliptic() ) {
|
|
Ecliptic.clear();
|
|
|
|
dms temp(0.0);
|
|
for ( unsigned int i=0; i<Equator.count(); ++i ) {
|
|
SkyPoint *o = new SkyPoint( 0.0, 0.0 );
|
|
o->setFromEcliptic( num.obliquity(), Equator.at(i)->ra(), &temp );
|
|
Ecliptic.append( o );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Moon moves ~30 arcmin/hr, so update its position every minute.
|
|
if ( fabs( ut().djd() - LastMoonUpdate.djd() ) > 0.00069444 ) {
|
|
LastMoonUpdate = ut();
|
|
if ( Options::showMoon() ) {
|
|
Moon->findPosition( &num, geo->lat(), LST );
|
|
Moon->findPhase( PCat->planetSun() );
|
|
}
|
|
|
|
//for now, update positions of Jupiter's moons here also
|
|
if ( Options::showPlanets() && Options::showJupiter() )
|
|
jmoons->findPosition( &num, (const KSPlanet*)PCat->findByName("Jupiter"), PCat->planetSun() );
|
|
}
|
|
|
|
//Update Alt/Az coordinates. Timescale varies with zoom level
|
|
//If Clock is in Manual Mode, always update. (?)
|
|
if ( fabs( ut().djd() - LastSkyUpdate.djd() ) > 0.25/Options::zoomFactor() || clock()->isManualMode() ) {
|
|
LastSkyUpdate = ut();
|
|
|
|
//Recompute Alt, Az coords for all objects
|
|
//Planets
|
|
//This updates trails as well
|
|
PCat->EquatorialToHorizontal( LST, geo->lat() );
|
|
|
|
jmoons->EquatorialToHorizontal( LST, geo->lat() );
|
|
if ( Options::showMoon() ) {
|
|
Moon->EquatorialToHorizontal( LST, geo->lat() );
|
|
if ( Moon->hasTrail() ) Moon->updateTrail( LST, geo->lat() );
|
|
}
|
|
|
|
// //Planet Trails
|
|
// for( SkyPoint *p = PlanetTrail.first(); p; p = PlanetTrail.next() )
|
|
// p->EquatorialToHorizontal( LST, geo->lat() );
|
|
|
|
//Asteroids
|
|
if ( Options::showAsteroids() ) {
|
|
for ( KSAsteroid *ast = asteroidList.first(); ast; ast = asteroidList.next() ) {
|
|
ast->EquatorialToHorizontal( LST, geo->lat() );
|
|
if ( ast->hasTrail() ) ast->updateTrail( LST, geo->lat() );
|
|
}
|
|
}
|
|
|
|
//Comets
|
|
if ( Options::showComets() ) {
|
|
for ( KSComet *com = cometList.first(); com; com = cometList.next() ) {
|
|
com->EquatorialToHorizontal( LST, geo->lat() );
|
|
if ( com->hasTrail() ) com->updateTrail( LST, geo->lat() );
|
|
}
|
|
}
|
|
|
|
//Stars (need to update if constell. lines or stars are shown)
|
|
if ( Options::showStars() || Options::showCLines() ) {
|
|
// use MINDRAWSTARMAG for calculating constellation lines right
|
|
float mag = Options::magLimitDrawStar();
|
|
if (mag < MINDRAWSTARMAG) mag = MINDRAWSTARMAG;
|
|
for ( StarObject *star = starList.first(); star; star = starList.next() ) {
|
|
if ( star->mag() > mag ) break;
|
|
if (needNewCoords) star->updateCoords( &num );
|
|
star->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
|
|
//Deep-sky objects. Keep lists separated for performance reasons
|
|
if ( Options::showMessier() || Options::showMessierImages() ) {
|
|
for ( SkyObject *o = deepSkyListMessier.first(); o; o = deepSkyListMessier.next() ) {
|
|
if (needNewCoords) o->updateCoords( &num );
|
|
o->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
if ( Options::showNGC() ) {
|
|
for ( SkyObject *o = deepSkyListNGC.first(); o; o = deepSkyListNGC.next() ) {
|
|
if (needNewCoords) o->updateCoords( &num );
|
|
o->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
if ( Options::showIC() ) {
|
|
for ( SkyObject *o = deepSkyListIC.first(); o; o = deepSkyListIC.next() ) {
|
|
if (needNewCoords) o->updateCoords( &num );
|
|
o->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
if ( Options::showOther() ) {
|
|
for ( SkyObject *o = deepSkyListOther.first(); o; o = deepSkyListOther.next() ) {
|
|
if (needNewCoords) o->updateCoords( &num );
|
|
o->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
|
|
|
|
//Custom Catalogs
|
|
for ( unsigned int j=0; j< CustomCatalogs.count(); ++j ) {
|
|
TQPtrList<SkyObject> cat = CustomCatalogs.at(j)->objList();
|
|
if ( Options::showCatalog()[j] ) {
|
|
for ( SkyObject *o = cat.first(); o; o = cat.next() ) {
|
|
if (needNewCoords) o->updateCoords( &num );
|
|
o->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
}
|
|
|
|
//Milky Way
|
|
if ( Options::showMilkyWay() ) {
|
|
for ( unsigned int j=0; j<11; ++j ) {
|
|
for ( SkyPoint *p = MilkyWay[j].first(); p; p = MilkyWay[j].next() ) {
|
|
if (needNewCoords) p->updateCoords( &num );
|
|
p->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
}
|
|
|
|
//CNames
|
|
if ( Options::showCNames() ) {
|
|
for ( SkyPoint *p = cnameList.first(); p; p = cnameList.next() ) {
|
|
if (needNewCoords) p->updateCoords( &num );
|
|
p->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
|
|
//Constellation Boundaries
|
|
if ( Options::showCBounds() ) {
|
|
for ( CSegment *seg = csegmentList.first(); seg; seg = csegmentList.next() ) {
|
|
for ( SkyPoint *p = seg->firstNode(); p; p = seg->nextNode() ) {
|
|
if ( needNewCoords ) p->updateCoords( &num );
|
|
p->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
}
|
|
|
|
//Celestial Equator
|
|
if ( Options::showEquator() ) {
|
|
for ( SkyPoint *p = Equator.first(); p; p = Equator.next() ) {
|
|
p->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
|
|
//Ecliptic
|
|
if ( Options::showEcliptic() ) {
|
|
for ( SkyPoint *p = Ecliptic.first(); p; p = Ecliptic.next() ) {
|
|
p->EquatorialToHorizontal( LST, geo->lat() );
|
|
}
|
|
}
|
|
|
|
//Horizon: different than the others; Alt & Az remain constant, RA, Dec must keep up
|
|
if ( Options::showHorizon() || Options::showGround() ) {
|
|
for ( SkyPoint *p = Horizon.first(); p; p = Horizon.next() ) {
|
|
p->HorizontalToEquatorial( LST, geo->lat() );
|
|
}
|
|
}
|
|
|
|
for (SkyObject *o = INDITelescopeList.first(); o; o = INDITelescopeList.next())
|
|
o->EquatorialToHorizontal(LST, geo->lat());
|
|
|
|
//Update focus
|
|
skymap->updateFocus();
|
|
|
|
if ( clock()->isManualMode() )
|
|
TQTimer::singleShot( 0, skymap, TQ_SLOT( forceUpdateNow() ) );
|
|
else skymap->forceUpdate();
|
|
}
|
|
}
|
|
|
|
void KStarsData::setTimeDirection( float scale ) {
|
|
TimeRunsForward = ( scale < 0 ? false : true );
|
|
}
|
|
|
|
void KStarsData::setFullTimeUpdate() {
|
|
LastSkyUpdate.setDJD( (long double)INVALID_DAY );
|
|
LastPlanetUpdate.setDJD( (long double)INVALID_DAY );
|
|
LastMoonUpdate.setDJD( (long double)INVALID_DAY );
|
|
LastNumUpdate.setDJD( (long double)INVALID_DAY );
|
|
}
|
|
|
|
void KStarsData::setLocationFromOptions() {
|
|
TQMap<TQString, TimeZoneRule>::Iterator it = Rulebook.find( Options::dST() );
|
|
setLocation( GeoLocation ( Options::longitude(), Options::latitude(),
|
|
Options::cityName(), Options::provinceName(), Options::countryName(),
|
|
Options::timeZone(), &(it.data()), 4, Options::elevation() ) );
|
|
}
|
|
|
|
void KStarsData::setLocation( const GeoLocation &l ) {
|
|
GeoLocation g( l );
|
|
if ( g.lat()->Degrees() >= 90.0 ) g.setLat( 89.99 );
|
|
if ( g.lat()->Degrees() <= -90.0 ) g.setLat( -89.99 );
|
|
|
|
Geo = g;
|
|
|
|
//store data in the Options objects
|
|
Options::setCityName( g.name() );
|
|
Options::setProvinceName( g.province() );
|
|
Options::setCountryName( g.country() );
|
|
Options::setTimeZone( g.TZ0() );
|
|
Options::setElevation( g.height() );
|
|
Options::setLongitude( g.lng()->Degrees() );
|
|
Options::setLatitude( g.lat()->Degrees() );
|
|
}
|
|
|
|
void KStarsData::syncLST() {
|
|
LST->set( geo()->GSTtoLST( ut().gst() ) );
|
|
}
|
|
|
|
void KStarsData::changeDateTime( const KStarsDateTime &newDate ) {
|
|
//Turn off animated slews for the next time step.
|
|
setSnapNextFocus();
|
|
|
|
clock()->setUTC( newDate );
|
|
LTime = geo()->UTtoLT( ut() );
|
|
//set local sideral time
|
|
syncLST();
|
|
|
|
//Make sure Numbers, Moon, planets, and sky objects are updated immediately
|
|
setFullTimeUpdate();
|
|
|
|
// reset tzrules data with new local time and time direction (forward or backward)
|
|
geo()->tzrule()->reset_with_ltime(LTime, geo()->TZ0(), isTimeRunningForward() );
|
|
|
|
// reset next dst change time
|
|
setNextDSTChange( geo()->tzrule()->nextDSTChange() );
|
|
}
|
|
|
|
SkyObject* KStarsData::objectNamed( const TQString &name ) {
|
|
if ( (name== "star") || (name== "nothing") || name.isEmpty() ) return NULL;
|
|
if ( name== Moon->name() ) return Moon;
|
|
|
|
SkyObject *so = PCat->findByName(name);
|
|
|
|
if (so != 0)
|
|
return so;
|
|
|
|
//Stars
|
|
for ( unsigned int i=0; i<starList.count(); ++i ) {
|
|
if ( name==starList.at(i)->name() ) return starList.at(i);
|
|
}
|
|
|
|
//Deep sky objects
|
|
for ( unsigned int i=0; i<deepSkyListMessier.count(); ++i ) {
|
|
if ( name==deepSkyListMessier.at(i)->name() ) return deepSkyListMessier.at(i);
|
|
}
|
|
for ( unsigned int i=0; i<deepSkyListNGC.count(); ++i ) {
|
|
if ( name==deepSkyListNGC.at(i)->name() ) return deepSkyListNGC.at(i);
|
|
}
|
|
for ( unsigned int i=0; i<deepSkyListIC.count(); ++i ) {
|
|
if ( name==deepSkyListIC.at(i)->name() ) return deepSkyListIC.at(i);
|
|
}
|
|
for ( unsigned int i=0; i<deepSkyListOther.count(); ++i ) {
|
|
if ( name==deepSkyListOther.at(i)->name() ) return deepSkyListOther.at(i);
|
|
}
|
|
|
|
//Constellations
|
|
for ( unsigned int i=0; i<cnameList.count(); ++i ) {
|
|
if ( name==cnameList.at(i)->name() ) return cnameList.at(i);
|
|
}
|
|
|
|
//Still no match. Try interpreting the string as a genetive star name
|
|
//(with ascii characters instead of a Greek letter)
|
|
for ( unsigned int i=0; i<starList.count(); ++i ) {
|
|
if ( name==starList.at(i)->gname( false ) ) return starList.at(i);
|
|
}
|
|
|
|
//Custom catalogs.
|
|
for ( unsigned int i=0; i<CustomCatalogs.count(); ++i ) {
|
|
TQPtrList<SkyObject> custCatObjs = CustomCatalogs.at(i)->objList();
|
|
for ( unsigned int j = 0; j < custCatObjs.count(); ++j ) {
|
|
if ( name==custCatObjs.at(j)->name() ) return custCatObjs.at(j);
|
|
}
|
|
}
|
|
|
|
//reach here only if argument is not matched
|
|
return NULL;
|
|
}
|
|
|
|
//"pseudo-execute" a shell script, ignoring all interactive aspects. Just use
|
|
//the portions of the script that change the state of the program. This is only
|
|
//used for image-dump mode, where the GUI is not running. So, some things (such as
|
|
//waitForKey()) don't make sense and should be ignored.
|
|
//also, even functions that do make sense in this context have aspects that should
|
|
//be modified or ignored. For example, we don't need to call slotCenter() on recentering
|
|
//commands, just setDestination(). (sltoCenter() does additional things that we dont need).
|
|
bool KStarsData::executeScript( const TQString &scriptname, SkyMap *map ) {
|
|
int cmdCount(0);
|
|
|
|
TQFile f( scriptname );
|
|
if ( !f.open( IO_ReadOnly) ) {
|
|
kdDebug() << i18n( "Could not open file %1" ).arg( f.name() ) << endl;
|
|
return false;
|
|
}
|
|
|
|
TQTextStream istream(&f);
|
|
while ( ! istream.eof() ) {
|
|
TQString line = istream.readLine();
|
|
|
|
//found a dcop line
|
|
if ( line.left(4) == "dcop" ) {
|
|
line = line.mid( 20 ); //strip away leading characters
|
|
TQStringList fn = TQStringList::split( " ", line );
|
|
|
|
if ( fn[0] == "lookTowards" && fn.count() >= 2 ) {
|
|
double az(-1.0);
|
|
TQString arg = fn[1].lower();
|
|
if ( arg == "n" || arg == "north" ) az = 0.0;
|
|
if ( arg == "ne" || arg == "northeast" ) az = 45.0;
|
|
if ( arg == "e" || arg == "east" ) az = 90.0;
|
|
if ( arg == "se" || arg == "southeast" ) az = 135.0;
|
|
if ( arg == "s" || arg == "south" ) az = 180.0;
|
|
if ( arg == "sw" || arg == "southwest" ) az = 225.0;
|
|
if ( arg == "w" || arg == "west" ) az = 270.0;
|
|
if ( arg == "nw" || arg == "northwest" ) az = 335.0;
|
|
if ( az >= 0.0 ) {
|
|
map->setFocusAltAz( 15.0, az );
|
|
cmdCount++;
|
|
map->setDestination( map->focus() );
|
|
}
|
|
|
|
if ( arg == "z" || arg == "zenith" ) {
|
|
map->setFocusAltAz( 90.0, map->focus()->az()->Degrees() );
|
|
cmdCount++;
|
|
map->setDestination( map->focus() );
|
|
}
|
|
|
|
//try a named object. name is everything after the first word (which is 'lookTowards')
|
|
fn.remove( fn.first() );
|
|
SkyObject *target = objectNamed( fn.join( " " ) );
|
|
if ( target ) { map->setFocus( target ); cmdCount++; }
|
|
|
|
} else if ( fn[0] == "setRaDec" && fn.count() == 3 ) {
|
|
bool ok( false );
|
|
dms r(0.0), d(0.0);
|
|
|
|
ok = r.setFromString( fn[1], false ); //assume angle in hours
|
|
if ( ok ) ok = d.setFromString( fn[2], true ); //assume angle in degrees
|
|
if ( ok ) {
|
|
map->setFocus( r, d );
|
|
cmdCount++;
|
|
}
|
|
|
|
} else if ( fn[0] == "setAltAz" && fn.count() == 3 ) {
|
|
bool ok( false );
|
|
dms az(0.0), alt(0.0);
|
|
|
|
ok = alt.setFromString( fn[1] );
|
|
if ( ok ) ok = az.setFromString( fn[2] );
|
|
if ( ok ) {
|
|
map->setFocusAltAz( alt, az );
|
|
cmdCount++;
|
|
}
|
|
|
|
} else if ( fn[0] == "zoom" && fn.count() == 2 ) {
|
|
bool ok(false);
|
|
double z = fn[1].toDouble(&ok);
|
|
if ( ok ) {
|
|
if ( z > MAXZOOM ) z = MAXZOOM;
|
|
if ( z < MINZOOM ) z = MINZOOM;
|
|
Options::setZoomFactor( z );
|
|
cmdCount++;
|
|
}
|
|
|
|
} else if ( fn[0] == "zoomIn" ) {
|
|
if ( Options::zoomFactor() < MAXZOOM ) {
|
|
Options::setZoomFactor( Options::zoomFactor() * DZOOM );
|
|
cmdCount++;
|
|
}
|
|
} else if ( fn[0] == "zoomOut" ) {
|
|
if ( Options::zoomFactor() > MINZOOM ) {
|
|
Options::setZoomFactor( Options::zoomFactor() / DZOOM );
|
|
cmdCount++;
|
|
}
|
|
} else if ( fn[0] == "defaultZoom" ) {
|
|
Options::setZoomFactor( DEFAULTZOOM );
|
|
cmdCount++;
|
|
} else if ( fn[0] == "setLocalTime" && fn.count() == 7 ) {
|
|
bool ok(false);
|
|
int yr(0), mth(0), day(0) ,hr(0), min(0), sec(0);
|
|
yr = fn[1].toInt(&ok);
|
|
if ( ok ) mth = fn[2].toInt(&ok);
|
|
if ( ok ) day = fn[3].toInt(&ok);
|
|
if ( ok ) hr = fn[4].toInt(&ok);
|
|
if ( ok ) min = fn[5].toInt(&ok);
|
|
if ( ok ) sec = fn[6].toInt(&ok);
|
|
if ( ok ) {
|
|
changeDateTime( geo()->LTtoUT( KStarsDateTime( ExtDate(yr, mth, day), TQTime(hr,min,sec) ) ) );
|
|
cmdCount++;
|
|
} else {
|
|
kdWarning() << i18n( "Could not set time: %1 / %2 / %3 ; %4:%5:%6" )
|
|
.arg(day).arg(mth).arg(yr).arg(hr).arg(min).arg(sec) << endl;
|
|
}
|
|
} else if ( fn[0] == "changeViewOption" && fn.count() == 3 ) {
|
|
bool bOk(false), nOk(false), dOk(false);
|
|
|
|
//parse bool value
|
|
bool bVal(false);
|
|
if ( fn[2].lower() == "true" ) { bOk = true; bVal = true; }
|
|
if ( fn[2].lower() == "false" ) { bOk = true; bVal = false; }
|
|
if ( fn[2] == "1" ) { bOk = true; bVal = true; }
|
|
if ( fn[2] == "0" ) { bOk = true; bVal = false; }
|
|
|
|
//parse int value
|
|
int nVal = fn[2].toInt( &nOk );
|
|
|
|
//parse double value
|
|
double dVal = fn[2].toDouble( &dOk );
|
|
|
|
if ( fn[1] == "FOVName" ) { Options::setFOVName( fn[2] ); cmdCount++; }
|
|
if ( fn[1] == "FOVSize" && dOk ) { Options::setFOVSize( (float)dVal ); cmdCount++; }
|
|
if ( fn[1] == "FOVShape" && nOk ) { Options::setFOVShape( nVal ); cmdCount++; }
|
|
if ( fn[1] == "FOVColor" ) { Options::setFOVColor( fn[2] ); cmdCount++; }
|
|
if ( fn[1] == "ShowStars" && bOk ) { Options::setShowStars( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowMessier" && bOk ) { Options::setShowMessier( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowMessierImages" && bOk ) { Options::setShowMessierImages( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowCLines" && bOk ) { Options::setShowCLines( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowCNames" && bOk ) { Options::setShowCNames( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowNGC" && bOk ) { Options::setShowNGC( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowIC" && bOk ) { Options::setShowIC( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowMilkyWay" && bOk ) { Options::setShowMilkyWay( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowGrid" && bOk ) { Options::setShowGrid( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowEquator" && bOk ) { Options::setShowEquator( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowEcliptic" && bOk ) { Options::setShowEcliptic( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowHorizon" && bOk ) { Options::setShowHorizon( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowGround" && bOk ) { Options::setShowGround( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowSun" && bOk ) { Options::setShowSun( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowMoon" && bOk ) { Options::setShowMoon( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowMercury" && bOk ) { Options::setShowMercury( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowVenus" && bOk ) { Options::setShowVenus( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowMars" && bOk ) { Options::setShowMars( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowJupiter" && bOk ) { Options::setShowJupiter( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowSaturn" && bOk ) { Options::setShowSaturn( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowUranus" && bOk ) { Options::setShowUranus( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowNeptune" && bOk ) { Options::setShowNeptune( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowPluto" && bOk ) { Options::setShowPluto( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowAsteroids" && bOk ) { Options::setShowAsteroids( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowComets" && bOk ) { Options::setShowComets( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowPlanets" && bOk ) { Options::setShowPlanets( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowDeepSky" && bOk ) { Options::setShowDeepSky( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowStarNames" && bOk ) { Options::setShowStarNames( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowStarMagnitudes" && bOk ) { Options::setShowStarMagnitudes( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowAsteroidNames" && bOk ) { Options::setShowAsteroidNames( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowCometNames" && bOk ) { Options::setShowCometNames( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowPlanetNames" && bOk ) { Options::setShowPlanetNames( bVal ); cmdCount++; }
|
|
if ( fn[1] == "ShowPlanetImages" && bOk ) { Options::setShowPlanetImages( bVal ); cmdCount++; }
|
|
|
|
if ( fn[1] == "UseAltAz" && bOk ) { Options::setUseAltAz( bVal ); cmdCount++; }
|
|
if ( fn[1] == "UseRefraction" && bOk ) { Options::setUseRefraction( bVal ); cmdCount++; }
|
|
if ( fn[1] == "UseAutoLabel" && bOk ) { Options::setUseAutoLabel( bVal ); cmdCount++; }
|
|
if ( fn[1] == "UseAutoTrail" && bOk ) { Options::setUseAutoTrail( bVal ); cmdCount++; }
|
|
if ( fn[1] == "UseAnimatedSlewing" && bOk ) { Options::setUseAnimatedSlewing( bVal ); cmdCount++; }
|
|
if ( fn[1] == "FadePlanetTrails" && bOk ) { Options::setFadePlanetTrails( bVal ); cmdCount++; }
|
|
if ( fn[1] == "SlewTimeScale" && dOk ) { Options::setSlewTimeScale( dVal ); cmdCount++; }
|
|
if ( fn[1] == "ZoomFactor" && dOk ) { Options::setZoomFactor( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MagLimitDrawStar" && dOk ) { Options::setMagLimitDrawStar( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MagLimitDrawStarZoomOut" && dOk ) { Options::setMagLimitDrawStarZoomOut( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MagLimitDrawDeepSky" && dOk ) { Options::setMagLimitDrawDeepSky( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MagLimitDrawDeepSkyZoomOut" && dOk ) { Options::setMagLimitDrawDeepSkyZoomOut( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MagLimitDrawStarInfo" && dOk ) { Options::setMagLimitDrawStarInfo( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MagLimitHideStar" && dOk ) { Options::setMagLimitHideStar( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MagLimitAsteroid" && dOk ) { Options::setMagLimitAsteroid( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MagLimitAsteroidName" && dOk ) { Options::setMagLimitAsteroidName( dVal ); cmdCount++; }
|
|
if ( fn[1] == "MaxRadCometName" && dOk ) { Options::setMaxRadCometName( dVal ); cmdCount++; }
|
|
|
|
//these three are a "radio group"
|
|
if ( fn[1] == "UseLatinConstellationNames" && bOk ) {
|
|
Options::setUseLatinConstellNames( true );
|
|
Options::setUseLocalConstellNames( false );
|
|
Options::setUseAbbrevConstellNames( false );
|
|
cmdCount++;
|
|
}
|
|
if ( fn[1] == "UseLocalConstellationNames" && bOk ) {
|
|
Options::setUseLatinConstellNames( false );
|
|
Options::setUseLocalConstellNames( true );
|
|
Options::setUseAbbrevConstellNames( false );
|
|
cmdCount++;
|
|
}
|
|
if ( fn[1] == "UseAbbrevConstellationNames" && bOk ) {
|
|
Options::setUseLatinConstellNames( false );
|
|
Options::setUseLocalConstellNames( false );
|
|
Options::setUseAbbrevConstellNames( true );
|
|
cmdCount++;
|
|
}
|
|
} else if ( fn[0] == "setGeoLocation" && ( fn.count() == 3 || fn.count() == 4 ) ) {
|
|
TQString city( fn[1] ), province( "" ), country( fn[2] );
|
|
if ( fn.count() == 4 ) {
|
|
province = fn[2];
|
|
country = fn[3];
|
|
}
|
|
|
|
bool cityFound( false );
|
|
for (GeoLocation *loc = geoList.first(); loc; loc = geoList.next()) {
|
|
if ( loc->translatedName() == city &&
|
|
( province.isEmpty() || loc->translatedProvince() == province ) &&
|
|
loc->translatedCountry() == country ) {
|
|
|
|
cityFound = true;
|
|
setLocation( *loc );
|
|
cmdCount++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !cityFound )
|
|
kdWarning() << i18n( "Could not set location named %1, %2, %3" ).arg(city).arg(province).arg(country) << endl;
|
|
}
|
|
}
|
|
} //end while
|
|
|
|
if ( cmdCount ) return true;
|
|
return false;
|
|
}
|
|
|
|
void KStarsData::appendTelescopeObject(SkyObject * object)
|
|
{
|
|
INDITelescopeList.append(object);
|
|
}
|
|
|
|
void KStarsData::saveTimeBoxShaded( bool b ) { Options::setShadeTimeBox( b ); }
|
|
void KStarsData::saveGeoBoxShaded( bool b ) { Options::setShadeGeoBox( b ); }
|
|
void KStarsData::saveFocusBoxShaded( bool b ) { Options::setShadeFocusBox( b ); }
|
|
void KStarsData::saveTimeBoxPos( TQPoint p ) { Options::setPositionTimeBox( p ); }
|
|
void KStarsData::saveGeoBoxPos( TQPoint p ) { Options::setPositionGeoBox( p ); }
|
|
void KStarsData::saveFocusBoxPos( TQPoint p ) { Options::setPositionFocusBox( p ); }
|
|
|
|
#include "kstarsdata.moc"
|