00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <qregexp.h>
00019 #include <qdir.h>
00020 #include <qfile.h>
00021
00022 #include <kapplication.h>
00023 #include <kmessagebox.h>
00024 #include <kdebug.h>
00025 #include <klocale.h>
00026 #include <kstandarddirs.h>
00027
00028 #include "kstarsdata.h"
00029
00030 #include "Options.h"
00031 #include "dms.h"
00032 #include "skymap.h"
00033 #include "ksutils.h"
00034 #include "ksnumbers.h"
00035 #include "skypoint.h"
00036 #include "skyobject.h"
00037 #include "starobject.h"
00038 #include "deepskyobject.h"
00039 #include "skyobjectname.h"
00040 #include "ksplanet.h"
00041 #include "ksasteroid.h"
00042 #include "kscomet.h"
00043 #include "ksmoon.h"
00044 #include "jupitermoons.h"
00045
00046 #include "simclock.h"
00047 #include "timezonerule.h"
00048 #include "filesource.h"
00049 #include "stardatasink.h"
00050 #include "ksfilereader.h"
00051 #include "indidriver.h"
00052 #include "indi/lilxml.h"
00053 #include "indistd.h"
00054 #include "detaildialog.h"
00055 #include "csegment.h"
00056 #include "customcatalog.h"
00057
00058 QPtrList<GeoLocation> KStarsData::geoList = QPtrList<GeoLocation>();
00059 QMap<QString, TimeZoneRule> KStarsData::Rulebook = QMap<QString, TimeZoneRule>();
00060 QStringList KStarsData::CustomColumns = QStringList::split( " ", "ID RA Dc Tp Nm Mg Mj Mn PA Ig" );
00061 int KStarsData::objects = 0;
00062
00063 KStarsData::KStarsData() : stdDirs(0), locale(0),
00064 LST(0), HourAngle(0),
00065 PCat(0), Moon(0), jmoons(0),
00066 starFileReader(0), initTimer(0),
00067 source(0), loader(0), pump(0)
00068 {
00069 startupComplete = false;
00070 objects++;
00071
00072
00073 stdDirs = new KStandardDirs();
00074 locale = new KLocale( "kstars" );
00075
00076
00077
00078 QString fname = locateLocal( "config", "kstarsrc" );
00079 useDefaultOptions = ! ( QFile(fname).exists() );
00080
00081
00082 LST = new dms();
00083 HourAngle = new dms();
00084
00085
00086 PCat = new PlanetCatalog(this);
00087
00088
00089 fovSymbol = FOV();
00090
00091
00092
00093 starList.setAutoDelete( TRUE );
00094 ADVtreeList.setAutoDelete( TRUE );
00095 geoList.setAutoDelete( TRUE );
00096 deepSkyList.setAutoDelete( TRUE );
00097
00098
00099
00100 deepSkyListMessier.setAutoDelete( FALSE );
00101 deepSkyListNGC.setAutoDelete( FALSE );
00102 deepSkyListIC.setAutoDelete( FALSE );
00103 deepSkyListOther.setAutoDelete( FALSE );
00104
00105
00106 ObjLabelList.setAutoDelete( FALSE );
00107
00108 cometList.setAutoDelete( TRUE );
00109 asteroidList.setAutoDelete( TRUE );
00110
00111
00112
00113 clineList.setAutoDelete( FALSE );
00114 clineModeList.setAutoDelete( TRUE );
00115 cnameList.setAutoDelete( TRUE );
00116 csegmentList.setAutoDelete( TRUE );
00117
00118 Equator.setAutoDelete( TRUE );
00119 Ecliptic.setAutoDelete( TRUE );
00120 Horizon.setAutoDelete( TRUE );
00121 for ( unsigned int i=0; i<11; ++i ) MilkyWay[i].setAutoDelete( TRUE );
00122
00123 VariableStarsList.setAutoDelete(TRUE);
00124 INDIHostsList.setAutoDelete(TRUE);
00125 INDITelescopeList.setAutoDelete(TRUE);
00126
00127
00128 TypeName[0] = i18n( "star" );
00129 TypeName[1] = i18n( "multiple star" );
00130 TypeName[2] = i18n( "planet" );
00131 TypeName[3] = i18n( "open cluster" );
00132 TypeName[4] = i18n( "globular cluster" );
00133 TypeName[5] = i18n( "gaseous nebula" );
00134 TypeName[6] = i18n( "planetary nebula" );
00135 TypeName[7] = i18n( "supernova remnant" );
00136 TypeName[8] = i18n( "galaxy" );
00137 TypeName[9] = i18n( "comet" );
00138 TypeName[10] = i18n( "asteroid" );
00139 TypeName[11] = i18n( "constellation" );
00140
00141
00142 setTimeDirection( 0.0 );
00143
00144
00145 StoredDate.setDJD( (long double)INVALID_DAY );
00146
00147 temporaryTrail = false;
00148 }
00149
00150 KStarsData::~KStarsData() {
00151 objects--;
00152 checkDataPumpAction();
00153
00154
00155
00156
00157 delete stdDirs;
00158 delete Moon;
00159 delete locale;
00160 delete PCat;
00161 delete jmoons;
00162 delete initTimer;
00163 }
00164
00165 bool KStarsData::readMWData( void ) {
00166 QFile file;
00167
00168 for ( unsigned int i=0; i<11; ++i ) {
00169 QString snum, fname, szero;
00170 snum = snum.setNum( i+1 );
00171 if ( i+1 < 10 ) szero = "0"; else szero = "";
00172 fname = "mw" + szero + snum + ".dat";
00173
00174 if ( KSUtils::openDataFile( file, fname ) ) {
00175 KSFileReader fileReader( file );
00176 while ( fileReader.hasMoreLines() ) {
00177 QString line;
00178 double ra, dec;
00179
00180 line = fileReader.readLine();
00181
00182 ra = line.mid( 0, 8 ).toDouble();
00183 dec = line.mid( 9, 8 ).toDouble();
00184
00185 SkyPoint *o = new SkyPoint( ra, dec );
00186 MilkyWay[i].append( o );
00187 }
00188 } else {
00189 return false;
00190 }
00191 }
00192 return true;
00193 }
00194
00195 bool KStarsData::readADVTreeData(void)
00196 {
00197
00198 QFile file;
00199 QString Interface;
00200
00201 if (!KSUtils::openDataFile(file, "advinterface.dat"))
00202 return false;
00203
00204 QTextStream stream(&file);
00205 QString Line;
00206
00207 while (!stream.atEnd())
00208 {
00209 QString Name, Link, subName;
00210 int Type, interfaceIndex;
00211
00212 Line = stream.readLine();
00213
00214 if (Line.startsWith("[KSLABEL]"))
00215 {
00216 Name = Line.mid(9);
00217 Type = 0;
00218 }
00219 else if (Line.startsWith("[END]"))
00220 Type = 1;
00221 else if (Line.startsWith("[KSINTERFACE]"))
00222 {
00223 Interface = Line.mid(13);
00224 continue;
00225 }
00226
00227 else
00228 {
00229 Name = Line.mid(0, Line.find(":"));
00230 Link = Line.mid(Line.find(":") + 1);
00231
00232
00233 if (Link.isEmpty())
00234 {
00235 Link = Interface;
00236 subName = Name;
00237 interfaceIndex = Link.find("KSINTERFACE");
00238 Link.remove(interfaceIndex, 11);
00239 Link = Link.insert(interfaceIndex, subName.replace( QRegExp(" "), "+"));
00240
00241 }
00242
00243 Type = 2;
00244 }
00245
00246 ADVTreeData *ADVData = new ADVTreeData;
00247
00248 ADVData->Name = Name;
00249 ADVData->Link = Link;
00250 ADVData->Type = Type;
00251
00252 ADVtreeList.append(ADVData);
00253 }
00254
00255 return true;
00256
00257
00258
00259 }
00260
00261 bool KStarsData::readVARData(void)
00262 {
00263 QString varFile("valaav.txt");
00264 QFile localeFile;
00265 QFile file;
00266
00267 file.setName( locateLocal( "appdata", varFile ) );
00268 if ( !file.open( IO_ReadOnly ) )
00269 {
00270
00271 if ( KSUtils::openDataFile( file, varFile ) )
00272 {
00273
00274 localeFile.setName( locateLocal( "appdata", varFile ) );
00275
00276 if (localeFile.open(IO_WriteOnly))
00277 {
00278 QTextStream readStream(&file);
00279 QTextStream writeStream(&localeFile);
00280 writeStream << readStream.read();
00281 localeFile.close();
00282 file.reset();
00283 }
00284 }
00285 else
00286 return false;
00287 }
00288
00289
00290 QTextStream stream(&file);
00291
00292 stream.readLine();
00293
00294 while (!stream.atEnd())
00295 {
00296 QString Name;
00297 QString Designation;
00298 QString Line;
00299
00300 Line = stream.readLine();
00301
00302 if (Line[0] == QChar('*'))
00303 break;
00304
00305 Designation = Line.mid(0,8).stripWhiteSpace();
00306 Name = Line.mid(10,20).simplifyWhiteSpace();
00307
00308 VariableStarInfo *VInfo = new VariableStarInfo;
00309
00310 VInfo->Designation = Designation;
00311 VInfo->Name = Name;
00312 VariableStarsList.append(VInfo);
00313 }
00314
00315 return true;
00316
00317 }
00318
00319
00320 bool KStarsData::readINDIHosts(void)
00321 {
00322 QString indiFile("indihosts.xml");
00323 QFile localeFile;
00324 QFile file;
00325 char errmsg[1024];
00326 signed char c;
00327 LilXML *xmlParser = newLilXML();
00328 XMLEle *root = NULL;
00329 XMLAtt *ap;
00330
00331 file.setName( locate( "appdata", indiFile ) );
00332 if ( file.name().isEmpty() || !file.open( IO_ReadOnly ) )
00333 return false;
00334
00335 while ( (c = (signed char) file.getch()) != -1)
00336 {
00337 root = readXMLEle(xmlParser, c, errmsg);
00338
00339 if (root)
00340 {
00341
00342
00343 ap = findXMLAtt(root, "name");
00344 if (!ap) {
00345 delLilXML(xmlParser);
00346 return false;
00347 }
00348
00349 INDIHostsInfo *VInfo = new INDIHostsInfo;
00350
00351 VInfo->name = QString(valuXMLAtt(ap));
00352
00353
00354 ap = findXMLAtt(root, "hostname");
00355
00356 if (!ap) {
00357 delLilXML(xmlParser);
00358 return false;
00359 }
00360
00361 VInfo->hostname = QString(valuXMLAtt(ap));
00362
00363 ap = findXMLAtt(root, "port");
00364
00365 if (!ap) {
00366 delLilXML(xmlParser);
00367 return false;
00368 }
00369
00370 VInfo->portnumber = QString(valuXMLAtt(ap));
00371
00372 VInfo->isConnected = false;
00373 VInfo->mgrID = -1;
00374
00375 INDIHostsList.append(VInfo);
00376
00377 delXMLEle(root);
00378 }
00379
00380 else if (errmsg[0])
00381 kdDebug() << errmsg << endl;
00382
00383 }
00384
00385 delLilXML(xmlParser);
00386
00387 return true;
00388
00389
00390 }
00391
00392 bool KStarsData::readCLineData( void ) {
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 QFile file;
00406 if ( KSUtils::openDataFile( file, "clines.dat" ) ) {
00407 QTextStream stream( &file );
00408
00409 while ( !stream.eof() ) {
00410 QString line, name;
00411 QChar *mode;
00412
00413 line = stream.readLine();
00414
00415
00416 if ( line.at( 0 ) != '#' ) {
00417 name = line.mid( 2 ).stripWhiteSpace();
00418
00419
00420
00421
00422 bool starFound( false );
00423 for ( SkyObjectName *oname = ObjNames.first(); oname; oname = ObjNames.next() ) {
00424 if ( oname->skyObject()->type() == SkyObject::STAR &&
00425 oname->skyObject()->name2() == name ) {
00426 starFound = true;
00427 clineList.append( (SkyPoint *)( oname->skyObject() ) );
00428
00429 mode = new QChar( line.at( 0 ) );
00430 clineModeList.append( mode );
00431 break;
00432 }
00433 }
00434
00435 if ( ! starFound )
00436 kdWarning() << i18n( "No star named %1 found." ).arg(name) << endl;
00437 }
00438 }
00439 file.close();
00440
00441 return true;
00442 } else {
00443 return false;
00444 }
00445 }
00446
00447 bool KStarsData::readCNameData( void ) {
00448 QFile file;
00449 cnameFile = "cnames.dat";
00450
00451 if ( KSUtils::openDataFile( file, cnameFile ) ) {
00452 QTextStream stream( &file );
00453
00454 while ( !stream.eof() ) {
00455 QString line, name, abbrev;
00456 int rah, ram, ras, dd, dm, ds;
00457 QChar sgn;
00458
00459 line = stream.readLine();
00460
00461 rah = line.mid( 0, 2 ).toInt();
00462 ram = line.mid( 2, 2 ).toInt();
00463 ras = line.mid( 4, 2 ).toInt();
00464
00465 sgn = line.at( 6 );
00466 dd = line.mid( 7, 2 ).toInt();
00467 dm = line.mid( 9, 2 ).toInt();
00468 ds = line.mid( 11, 2 ).toInt();
00469
00470 abbrev = line.mid( 13, 3 );
00471 name = line.mid( 17 ).stripWhiteSpace();
00472
00473 dms r; r.setH( rah, ram, ras );
00474 dms d( dd, dm, ds );
00475
00476 if ( sgn == "-" ) { d.setD( -1.0*d.Degrees() ); }
00477
00478 SkyObject *o = new SkyObject( SkyObject::CONSTELLATION, r, d, 0.0, name, abbrev );
00479 cnameList.append( o );
00480 ObjNames.append( o );
00481 }
00482 file.close();
00483
00484 return true;
00485 } else {
00486 return false;
00487 }
00488 }
00489
00490 bool KStarsData::readCBoundData( void ) {
00491 QFile file;
00492
00493 if ( KSUtils::openDataFile( file, "cbound.dat" ) ) {
00494 QTextStream stream( &file );
00495
00496 unsigned int nn(0);
00497 double ra(0.0), dec(0.0);
00498 QString d1, d2;
00499 bool ok(false), comment(false);
00500
00501
00502
00503
00504
00505 while ( !stream.eof() ) {
00506 stream >> d1;
00507 if ( d1.at(0) == '#' ) {
00508 comment = true;
00509 ok = true;
00510 } else {
00511 comment = false;
00512 nn = d1.toInt( &ok );
00513 }
00514
00515 if ( !ok || comment ) {
00516 d1 = stream.readLine();
00517
00518 if ( !ok )
00519 kdWarning() << i18n( "Unable to parse boundary segment." ) << endl;
00520
00521 } else {
00522 CSegment *seg = new CSegment();
00523
00524 for ( unsigned int i=0; i<nn; ++i ) {
00525 stream >> d1 >> d2;
00526 ra = d1.toDouble( &ok );
00527 if ( ok ) dec = d2.toDouble( &ok );
00528 if ( !ok ) break;
00529
00530 seg->addPoint( ra, dec );
00531 }
00532
00533 if ( !ok ) {
00534
00535 kdWarning() << i18n( "Unable to parse boundary segment." ) << endl;
00536 delete seg;
00537 d1 = stream.readLine();
00538
00539 } else {
00540 stream >> d1;
00541
00542 nn = d1.toInt( &ok );
00543
00544 if ( !ok || nn != 2 ) {
00545 kdWarning() << i18n( "Bad Constellation Boundary data." ) << endl;
00546 delete seg;
00547 d1 = stream.readLine();
00548 }
00549 }
00550
00551 if ( ok ) {
00552 stream >> d1 >> d2;
00553 ok = seg->setNames( d1, d2 );
00554 if ( ok ) csegmentList.append( seg );
00555 }
00556 }
00557 }
00558
00559 return true;
00560 } else {
00561 return false;
00562 }
00563 }
00564
00565 bool KStarsData::openStarFile( int i ) {
00566 if (starFileReader != 0) delete starFileReader;
00567 QFile file;
00568 QString snum, fname;
00569 snum = QString().sprintf("%03d", i);
00570 fname = "hip" + snum + ".dat";
00571 if (KSUtils::openDataFile(file, fname)) {
00572 starFileReader = new KSFileReader(file);
00573 } else {
00574 starFileReader = 0;
00575 return false;
00576 }
00577 return true;
00578 }
00579
00580 bool KStarsData::readStarData( void ) {
00581 bool ready = false;
00582
00583 float loadUntilMag = MINDRAWSTARMAG;
00584 if (Options::magLimitDrawStar() > loadUntilMag) loadUntilMag = Options::magLimitDrawStar();
00585
00586 for (unsigned int i=1; i<NHIPFILES+1; ++i) {
00587 emit progressText( i18n( "Loading Star Data (%1%)" ).arg( int(100.*float(i)/float(NHIPFILES)) ) );
00588
00589 if (openStarFile(i) == true) {
00590 while (starFileReader->hasMoreLines()) {
00591 QString line;
00592 float mag;
00593
00594 line = starFileReader->readLine();
00595 if ( line.left(1) != "#" ) {
00596
00597 mag = line.mid( 46,5 ).toFloat();
00598 if ( mag > loadUntilMag ) {
00599 ready = true;
00600 break;
00601 }
00602
00603 processStar(&line);
00604 }
00605 }
00606
00607 } else {
00608 if ( starList.count() ) return true;
00609 else return false;
00610 }
00611
00612 if (ready == true) break;
00613 }
00614
00615
00616 maxSetMagnitude = Options::magLimitDrawStar();
00617 delete starFileReader;
00618 starFileReader = 0;
00619 return true;
00620 }
00621
00622 void KStarsData::processStar( QString *line, bool reloadMode ) {
00623 QString name, gname, SpType;
00624 int rah, ram, ras, ras2, dd, dm, ds, ds2;
00625 bool mult, var;
00626 QChar sgn;
00627 double mag, bv, dmag, vper;
00628 double pmra, pmdec, plx;
00629
00630 name = ""; gname = "";
00631
00632
00633 rah = line->mid( 0, 2 ).toInt();
00634 ram = line->mid( 2, 2 ).toInt();
00635 ras = int(line->mid( 4, 5 ).toDouble());
00636 ras2 = int(60.0*(line->mid( 4, 5 ).toDouble()-ras) + 0.5);
00637
00638 sgn = line->at(10);
00639 dd = line->mid(11, 2).toInt();
00640 dm = line->mid(13, 2).toInt();
00641 ds = int(line->mid(15, 4).toDouble());
00642 ds2 = int(60.0*(line->mid( 15, 5 ).toDouble()-ds) + 0.5);
00643
00644
00645 pmra = line->mid( 20, 9 ).toDouble();
00646 pmdec = line->mid( 29, 9 ).toDouble();
00647 plx = line->mid( 38, 7 ).toDouble();
00648
00649
00650 mag = line->mid( 46, 5 ).toDouble();
00651 bv = line->mid( 51, 5 ).toDouble();
00652 SpType = line->mid(56, 2);
00653
00654
00655 mult = line->mid( 59, 1 ).toInt();
00656
00657
00658 var = false; dmag = 0.0; vper = 0.0;
00659 if ( line->at( 62 ) == '.' ) {
00660 var = true;
00661 dmag = line->mid( 61, 4 ).toDouble();
00662 vper = line->mid( 66, 6 ).toDouble();
00663 }
00664
00665
00666 name = line->mid( 72 ).stripWhiteSpace();
00667 if (name.contains( ':' )) {
00668 gname = name.mid( name.find(':')+1 ).stripWhiteSpace();
00669 name = name.mid( 0, name.find(':') ).stripWhiteSpace();
00670 }
00671
00672
00673 name = i18n("star name", name.local8Bit().data());
00674
00675 bool starIsUnnamed( false );
00676 if (name.isEmpty() && gname.isEmpty()) {
00677 starIsUnnamed = true;
00678 }
00679
00680 dms r;
00681 r.setH(rah, ram, ras, ras2);
00682 dms d(dd, dm, ds, ds2);
00683
00684 if (sgn == "-") { d.setD( -1.0*d.Degrees() ); }
00685
00686 StarObject *o = new StarObject(r, d, mag, name, gname, SpType, pmra, pmdec, plx, mult, var );
00687 starList.append(o);
00688
00689
00690
00691 if (reloadMode) {
00692 o->EquatorialToHorizontal( LST, geo()->lat() );
00693 }
00694
00695
00696
00697
00698
00699
00700 if (starIsUnnamed == false) {
00701 ObjNames.append(o);
00702 }
00703 }
00704
00705 bool KStarsData::readAsteroidData( void ) {
00706 QFile file;
00707
00708 if ( KSUtils::openDataFile( file, "asteroids.dat" ) ) {
00709 KSFileReader fileReader( file );
00710
00711 while( fileReader.hasMoreLines() ) {
00712 QString line, name;
00713 int mJD;
00714 double a, e, dble_i, dble_w, dble_N, dble_M, H;
00715 long double JD;
00716 KSAsteroid *ast = 0;
00717
00718 line = fileReader.readLine();
00719 name = line.mid( 6, 17 ).stripWhiteSpace();
00720 mJD = line.mid( 24, 5 ).toInt();
00721 a = line.mid( 30, 9 ).toDouble();
00722 e = line.mid( 41, 10 ).toDouble();
00723 dble_i = line.mid( 52, 9 ).toDouble();
00724 dble_w = line.mid( 62, 9 ).toDouble();
00725 dble_N = line.mid( 72, 9 ).toDouble();
00726 dble_M = line.mid( 82, 11 ).toDouble();
00727 H = line.mid( 94, 5 ).toDouble();
00728
00729 JD = double( mJD ) + 2400000.5;
00730
00731 ast = new KSAsteroid( this, name, "", JD, a, e, dms(dble_i), dms(dble_w), dms(dble_N), dms(dble_M), H );
00732 ast->setAngularSize( 0.005 );
00733 asteroidList.append( ast );
00734 ObjNames.append( ast );
00735 }
00736
00737 if ( asteroidList.count() ) return true;
00738 }
00739
00740 return false;
00741 }
00742
00743 bool KStarsData::readCometData( void ) {
00744 QFile file;
00745
00746 if ( KSUtils::openDataFile( file, "comets.dat" ) ) {
00747 KSFileReader fileReader( file );
00748
00749 while( fileReader.hasMoreLines() ) {
00750 QString line, name;
00751 int mJD;
00752 double q, e, dble_i, dble_w, dble_N, Tp;
00753 long double JD;
00754 KSComet *com = 0;
00755
00756 line = fileReader.readLine();
00757 name = line.mid( 3, 35 ).stripWhiteSpace();
00758 mJD = line.mid( 38, 5 ).toInt();
00759 q = line.mid( 44, 10 ).toDouble();
00760 e = line.mid( 55, 10 ).toDouble();
00761 dble_i = line.mid( 66, 9 ).toDouble();
00762 dble_w = line.mid( 76, 9 ).toDouble();
00763 dble_N = line.mid( 86, 9 ).toDouble();
00764 Tp = line.mid( 96, 14 ).toDouble();
00765
00766 JD = double( mJD ) + 2400000.5;
00767
00768 com = new KSComet( this, name, "", JD, q, e, dms(dble_i), dms(dble_w), dms(dble_N), Tp );
00769 com->setAngularSize( 0.005 );
00770
00771 cometList.append( com );
00772 ObjNames.append( com );
00773 }
00774
00775 if ( cometList.count() ) return true;
00776 }
00777
00778 return false;
00779 }
00780
00781
00782
00783 bool KStarsData::readDeepSkyData( void ) {
00784 QFile file;
00785
00786 for ( unsigned int i=0; i<NNGCFILES; ++i ) {
00787 QString snum, fname;
00788 snum = QString().sprintf( "%02d", i+1 );
00789 fname = "ngcic" + snum + ".dat";
00790
00791 emit progressText( i18n( "Loading NGC/IC Data (%1%)" ).arg( int(100.*float(i)/float(NNGCFILES)) ) );
00792
00793 if ( KSUtils::openDataFile( file, fname ) ) {
00794 KSFileReader fileReader( file );
00795 while ( fileReader.hasMoreLines() ) {
00796 QString line, con, ss, name, name2, longname;
00797 QString cat, cat2;
00798 float mag(1000.0), ras, a, b;
00799 int type, ingc, imess(-1), rah, ram, dd, dm, ds, pa;
00800 int pgc, ugc;
00801 QChar sgn, iflag;
00802
00803 line = fileReader.readLine();
00804
00805 while ( line.at(0) == '#' && fileReader.hasMoreLines() ) line = fileReader.readLine();
00806
00807 while ( line.mid(6,8).stripWhiteSpace().isEmpty() ) line = fileReader.readLine();
00808
00809 iflag = line.at( 0 );
00810 if ( iflag == 'I' ) cat = "IC";
00811 else if ( iflag == 'N' ) cat = "NGC";
00812
00813 ingc = line.mid( 1, 4 ).toInt();
00814 if ( ingc==0 ) cat = "";
00815
00816
00817 rah = line.mid( 6, 2 ).toInt();
00818 ram = line.mid( 8, 2 ).toInt();
00819 ras = line.mid( 10, 4 ).toFloat();
00820 sgn = line.at( 15 );
00821 dd = line.mid( 16, 2 ).toInt();
00822 dm = line.mid( 18, 2 ).toInt();
00823 ds = line.mid( 20, 2 ).toInt();
00824
00825
00826 ss = line.mid( 23, 4 );
00827 if (ss == " " ) { mag = 99.9; } else { mag = ss.toFloat(); }
00828
00829
00830 type = line.mid( 29, 1 ).toInt();
00831
00832
00833 ss = line.mid( 31, 5 );
00834 if (ss == " " ) { a = 0.0; } else { a = ss.toFloat(); }
00835 ss = line.mid( 37, 5 );
00836 if (ss == " " ) { b = 0.0; } else { b = ss.toFloat(); }
00837
00838
00839
00840 ss = line.mid( 43, 3 );
00841 if (ss == " " ) { pa = 90; } else { pa = 90 - ss.toInt(); }
00842
00843
00844 ss = line.mid( 47, 6 );
00845 if (ss == " " ) { pgc = 0; } else { pgc = ss.toInt(); }
00846
00847
00848 if ( line.mid( 54, 3 ) == "UGC" ) {
00849 ugc = line.mid( 58, 5 ).toInt();
00850 } else {
00851 ugc = 0;
00852 }
00853
00854
00855 if ( line.at( 70 ) == 'M' ) {
00856 cat2 = cat;
00857 if ( ingc==0 ) cat2 = "";
00858 cat = "M";
00859 imess = line.mid( 72, 3 ).toInt();
00860 }
00861
00862 longname = line.mid( 76, line.length() ).stripWhiteSpace();
00863
00864 dms r;
00865 r.setH( rah, ram, int(ras) );
00866 dms d( dd, dm, ds );
00867
00868 if ( sgn == "-" ) { d.setD( -1.0*d.Degrees() ); }
00869
00870
00871 if ( cat=="IC" || cat=="NGC" ) {
00872 snum.setNum( ingc );
00873 name = cat + " " + snum;
00874 } else if ( cat=="M" ) {
00875 snum.setNum( imess );
00876 name = cat + " " + snum;
00877 if ( cat2=="NGC" ) {
00878 snum.setNum( ingc );
00879 name2 = cat2 + " " + snum;
00880 } else if ( cat2=="IC" ) {
00881 snum.setNum( ingc );
00882 name2 = cat2 + " " + snum;
00883 } else {
00884 name2 = "";
00885 }
00886 } else {
00887 if ( longname.isEmpty() ) name = i18n( "Unnamed Object" );
00888 else name = longname;
00889 }
00890
00891
00892 DeepSkyObject *o = 0;
00893 if ( type==0 ) type = 1;
00894 o = new DeepSkyObject( type, r, d, mag, name, name2, longname, cat, a, b, pa, pgc, ugc );
00895
00896
00897 deepSkyList.append( o );
00898
00899
00900 if ( o->isCatalogM()) {
00901 deepSkyListMessier.append( o );
00902 } else if (o->isCatalogNGC() ) {
00903 deepSkyListNGC.append( o );
00904 } else if ( o->isCatalogIC() ) {
00905 deepSkyListIC.append( o );
00906 } else {
00907 deepSkyListOther.append( o );
00908 }
00909
00910
00911 ObjNames.append( (SkyObject*)o );
00912
00913
00914 if ( !o->longname().isEmpty() && o->name() != o->longname() && o->hasName() ) {
00915 ObjNames.append( o, true );
00916 }
00917 }
00918 } else {
00919 return false;
00920 }
00921 }
00922
00923 return true;
00924 }
00925
00926 bool KStarsData::openURLFile(QString urlfile, QFile & file) {
00927
00928 QString localFile;
00929 bool fileFound = false;
00930 QFile localeFile;
00931
00932 if ( locale->language() != "en_US" )
00933 localFile = locale->language() + "/" + urlfile;
00934
00935 if ( ! localFile.isEmpty() && KSUtils::openDataFile( file, localFile ) ) {
00936 fileFound = true;
00937 } else {
00938
00939 file.setName( locateLocal( "appdata", urlfile ) );
00940 if ( file.open( IO_ReadOnly ) ) {
00941
00942
00943 bool newDataFound( false );
00944 QStringList urlData;
00945 QTextStream lStream( &file );
00946 while ( ! lStream.eof() ) urlData.append( lStream.readLine() );
00947
00948
00949 QFileInfo fi_local( file.name() );
00950 QStringList flist = KGlobal::instance()->dirs()->findAllResources( "appdata", urlfile );
00951 for ( unsigned int i=0; i< flist.count(); i++ ) {
00952 if ( flist[i] != file.name() ) {
00953 QFileInfo fi_global( flist[i] );
00954
00955
00956 if ( fi_global.lastModified() > fi_local.lastModified() ) {
00957
00958
00959
00960 QFile globalFile( flist[i] );
00961 if ( globalFile.open( IO_ReadOnly ) ) {
00962 QTextStream gStream( &globalFile );
00963 while ( ! gStream.eof() ) {
00964 QString line = gStream.readLine();
00965
00966
00967 if ( line.left( 4 ) == "XXX:" && urlData.contains( line.mid( 4 ) ) ) {
00968 urlData.remove( urlData.find( line.mid( 4 ) ) );
00969 } else {
00970
00971
00972 bool linefound( false );
00973 for ( unsigned int j=0; j< urlData.count(); ++j ) {
00974 if ( urlData[j].contains( line.left( line.find( ':', line.find( ':' ) + 1 ) ) ) ) {
00975
00976 urlData.remove( urlData.at(j) );
00977 urlData.insert( urlData.at(j), line );
00978 if ( !newDataFound ) newDataFound = true;
00979 linefound = true;
00980 break;
00981 }
00982 }
00983 if ( ! linefound ) {
00984 urlData.append( line );
00985 if ( !newDataFound ) newDataFound = true;
00986 }
00987 }
00988 }
00989 }
00990 }
00991 }
00992 }
00993
00994 file.close();
00995
00996
00997 if ( newDataFound ) {
00998 if ( file.open( IO_WriteOnly ) ) {
00999 QTextStream outStream( &file );
01000 for ( unsigned int i=0; i<urlData.count(); i++ ) {
01001 outStream << urlData[i] << endl;
01002 }
01003 file.close();
01004 }
01005 }
01006
01007 if ( file.open( IO_ReadOnly ) ) fileFound = true;
01008
01009 } else {
01010 if ( KSUtils::openDataFile( file, urlfile ) ) {
01011 if ( locale->language() != "en_US" ) kdDebug() << i18n( "No localized URL file; using default English file." ) << endl;
01012
01013 localeFile.setName( locateLocal( "appdata", urlfile ) );
01014 if (localeFile.open(IO_WriteOnly)) {
01015 QTextStream readStream(&file);
01016 QTextStream writeStream(&localeFile);
01017 while ( ! readStream.eof() ) {
01018 QString line = readStream.readLine();
01019 if ( line.left( 4 ) != "XXX:" )
01020 writeStream << line << endl;
01021 }
01022
01023 localeFile.close();
01024 file.reset();
01025 } else {
01026 kdDebug() << i18n( "Failed to copy default URL file to locale folder, modifying default object links is not possible" ) << endl;
01027 }
01028 fileFound = true;
01029 }
01030 }
01031 }
01032 return fileFound;
01033 }
01034
01035 bool KStarsData::readUserLog(void)
01036 {
01037 QFile file;
01038 QString buffer;
01039 QString sub, name, data;
01040
01041 if (!KSUtils::openDataFile( file, "userlog.dat" )) return false;
01042
01043 QTextStream stream(&file);
01044
01045 if (!stream.eof()) buffer = stream.read();
01046
01047 while (!buffer.isEmpty()) {
01048 int startIndex, endIndex;
01049
01050 startIndex = buffer.find("[KSLABEL:");
01051 sub = buffer.mid(startIndex);
01052 endIndex = sub.find("[KSLogEnd]");
01053
01054
01055 uint uiFirstNewline = sub.find("\n", startIndex + 9);
01056 name = sub.mid(startIndex + 9, sub.findRev( "]", uiFirstNewline ) - (startIndex + 9) );
01057
01058 data = sub.mid( uiFirstNewline + 1, endIndex - (uiFirstNewline + 1));
01059 buffer = buffer.mid(endIndex + 11);
01060
01061
01062
01063
01064 SkyObjectName *sonm = ObjNames.find(name);
01065 if (sonm == 0) {
01066 kdWarning() << k_funcinfo << name << " not found" << endl;
01067 } else {
01068 sonm->skyObject()->userLog = data;
01069 }
01070
01071 }
01072 file.close();
01073 return true;
01074 }
01075
01076 bool KStarsData::readURLData( QString urlfile, int type, bool deepOnly ) {
01077 QFile file;
01078 if (!openURLFile(urlfile, file)) return false;
01079
01080 QTextStream stream(&file);
01081
01082 while ( !stream.eof() ) {
01083 QString line = stream.readLine();
01084
01085
01086 if ( line.left(1) != "#" ) {
01087 QString name = line.mid( 0, line.find(':') );
01088 QString sub = line.mid( line.find(':')+1 );
01089 QString title = sub.mid( 0, sub.find(':') );
01090 QString url = sub.mid( sub.find(':')+1 );
01091
01092 SkyObjectName *sonm = ObjNames.find(name);
01093
01094 if (sonm == 0) {
01095 kdWarning() << k_funcinfo << name << " not found" << endl;
01096 } else {
01097 if ( ! deepOnly || ( sonm->skyObject()->type() > 2 && sonm->skyObject()->type() < 9 ) ) {
01098 if ( type==0 ) {
01099 sonm->skyObject()->ImageList.append( url );
01100 sonm->skyObject()->ImageTitle.append( title );
01101 } else if ( type==1 ) {
01102 sonm->skyObject()->InfoList.append( url );
01103 sonm->skyObject()->InfoTitle.append( title );
01104 }
01105 }
01106 }
01107 }
01108 }
01109 file.close();
01110 return true;
01111 }
01112
01113 bool KStarsData::readCustomCatalogs() {
01114 bool result = false;
01115
01116 for ( uint i=0; i < Options::catalogFile().count(); i++ ) {
01117 bool thisresult = addCatalog( Options::catalogFile()[i] );
01118
01119 result = ( result || thisresult );
01120 }
01121 return result;
01122 }
01123
01124 bool KStarsData::addCatalog( QString filename ) {
01125 CustomCatalog *newCat = createCustomCatalog( filename, false );
01126 if ( newCat ) {
01127 CustomCatalogs.append( newCat );
01128
01129
01130 for ( uint i=0; i < newCat->objList().count(); i++ ) {
01131
01132 SkyObject *o = newCat->objList().at(i);
01133 ObjNames.append( o );
01134 if ( o->hasLongName() && o->longname() != o->name() )
01135 ObjNames.append( o, true );
01136
01137
01138
01139
01140
01141 }
01142
01143 return true;
01144 } else
01145 kdWarning() << k_funcinfo << i18n("Error adding catalog: %1").arg( filename ) << endl;
01146
01147 return false;
01148 }
01149
01150 bool KStarsData::removeCatalog( int i ) {
01151 if ( ! CustomCatalogs.at(i) ) return false;
01152
01153 QPtrList<SkyObject> cat = CustomCatalogs.at(i)->objList();
01154
01155 for ( SkyObject *o=cat.first(); o; o=cat.next() ) {
01156 ObjNames.remove( o->name() );
01157 if ( o->hasLongName() && o->longname() != o->name() )
01158 ObjNames.remove( o->longname() );
01159 }
01160
01161 CustomCatalogs.remove(i);
01162
01163 return true;
01164 }
01165
01166 CustomCatalog* KStarsData::createCustomCatalog( QString filename, bool showerrs ) {
01167 QDir::setCurrent( QDir::homeDirPath() );
01168 QPtrList<SkyObject> objList;
01169 QString CatalogName, CatalogPrefix, CatalogColor;
01170 float CatalogEpoch;
01171
01172
01173
01174 if ( filename.at(0)=='~' )
01175 filename = QDir::homeDirPath() + filename.mid( 1, filename.length() );
01176 QFile ccFile( filename );
01177
01178 if ( ccFile.open( IO_ReadOnly ) ) {
01179 int iStart(0);
01180 QStringList errs;
01181 QStringList Columns;
01182
01183 QTextStream stream( &ccFile );
01184 QStringList lines = QStringList::split( "\n", stream.read() );
01185
01186 if ( parseCustomDataHeader( lines, Columns, CatalogName, CatalogPrefix,
01187 CatalogColor, CatalogEpoch, iStart, showerrs, errs ) ) {
01188
01189 QStringList::Iterator it = lines.begin();
01190 QStringList::Iterator itEnd = lines.end();
01191 it += iStart;
01192
01193 for ( uint i=iStart; i < lines.count(); i++ ) {
01194 QStringList d = QStringList::split( " ", lines[i] );
01195
01196
01197
01198
01199 int iname = Columns.findIndex( "Nm" );
01200 if ( iname >= 0 && d[iname].left(1) == "\"" ) {
01201 d[iname] = d[iname].mid(1);
01202
01203 if ( d[iname].right(1) == "\"" ) {
01204 d[iname] = d[iname].left( d[iname].length() - 1 );
01205 } else {
01206 int iend = iname + 1;
01207 while ( d[iend].right(1) != "\"" ) {
01208 d[iname] += " " + d[iend];
01209 ++iend;
01210 }
01211 d[iname] += " " + d[iend].left( d[iend].length() - 1 );
01212
01213
01214 for ( int j=iname+1; j<=iend; j++ ) {
01215 d.remove( d.at(iname + 1) );
01216 }
01217 }
01218 }
01219
01220 if ( d.count() == Columns.count() ) {
01221 processCustomDataLine( i, d, Columns, CatalogPrefix, objList, showerrs, errs );
01222 } else {
01223 if ( showerrs ) errs.append( i18n( "Line %1 does not contain %2 fields. Skipping it." ).arg( i ).arg( Columns.count() ) );
01224 }
01225 }
01226 }
01227
01228 if ( objList.count() ) {
01229 if ( errs.count() > 0 ) {
01230 QString message( i18n( "Some lines in the custom catalog could not be parsed; see error messages below." ) + "\n" +
01231 i18n( "To reject the file, press Cancel. " ) +
01232 i18n( "To accept the file (ignoring unparsed lines), press Accept." ) );
01233 if ( KMessageBox::warningContinueCancelList( 0, message, errs,
01234 i18n( "Some Lines in File Were Invalid" ), i18n( "Accept" ) ) != KMessageBox::Continue ) {
01235 return 0;
01236 }
01237 }
01238 } else {
01239 if ( showerrs ) {
01240 QString message( i18n( "No lines could be parsed from the specified file, see error messages below." ) );
01241 KMessageBox::informationList( 0, message, errs,
01242 i18n( "No Valid Data Found in File" ) );
01243 }
01244 return 0;
01245 }
01246
01247 } else {
01248 if ( showerrs )
01249 KMessageBox::sorry( 0, i18n( "Could not open custom data file: %1" ).arg( filename ),
01250 i18n( "Error opening file" ) );
01251 else
01252 kdDebug() << i18n( "Could not open custom data file: %1" ).arg( filename ) << endl;
01253 }
01254
01255
01256 if ( objList.count() )
01257 return new CustomCatalog( CatalogName, CatalogPrefix, CatalogColor, CatalogEpoch, objList );
01258 else
01259 return 0;
01260 }
01261
01262
01263 bool KStarsData::processCustomDataLine( int lnum, QStringList d, QStringList Columns,
01264 QString Prefix, QPtrList<SkyObject> &objList, bool showerrs, QStringList &errs ) {
01265
01266
01267 unsigned char iType(0);
01268 dms RA, Dec;
01269 float mag(0.0), a(0.0), b(0.0), PA(0.0);
01270 QString name(""); QString lname("");
01271
01272 for ( uint i=0; i<Columns.count(); i++ ) {
01273 if ( Columns[i] == "ID" )
01274 name = Prefix + " " + d[i];
01275
01276 if ( Columns[i] == "Nm" )
01277 lname = d[i];
01278
01279 if ( Columns[i] == "RA" ) {
01280 if ( ! RA.setFromString( d[i], false ) ) {
01281 if ( showerrs )
01282 errs.append( i18n( "Line %1, field %2: Unable to parse RA value: %3" )
01283 .arg(lnum).arg(i).arg(d[i]) );
01284 return false;
01285 }
01286 }
01287
01288 if ( Columns[i] == "Dc" ) {
01289 if ( ! Dec.setFromString( d[i], true ) ) {
01290 if ( showerrs )
01291 errs.append( i18n( "Line %1, field %2: Unable to parse Dec value: %3" )
01292 .arg(lnum).arg(i).arg(d[i]) );
01293 return false;
01294 }
01295 }
01296
01297 if ( Columns[i] == "Tp" ) {
01298 bool ok(false);
01299 iType = d[i].toUInt( &ok );
01300 if ( ok ) {
01301 if ( iType == 2 || iType > 8 ) {
01302 if ( showerrs )
01303 errs.append( i18n( "Line %1, field %2: Invalid object type: %3" )
01304 .arg(lnum).arg(i).arg(d[i]) +
01305 i18n( "Must be one of 0, 1, 3, 4, 5, 6, 7, 8." ) );
01306 return false;
01307 }
01308 } else {
01309 if ( showerrs )
01310 errs.append( i18n( "Line %1, field %2: Unable to parse Object type: %3" )
01311 .arg(lnum).arg(i).arg(d[i]) );
01312 return false;
01313 }
01314 }
01315
01316 if ( Columns[i] == "Mg" ) {
01317 bool ok(false);
01318 mag = d[i].toFloat( &ok );
01319 if ( ! ok ) {
01320 if ( showerrs )
01321 errs.append( i18n( "Line %1, field %2: Unable to parse Magnitude: %3" )
01322 .arg(lnum).arg(i).arg(d[i]) );
01323 return false;
01324 }
01325 }
01326
01327 if ( Columns[i] == "Mj" ) {
01328 bool ok(false);
01329 a = d[i].toFloat( &ok );
01330 if ( ! ok ) {
01331 if ( showerrs )
01332 errs.append( i18n( "Line %1, field %2: Unable to parse Major Axis: %3" )
01333 .arg(lnum).arg(i).arg(d[i]) );
01334 return false;
01335 }
01336 }
01337
01338 if ( Columns[i] == "Mn" ) {
01339 bool ok(false);
01340 b = d[i].toFloat( &ok );
01341 if ( ! ok ) {
01342 if ( showerrs )
01343 errs.append( i18n( "Line %1, field %2: Unable to parse Minor Axis: %3" )
01344 .arg(lnum).arg(i).arg(d[i]) );
01345 return false;
01346 }
01347 }
01348
01349 if ( Columns[i] == "PA" ) {
01350 bool ok(false);
01351 PA = d[i].toFloat( &ok );
01352 if ( ! ok ) {
01353 if ( showerrs )
01354 errs.append( i18n( "Line %1, field %2: Unable to parse Position Angle: %3" )
01355 .arg(lnum).arg(i).arg(d[i]) );
01356 return false;
01357 }
01358 }
01359 }
01360
01361 if ( iType == 0 ) {
01362 StarObject *o = new StarObject( RA, Dec, mag, lname );
01363 objList.append( o );
01364 } else {
01365 DeepSkyObject *o = new DeepSkyObject( iType, RA, Dec, mag,
01366 name, "", lname, Prefix, a, b, PA );
01367 objList.append( o );
01368 }
01369
01370 return true;
01371 }
01372
01373 bool KStarsData::parseCustomDataHeader( QStringList lines, QStringList &Columns,
01374 QString &CatalogName, QString &CatalogPrefix, QString &CatalogColor, float &CatalogEpoch,
01375 int &iStart, bool showerrs, QStringList &errs ) {
01376
01377 bool foundDataColumns( false );
01378 int ncol( 0 );
01379
01380 QStringList::Iterator it = lines.begin();
01381 QStringList::Iterator itEnd = lines.end();
01382
01383 CatalogName = "";
01384 CatalogPrefix = "";
01385 CatalogColor = "";
01386 CatalogEpoch = 0.;
01387 for ( ; it != itEnd; it++ ) {
01388 QString d( *it );
01389 if ( d.left(1) != "#" ) break;
01390
01391 int iname = d.find( "# Name: " );
01392 int iprefix = d.find( "# Prefix: " );
01393 int icolor = d.find( "# Color: " );
01394 int iepoch = d.find( "# Epoch: " );
01395
01396 if ( iname == 0 ) {
01397 iname = d.find(":")+2;
01398 if ( CatalogName.isEmpty() ) {
01399 CatalogName = d.mid( iname );
01400 } else {
01401 if ( showerrs )
01402 errs.append( i18n( "Parsing header: " ) +
01403 i18n( "Extra Name field in header: %1. Will be ignored" ).arg( d.mid(iname) ) );
01404 }
01405 } else if ( iprefix == 0 ) {
01406 iprefix = d.find(":")+2;
01407 if ( CatalogPrefix.isEmpty() ) {
01408 CatalogPrefix = d.mid( iprefix );
01409 } else {
01410 if ( showerrs )
01411 errs.append( i18n( "Parsing header: " ) +
01412 i18n( "Extra Prefix field in header: %1. Will be ignored" ).arg( d.mid(iprefix) ) );
01413 }
01414 } else if ( icolor == 0 ) {
01415 icolor = d.find(":")+2;
01416 if ( CatalogColor.isEmpty() ) {
01417 CatalogColor = d.mid( icolor );
01418 } else {
01419 if ( showerrs )
01420 errs.append( i18n( "Parsing header: " ) +
01421 i18n( "Extra Color field in header: %1. Will be ignored" ).arg( d.mid(icolor) ) );
01422 }
01423 } else if ( iepoch == 0 ) {
01424 iepoch = d.find(":")+2;
01425 if ( CatalogEpoch == 0. ) {
01426 bool ok( false );
01427 CatalogEpoch = d.mid( iepoch ).toFloat( &ok );
01428 if ( !ok ) {
01429 if ( showerrs )
01430 errs.append( i18n( "Parsing header: " ) +
01431 i18n( "Could not convert Epoch to float: %1. Using 2000. instead" ).arg( d.mid(iepoch) ) );
01432 CatalogEpoch = 2000.;
01433 }
01434 } else {
01435 if ( showerrs )
01436 errs.append( i18n( "Parsing header: " ) +
01437 i18n( "Extra Epoch field in header: %1. Will be ignored" ).arg( d.mid(iepoch) ) );
01438 }
01439 } else if ( ! foundDataColumns ) {
01440
01441 d = d.replace( QRegExp( "#" ), "" );
01442
01443 QStringList fields = QStringList::split( " ", d );
01444
01445
01446
01447
01448 QStringList master( KStarsData::CustomColumns );
01449
01450 QStringList::Iterator itf = fields.begin();
01451 QStringList::Iterator itfEnd = fields.end();
01452
01453 for ( ; itf != itfEnd; itf++ ) {
01454 QString s( *itf );
01455 if ( master.contains( s ) ) {
01456
01457 Columns.append( s );
01458
01459
01460
01461 if ( s != "Ig" ) {
01462 master.remove( master.find( s ) );
01463 ncol++;
01464 }
01465 } else if ( fields.contains( s ) ) {
01466 fields.append( "Ig" );
01467 if ( showerrs )
01468 errs.append( i18n( "Parsing header: " ) +
01469 i18n( "Duplicate data field descriptor \"%1\" will be ignored" ).arg( s ) );
01470 } else {
01471 fields.append( "Ig" );
01472 if ( showerrs )
01473 errs.append( i18n( "Parsing header: " ) +
01474 i18n( "Invalid data field descriptor \"%1\" will be ignored" ).arg( s ) );
01475 }
01476 }
01477
01478 if ( ncol ) foundDataColumns = true;
01479 }
01480 }
01481
01482 if ( ! foundDataColumns ) {
01483 if ( showerrs )
01484 errs.append( i18n( "Parsing header: " ) +
01485 i18n( "No valid column descriptors found. Exiting" ) );
01486 return false;
01487 }
01488
01489 if ( it == itEnd ) {
01490 if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
01491 i18n( "No data lines found after header. Exiting." ) );
01492 return false;
01493 } else {
01494
01495 if ( CatalogName.isEmpty() ) {
01496 if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
01497 i18n( "No Catalog Name specified; setting to \"Custom\"" ) );
01498 CatalogName = i18n("Custom");
01499 }
01500 if ( CatalogPrefix.isEmpty() ) {
01501 if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
01502 i18n( "No Catalog Prefix specified; setting to \"CC\"" ) );
01503 CatalogPrefix = "CC";
01504 }
01505 if ( CatalogColor.isEmpty() ) {
01506 if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
01507 i18n( "No Catalog Color specified; setting to Red" ) );
01508 CatalogColor = "#CC0000";
01509 }
01510 if ( CatalogEpoch == 0. ) {
01511 if ( showerrs ) errs.append( i18n( "Parsing header: " ) +
01512 i18n( "No Catalog Epoch specified; assuming 2000." ) );
01513 CatalogEpoch = 2000.;
01514 }
01515
01516
01517 iStart = lines.findIndex( QString( *it ) );
01518 return true;
01519 }
01520 }
01521
01522 bool KStarsData::processCity( QString& line ) {
01523 QString totalLine;
01524 QString name, province, country;
01525 QStringList fields;
01526 TimeZoneRule *TZrule;
01527 bool intCheck = true;
01528 char latsgn, lngsgn;
01529 int lngD, lngM, lngS;
01530 int latD, latM, latS;
01531 double TZ;
01532 float lng, lat;
01533
01534 totalLine = line;
01535
01536
01537 fields = QStringList::split( ":", line );
01538
01539 for ( unsigned int i=0; i< fields.count(); ++i )
01540 fields[i] = fields[i].stripWhiteSpace();
01541
01542 if ( fields.count() < 11 ) {
01543 kdDebug()<< i18n( "Cities.dat: Ran out of fields. Line was:" ) <<endl;
01544 kdDebug()<< totalLine.local8Bit() <<endl;
01545 return false;
01546 } else if ( fields.count() < 12 ) {
01547
01548 fields.append("");
01549 fields.append("--");
01550 } else if ( fields.count() < 13 ) {
01551
01552 fields.append("--");
01553 }
01554
01555 name = fields[0];
01556 province = fields[1];
01557 country = fields[2];
01558
01559 latD = fields[3].toInt( &intCheck );
01560 if ( !intCheck ) {
01561 kdDebug() << fields[3] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
01562 return false;
01563 }
01564
01565 latM = fields[4].toInt( &intCheck );
01566 if ( !intCheck ) {
01567 kdDebug() << fields[4] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
01568 return false;
01569 }
01570
01571 latS = fields[5].toInt( &intCheck );
01572 if ( !intCheck ) {
01573 kdDebug() << fields[5] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
01574 return false;
01575 }
01576
01577 QChar ctemp = fields[6].at(0);
01578 latsgn = ctemp;
01579 if (latsgn != 'N' && latsgn != 'S') {
01580 kdDebug() << latsgn << i18n( "\nCities.dat: Invalid latitude sign. Line was:\n" ) << totalLine << endl;
01581 return false;
01582 }
01583
01584 lngD = fields[7].toInt( &intCheck );
01585 if ( !intCheck ) {
01586 kdDebug() << fields[7] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
01587 return false;
01588 }
01589
01590 lngM = fields[8].toInt( &intCheck );
01591 if ( !intCheck ) {
01592 kdDebug() << fields[8] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
01593 return false;
01594 }
01595
01596 lngS = fields[9].toInt( &intCheck );
01597 if ( !intCheck ) {
01598 kdDebug() << fields[9] << i18n( "\nCities.dat: Bad integer. Line was:\n" ) << totalLine << endl;
01599 return false;
01600 }
01601
01602 ctemp = fields[10].at(0);
01603 lngsgn = ctemp;
01604 if (lngsgn != 'E' && lngsgn != 'W') {
01605 kdDebug() << latsgn << i18n( "\nCities.dat: Invalid longitude sign. Line was:\n" ) << totalLine << endl;
01606 return false;
01607 }
01608
01609 lat = (float)latD + ((float)latM + (float)latS/60.0)/60.0;
01610 lng = (float)lngD + ((float)lngM + (float)lngS/60.0)/60.0;
01611
01612 if ( latsgn == 'S' ) lat *= -1.0;
01613 if ( lngsgn == 'W' ) lng *= -1.0;
01614
01615
01616
01617 if ( fields[11].isEmpty() || ('x' == fields[11].at(0)) ) {
01618 TZ = int(lng/15.0);
01619 } else {
01620 bool doubleCheck = true;
01621 TZ = fields[11].toDouble( &doubleCheck);
01622 if ( !doubleCheck ) {
01623 kdDebug() << fields[11] << i18n( "\nCities.dat: Bad time zone. Line was:\n" ) << totalLine << endl;
01624 return false;
01625 }
01626 }
01627
01628
01629 TZrule = &( Rulebook[ fields[12] ] );
01630
01631
01632
01633 geoList.append ( new GeoLocation( lng, lat, name, province, country, TZ, TZrule ));
01634 return true;
01635 }
01636
01637 bool KStarsData::readTimeZoneRulebook( void ) {
01638 QFile file;
01639 QString id;
01640
01641 if ( KSUtils::openDataFile( file, "TZrules.dat" ) ) {
01642 QTextStream stream( &file );
01643
01644 while ( !stream.eof() ) {
01645 QString line = stream.readLine().stripWhiteSpace();
01646 if ( line.left(1) != "#" && line.length() ) {
01647 QStringList fields = QStringList::split( " ", line );
01648 id = fields[0];
01649 QTime stime = QTime( fields[3].left( fields[3].find(':')).toInt() ,
01650 fields[3].mid( fields[3].find(':')+1, fields[3].length()).toInt() );
01651 QTime rtime = QTime( fields[6].left( fields[6].find(':')).toInt(),
01652 fields[6].mid( fields[6].find(':')+1, fields[6].length()).toInt() );
01653
01654 Rulebook[ id ] = TimeZoneRule( fields[1], fields[2], stime, fields[4], fields[5], rtime );
01655 }
01656 }
01657 return true;
01658 } else {
01659 return false;
01660 }
01661 }
01662
01663 bool KStarsData::readCityData( void ) {
01664 QFile file;
01665 bool citiesFound = false;
01666
01667
01668 if ( KSUtils::openDataFile( file, "Cities.dat" ) ) {
01669 KSFileReader fileReader( file );
01670 while ( fileReader.hasMoreLines() ) {
01671 citiesFound |= processCity( fileReader.readLine() );
01672 }
01673 }
01674
01675
01676
01677 file.setName( locate( "appdata", "mycities.dat" ) );
01678 if ( file.exists() && file.open( IO_ReadOnly ) ) {
01679 QTextStream stream( &file );
01680
01681 while ( !stream.eof() ) {
01682 QString line = stream.readLine();
01683 citiesFound |= processCity( line );
01684 }
01685 file.close();
01686 }
01687
01688 return citiesFound;
01689 }
01690
01691 void KStarsData::setMagnitude( float newMagnitude, bool forceReload ) {
01692
01693
01694
01695 if ( newMagnitude > maxSetMagnitude || forceReload ) {
01696 maxSetMagnitude = newMagnitude;
01697
01698 if (reloadingData() == false) {
01699 source = new FileSource(this, newMagnitude);
01700 loader = new StarDataSink(this);
01701 connect(loader, SIGNAL(done()), this, SLOT(checkDataPumpAction()));
01702 connect(loader, SIGNAL(updateSkymap()), this, SLOT(updateSkymap()));
01703 connect(loader, SIGNAL(clearCache()), this, SLOT(sendClearCache()));
01704
01705 pump = new QDataPump (source, (QDataSink*) loader);
01706 }
01707 }
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723 Options::setMagLimitDrawStar( newMagnitude );
01724 }
01725
01726 void KStarsData::checkDataPumpAction() {
01727
01728 bool reloadMoreData = false;
01729 if (source != 0) {
01730
01731 if (source->magnitude() < maxSetMagnitude) reloadMoreData = true;
01732 delete source;
01733 source = 0;
01734 }
01735 if (pump != 0) {
01736 delete pump;
01737 pump = 0;
01738 }
01739 if (loader != 0) {
01740 delete loader;
01741 loader = 0;
01742 }
01743
01744 if (reloadMoreData == true) {
01745 setMagnitude(maxSetMagnitude, true);
01746 }
01747 }
01748
01749 bool KStarsData::reloadingData() {
01750 return ( pump || loader || source );
01751 }
01752
01753 void KStarsData::updateSkymap() {
01754 emit update();
01755 }
01756
01757 void KStarsData::sendClearCache() {
01758 emit clearCache();
01759 }
01760
01761 void KStarsData::initialize() {
01762 if (startupComplete) return;
01763
01764 initTimer = new QTimer;
01765 QObject::connect(initTimer, SIGNAL(timeout()), this, SLOT( slotInitialize() ) );
01766 initCounter = 0;
01767 initTimer->start(1);
01768 }
01769
01770 void KStarsData::initError(QString s, bool required = false) {
01771 QString message, caption;
01772 initTimer->stop();
01773 if (required) {
01774 message = i18n( "The file %1 could not be found. "
01775 "KStars cannot run properly without this file. "
01776 "To continue loading, place the file in one of the "
01777 "following locations, then press Retry:\n\n" ).arg( s )
01778 + QString( "\t$(KDEDIR)/share/apps/kstars/%1\n" ).arg( s )
01779 + QString( "\t~/.kde/share/apps/kstars/%1\n\n" ).arg( s )
01780 + i18n( "Otherwise, press Cancel to shutdown." );
01781 caption = i18n( "Critical File Not Found: %1" ).arg( s );
01782 } else {
01783 message = i18n( "The file %1 could not be found. "
01784 "KStars can still run without this file. "
01785 "However, to avoid seeing this message in the future, you can "
01786 "place the file in one of the following locations, then press Retry:\n\n" ).arg( s )
01787 + QString( "\t$(KDEDIR)/share/apps/kstars/%1\n" ).arg( s )
01788 + QString( "\t~/.kde/share/apps/kstars/%1\n\n" ).arg( s )
01789 + i18n( "Otherwise, press Cancel to continue loading without this file." ).arg( s );
01790 caption = i18n( "Non-Critical File Not Found: %1" ).arg( s );
01791 }
01792
01793 if ( KMessageBox::warningContinueCancel( 0, message, caption, i18n( "Retry" ) ) == KMessageBox::Continue ) {
01794 initCounter--;
01795 initTimer->start(1);
01796 } else {
01797 if (required) {
01798 delete initTimer;
01799 initTimer = 0L;
01800 emit initFinished(false);
01801 } else {
01802 initTimer->start(1);
01803 }
01804 }
01805 }
01806
01807 void KStarsData::slotInitialize() {
01808 QFile imFile;
01809 QString ImageName;
01810
01811 kapp->flush();
01812
01813 switch ( initCounter )
01814 {
01815 case 0:
01816 emit progressText( i18n("Reading Time Zone Rules") );
01817
01818 if (objects==1) {
01819
01820 if ( !readTimeZoneRulebook( ) )
01821 initError( "TZrules.dat", true );
01822 }
01823
01824
01825 readINDIHosts();
01826 break;
01827
01828 case 1:
01829 {
01830 if (objects>1) break;
01831
01832 emit progressText( i18n("Loading City Data") );
01833
01834 if ( !readCityData( ) )
01835 initError( "Cities.dat", true );
01836
01837 break;
01838 }
01839
01840 case 2:
01841
01842 emit progressText(i18n("Loading Star Data (%1%)" ).arg(0) );
01843 if ( !readStarData( ) )
01844 initError( "hipNNN.dat", true );
01845 if (!readVARData())
01846 initError( "valaav.dat", false);
01847 if (!readADVTreeData())
01848 initError( "advinterface.dat", false);
01849 break;
01850
01851 case 3:
01852
01853 emit progressText( i18n("Loading NGC/IC Data (%1%)" ).arg(0) );
01854 if ( !readDeepSkyData( ) )
01855 initError( "ngcicN.dat", true );
01856
01857 emit progressText( i18n("Loading Custom catalogs" ) );
01858 readCustomCatalogs( );
01859
01860
01861 break;
01862
01863 case 4:
01864
01865 emit progressText( i18n("Loading Constellations" ) );
01866 if ( !readCLineData( ) )
01867 initError( "clines.dat", true );
01868 break;
01869
01870 case 5:
01871
01872 emit progressText( i18n("Loading Constellation Names" ) );
01873 if ( !readCNameData( ) )
01874 initError( cnameFile, true );
01875 break;
01876
01877 case 6:
01878
01879 emit progressText( i18n("Loading Constellation Boundaries" ) );
01880 if ( !readCBoundData( ) )
01881 initError( "cbound.dat", true );
01882 break;
01883
01884 case 7:
01885
01886 emit progressText( i18n("Loading Milky Way" ) );
01887 if ( !readMWData( ) )
01888 initError( "mw*.dat", true );
01889 break;
01890
01891 case 8:
01892
01893 emit progressText( i18n("Creating Planets" ) );
01894 if (PCat->initialize())
01895 PCat->addObject( ObjNames );
01896
01897 jmoons = new JupiterMoons();
01898 break;
01899
01900 case 9:
01901
01902 emit progressText( i18n( "Creating Asteroids and Comets" ) );
01903 if ( !readAsteroidData() )
01904 initError( "asteroids.dat", false );
01905 if ( !readCometData() )
01906 initError( "comets.dat", false );
01907
01908 break;
01909
01910 case 10:
01911
01912 emit progressText( i18n("Creating Moon" ) );
01913 Moon = new KSMoon(this);
01914 ObjNames.append( Moon );
01915 Moon->loadData();
01916 break;
01917
01918 case 11:
01919
01920 emit progressText( i18n("Loading Image URLs" ) );
01921 if ( !readURLData( "image_url.dat", 0 ) ) {
01922 initError( "image_url.dat", false );
01923 }
01924
01925
01926
01927
01928 readUserLog();
01929
01930 break;
01931
01932 case 12:
01933
01934 emit progressText( i18n("Loading Information URLs" ) );
01935 if ( !readURLData( "info_url.dat", 1 ) ) {
01936 initError( "info_url.dat", false );
01937 }
01938
01939
01940
01941 break;
01942
01943 default:
01944 initTimer->stop();
01945 delete initTimer;
01946 initTimer = 0L;
01947 startupComplete = true;
01948 emit initFinished(true);
01949 break;
01950 }
01951
01952 initCounter++;
01953 }
01954
01955 void KStarsData::initGuides(KSNumbers *num)
01956 {
01957
01958 for ( unsigned int i=0; i<NCIRCLE; ++i ) {
01959 SkyPoint *o = new SkyPoint( i*24./NCIRCLE, 0.0 );
01960 o->EquatorialToHorizontal( LST, geo()->lat() );
01961 Equator.append( o );
01962 }
01963
01964
01965
01966
01967
01968 dms temp( 0.0 );
01969 for (SkyPoint *point = Equator.first(); point; point = Equator.next()) {
01970 double sinlat, coslat, sindec, cosdec, sinAz, cosAz;
01971 double HARad;
01972 dms dec, HA, RA, Az;
01973 Az = dms(*(point->ra()));
01974
01975 Az.SinCos( sinAz, cosAz );
01976 geo()->lat()->SinCos( sinlat, coslat );
01977
01978 dec.setRadians( asin( coslat*cosAz ) );
01979 dec.SinCos( sindec, cosdec );
01980
01981 HARad = acos( -1.0*(sinlat*sindec)/(coslat*cosdec) );
01982 if ( sinAz > 0.0 ) { HARad = 2.0*dms::PI - HARad; }
01983 HA.setRadians( HARad );
01984 RA = LST->Degrees() - HA.Degrees();
01985
01986 SkyPoint *o = new SkyPoint( RA, dec );
01987 o->setAlt( 0.0 );
01988 o->setAz( Az );
01989
01990 Horizon.append( o );
01991
01992
01993 o = new SkyPoint( 0.0, 0.0 );
01994 o->setFromEcliptic( num->obliquity(), point->ra(), &temp );
01995 o->EquatorialToHorizontal( LST, geo()->lat() );
01996 Ecliptic.append( o );
01997 }
01998 }
01999
02000 void KStarsData::resetToNewDST(const GeoLocation *geo, const bool automaticDSTchange) {
02001
02002
02003 geo->tzrule()->reset_with_ltime( LTime, geo->TZ0(), TimeRunsForward, automaticDSTchange );
02004
02005 setNextDSTChange( geo->tzrule()->nextDSTChange() );
02006
02007 LTime = geo->UTtoLT( ut() );
02008 }
02009
02010 void KStarsData::updateTime( GeoLocation *geo, SkyMap *skymap, const bool automaticDSTchange ) {
02011
02012 LTime = geo->UTtoLT( ut() );
02013 syncLST();
02014
02015
02016
02017 if ( !geo->tzrule()->isEmptyRule() ) {
02018 if ( TimeRunsForward ) {
02019
02020
02021 if ( ut() > NextDSTChange ) resetToNewDST(geo, automaticDSTchange);
02022 } else {
02023
02024
02025 if ( ut() < NextDSTChange ) resetToNewDST(geo, automaticDSTchange);
02026 }
02027 }
02028
02029 KSNumbers num( ut().djd() );
02030
02031 bool needNewCoords = false;
02032 if ( fabs( ut().djd() - LastNumUpdate.djd() ) > 1.0 ) {
02033
02034 needNewCoords = true;
02035 LastNumUpdate = ut().djd();
02036 }
02037
02038
02039 if ( fabs( ut().djd() - LastPlanetUpdate.djd() ) > 0.01 ) {
02040 LastPlanetUpdate = ut().djd();
02041
02042 if ( Options::showPlanets() ) PCat->findPosition( &num, geo->lat(), LST );
02043
02044
02045 if ( Options::showPlanets() && Options::showAsteroids() )
02046 for ( KSAsteroid *ast = asteroidList.first(); ast; ast = asteroidList.next() )
02047 ast->findPosition( &num, geo->lat(), LST, earth() );
02048
02049
02050 if ( Options::showPlanets() && Options::showComets() )
02051 for ( KSComet *com = cometList.first(); com; com = cometList.next() )
02052 com->findPosition( &num, geo->lat(), LST, earth() );
02053
02054
02055 if ( Options::showEcliptic() ) {
02056 Ecliptic.clear();
02057
02058 dms temp(0.0);
02059 for ( unsigned int i=0; i<Equator.count(); ++i ) {
02060 SkyPoint *o = new SkyPoint( 0.0, 0.0 );
02061 o->setFromEcliptic( num.obliquity(), Equator.at(i)->ra(), &temp );
02062 Ecliptic.append( o );
02063 }
02064 }
02065 }
02066
02067
02068 if ( fabs( ut().djd() - LastMoonUpdate.djd() ) > 0.00069444 ) {
02069 LastMoonUpdate = ut();
02070 if ( Options::showMoon() ) {
02071 Moon->findPosition( &num, geo->lat(), LST );
02072 Moon->findPhase( PCat->planetSun() );
02073 }
02074
02075
02076 if ( Options::showPlanets() && Options::showJupiter() )
02077 jmoons->findPosition( &num, (const KSPlanet*)PCat->findByName("Jupiter"), PCat->planetSun() );
02078 }
02079
02080
02081
02082 if ( fabs( ut().djd() - LastSkyUpdate.djd() ) > 0.25/Options::zoomFactor() || clock()->isManualMode() ) {
02083 LastSkyUpdate = ut();
02084
02085
02086
02087
02088 PCat->EquatorialToHorizontal( LST, geo->lat() );
02089
02090 jmoons->EquatorialToHorizontal( LST, geo->lat() );
02091 if ( Options::showMoon() ) {
02092 Moon->EquatorialToHorizontal( LST, geo->lat() );
02093 if ( Moon->hasTrail() ) Moon->updateTrail( LST, geo->lat() );
02094 }
02095
02096
02097
02098
02099
02100
02101 if ( Options::showAsteroids() ) {
02102 for ( KSAsteroid *ast = asteroidList.first(); ast; ast = asteroidList.next() ) {
02103 ast->EquatorialToHorizontal( LST, geo->lat() );
02104 if ( ast->hasTrail() ) ast->updateTrail( LST, geo->lat() );
02105 }
02106 }
02107
02108
02109 if ( Options::showComets() ) {
02110 for ( KSComet *com = cometList.first(); com; com = cometList.next() ) {
02111 com->EquatorialToHorizontal( LST, geo->lat() );
02112 if ( com->hasTrail() ) com->updateTrail( LST, geo->lat() );
02113 }
02114 }
02115
02116
02117 if ( Options::showStars() || Options::showCLines() ) {
02118
02119 float mag = Options::magLimitDrawStar();
02120 if (mag < MINDRAWSTARMAG) mag = MINDRAWSTARMAG;
02121 for ( StarObject *star = starList.first(); star; star = starList.next() ) {
02122 if ( star->mag() > mag ) break;
02123 if (needNewCoords) star->updateCoords( &num );
02124 star->EquatorialToHorizontal( LST, geo->lat() );
02125 }
02126 }
02127
02128
02129 if ( Options::showMessier() || Options::showMessierImages() ) {
02130 for ( SkyObject *o = deepSkyListMessier.first(); o; o = deepSkyListMessier.next() ) {
02131 if (needNewCoords) o->updateCoords( &num );
02132 o->EquatorialToHorizontal( LST, geo->lat() );
02133 }
02134 }
02135 if ( Options::showNGC() ) {
02136 for ( SkyObject *o = deepSkyListNGC.first(); o; o = deepSkyListNGC.next() ) {
02137 if (needNewCoords) o->updateCoords( &num );
02138 o->EquatorialToHorizontal( LST, geo->lat() );
02139 }
02140 }
02141 if ( Options::showIC() ) {
02142 for ( SkyObject *o = deepSkyListIC.first(); o; o = deepSkyListIC.next() ) {
02143 if (needNewCoords) o->updateCoords( &num );
02144 o->EquatorialToHorizontal( LST, geo->lat() );
02145 }
02146 }
02147 if ( Options::showOther() ) {
02148 for ( SkyObject *o = deepSkyListOther.first(); o; o = deepSkyListOther.next() ) {
02149 if (needNewCoords) o->updateCoords( &num );
02150 o->EquatorialToHorizontal( LST, geo->lat() );
02151 }
02152 }
02153
02154
02155
02156 for ( unsigned int j=0; j< CustomCatalogs.count(); ++j ) {
02157 QPtrList<SkyObject> cat = CustomCatalogs.at(j)->objList();
02158 if ( Options::showCatalog()[j] ) {
02159 for ( SkyObject *o = cat.first(); o; o = cat.next() ) {
02160 if (needNewCoords) o->updateCoords( &num );
02161 o->EquatorialToHorizontal( LST, geo->lat() );
02162 }
02163 }
02164 }
02165
02166
02167 if ( Options::showMilkyWay() ) {
02168 for ( unsigned int j=0; j<11; ++j ) {
02169 for ( SkyPoint *p = MilkyWay[j].first(); p; p = MilkyWay[j].next() ) {
02170 if (needNewCoords) p->updateCoords( &num );
02171 p->EquatorialToHorizontal( LST, geo->lat() );
02172 }
02173 }
02174 }
02175
02176
02177 if ( Options::showCNames() ) {
02178 for ( SkyPoint *p = cnameList.first(); p; p = cnameList.next() ) {
02179 if (needNewCoords) p->updateCoords( &num );
02180 p->EquatorialToHorizontal( LST, geo->lat() );
02181 }
02182 }
02183
02184
02185 if ( Options::showCBounds() ) {
02186 for ( CSegment *seg = csegmentList.first(); seg; seg = csegmentList.next() ) {
02187 for ( SkyPoint *p = seg->firstNode(); p; p = seg->nextNode() ) {
02188 if ( needNewCoords ) p->updateCoords( &num );
02189 p->EquatorialToHorizontal( LST, geo->lat() );
02190 }
02191 }
02192 }
02193
02194
02195 if ( Options::showEquator() ) {
02196 for ( SkyPoint *p = Equator.first(); p; p = Equator.next() ) {
02197 p->EquatorialToHorizontal( LST, geo->lat() );
02198 }
02199 }
02200
02201
02202 if ( Options::showEcliptic() ) {
02203 for ( SkyPoint *p = Ecliptic.first(); p; p = Ecliptic.next() ) {
02204 p->EquatorialToHorizontal( LST, geo->lat() );
02205 }
02206 }
02207
02208
02209 if ( Options::showHorizon() || Options::showGround() ) {
02210 for ( SkyPoint *p = Horizon.first(); p; p = Horizon.next() ) {
02211 p->HorizontalToEquatorial( LST, geo->lat() );
02212 }
02213 }
02214
02215 for (SkyObject *o = INDITelescopeList.first(); o; o = INDITelescopeList.next())
02216 o->EquatorialToHorizontal(LST, geo->lat());
02217
02218
02219 skymap->updateFocus();
02220
02221 if ( clock()->isManualMode() )
02222 QTimer::singleShot( 0, skymap, SLOT( forceUpdateNow() ) );
02223 else skymap->forceUpdate();
02224 }
02225 }
02226
02227 void KStarsData::setTimeDirection( float scale ) {
02228 TimeRunsForward = ( scale < 0 ? false : true );
02229 }
02230
02231 void KStarsData::setFullTimeUpdate() {
02232 LastSkyUpdate.setDJD( (long double)INVALID_DAY );
02233 LastPlanetUpdate.setDJD( (long double)INVALID_DAY );
02234 LastMoonUpdate.setDJD( (long double)INVALID_DAY );
02235 LastNumUpdate.setDJD( (long double)INVALID_DAY );
02236 }
02237
02238 void KStarsData::setLocationFromOptions() {
02239 QMap<QString, TimeZoneRule>::Iterator it = Rulebook.find( Options::dST() );
02240 setLocation( GeoLocation ( Options::longitude(), Options::latitude(),
02241 Options::cityName(), Options::provinceName(), Options::countryName(),
02242 Options::timeZone(), &(it.data()), 4, Options::elevation() ) );
02243 }
02244
02245 void KStarsData::setLocation( const GeoLocation &l ) {
02246 GeoLocation g( l );
02247 if ( g.lat()->Degrees() >= 90.0 ) g.setLat( 89.99 );
02248 if ( g.lat()->Degrees() <= -90.0 ) g.setLat( -89.99 );
02249
02250 Geo = g;
02251
02252
02253 Options::setCityName( g.name() );
02254 Options::setProvinceName( g.province() );
02255 Options::setCountryName( g.country() );
02256 Options::setTimeZone( g.TZ0() );
02257 Options::setElevation( g.height() );
02258 Options::setLongitude( g.lng()->Degrees() );
02259 Options::setLatitude( g.lat()->Degrees() );
02260 }
02261
02262 void KStarsData::syncLST() {
02263 LST->set( geo()->GSTtoLST( ut().gst() ) );
02264 }
02265
02266 void KStarsData::changeDateTime( const KStarsDateTime &newDate ) {
02267
02268 setSnapNextFocus();
02269
02270 clock()->setUTC( newDate );
02271 LTime = geo()->UTtoLT( ut() );
02272
02273 syncLST();
02274
02275
02276 setFullTimeUpdate();
02277
02278
02279 geo()->tzrule()->reset_with_ltime(LTime, geo()->TZ0(), isTimeRunningForward() );
02280
02281
02282 setNextDSTChange( geo()->tzrule()->nextDSTChange() );
02283 }
02284
02285 SkyObject* KStarsData::objectNamed( const QString &name ) {
02286 if ( (name== "star") || (name== "nothing") || name.isEmpty() ) return NULL;
02287 if ( name== Moon->name() ) return Moon;
02288
02289 SkyObject *so = PCat->findByName(name);
02290
02291 if (so != 0)
02292 return so;
02293
02294
02295 for ( unsigned int i=0; i<starList.count(); ++i ) {
02296 if ( name==starList.at(i)->name() ) return starList.at(i);
02297 }
02298
02299
02300 for ( unsigned int i=0; i<deepSkyListMessier.count(); ++i ) {
02301 if ( name==deepSkyListMessier.at(i)->name() ) return deepSkyListMessier.at(i);
02302 }
02303 for ( unsigned int i=0; i<deepSkyListNGC.count(); ++i ) {
02304 if ( name==deepSkyListNGC.at(i)->name() ) return deepSkyListNGC.at(i);
02305 }
02306 for ( unsigned int i=0; i<deepSkyListIC.count(); ++i ) {
02307 if ( name==deepSkyListIC.at(i)->name() ) return deepSkyListIC.at(i);
02308 }
02309 for ( unsigned int i=0; i<deepSkyListOther.count(); ++i ) {
02310 if ( name==deepSkyListOther.at(i)->name() ) return deepSkyListOther.at(i);
02311 }
02312
02313
02314 for ( unsigned int i=0; i<cnameList.count(); ++i ) {
02315 if ( name==cnameList.at(i)->name() ) return cnameList.at(i);
02316 }
02317
02318
02319
02320 for ( unsigned int i=0; i<starList.count(); ++i ) {
02321 if ( name==starList.at(i)->gname( false ) ) return starList.at(i);
02322 }
02323
02324
02325 for ( unsigned int i=0; i<CustomCatalogs.count(); ++i ) {
02326 QPtrList<SkyObject> custCatObjs = CustomCatalogs.at(i)->objList();
02327 for ( unsigned int j = 0; j < custCatObjs.count(); ++j ) {
02328 if ( name==custCatObjs.at(j)->name() ) return custCatObjs.at(j);
02329 }
02330 }
02331
02332
02333 return NULL;
02334 }
02335
02336
02337
02338
02339
02340
02341
02342
02343 bool KStarsData::executeScript( const QString &scriptname, SkyMap *map ) {
02344 int cmdCount(0);
02345
02346 QFile f( scriptname );
02347 if ( !f.open( IO_ReadOnly) ) {
02348 kdDebug() << i18n( "Could not open file %1" ).arg( f.name() ) << endl;
02349 return false;
02350 }
02351
02352 QTextStream istream(&f);
02353 while ( ! istream.eof() ) {
02354 QString line = istream.readLine();
02355
02356
02357 if ( line.left(4) == "dcop" ) {
02358 line = line.mid( 20 );
02359 QStringList fn = QStringList::split( " ", line );
02360
02361 if ( fn[0] == "lookTowards" && fn.count() >= 2 ) {
02362 double az(-1.0);
02363 QString arg = fn[1].lower();
02364 if ( arg == "n" || arg == "north" ) az = 0.0;
02365 if ( arg == "ne" || arg == "northeast" ) az = 45.0;
02366 if ( arg == "e" || arg == "east" ) az = 90.0;
02367 if ( arg == "se" || arg == "southeast" ) az = 135.0;
02368 if ( arg == "s" || arg == "south" ) az = 180.0;
02369 if ( arg == "sw" || arg == "southwest" ) az = 225.0;
02370 if ( arg == "w" || arg == "west" ) az = 270.0;
02371 if ( arg == "nw" || arg == "northwest" ) az = 335.0;
02372 if ( az >= 0.0 ) {
02373 map->setFocusAltAz( 15.0, az );
02374 cmdCount++;
02375 map->setDestination( map->focus() );
02376 }
02377
02378 if ( arg == "z" || arg == "zenith" ) {
02379 map->setFocusAltAz( 90.0, map->focus()->az()->Degrees() );
02380 cmdCount++;
02381 map->setDestination( map->focus() );
02382 }
02383
02384
02385 fn.remove( fn.first() );
02386 SkyObject *target = objectNamed( fn.join( " " ) );
02387 if ( target ) { map->setFocus( target ); cmdCount++; }
02388
02389 } else if ( fn[0] == "setRaDec" && fn.count() == 3 ) {
02390 bool ok( false );
02391 dms r(0.0), d(0.0);
02392
02393 ok = r.setFromString( fn[1], false );
02394 if ( ok ) ok = d.setFromString( fn[2], true );
02395 if ( ok ) {
02396 map->setFocus( r, d );
02397 cmdCount++;
02398 }
02399
02400 } else if ( fn[0] == "setAltAz" && fn.count() == 3 ) {
02401 bool ok( false );
02402 dms az(0.0), alt(0.0);
02403
02404 ok = alt.setFromString( fn[1] );
02405 if ( ok ) ok = az.setFromString( fn[2] );
02406 if ( ok ) {
02407 map->setFocusAltAz( alt, az );
02408 cmdCount++;
02409 }
02410
02411 } else if ( fn[0] == "zoom" && fn.count() == 2 ) {
02412 bool ok(false);
02413 double z = fn[1].toDouble(&ok);
02414 if ( ok ) {
02415 if ( z > MAXZOOM ) z = MAXZOOM;
02416 if ( z < MINZOOM ) z = MINZOOM;
02417 Options::setZoomFactor( z );
02418 cmdCount++;
02419 }
02420
02421 } else if ( fn[0] == "zoomIn" ) {
02422 if ( Options::zoomFactor() < MAXZOOM ) {
02423 Options::setZoomFactor( Options::zoomFactor() * DZOOM );
02424 cmdCount++;
02425 }
02426 } else if ( fn[0] == "zoomOut" ) {
02427 if ( Options::zoomFactor() > MINZOOM ) {
02428 Options::setZoomFactor( Options::zoomFactor() / DZOOM );
02429 cmdCount++;
02430 }
02431 } else if ( fn[0] == "defaultZoom" ) {
02432 Options::setZoomFactor( DEFAULTZOOM );
02433 cmdCount++;
02434 } else if ( fn[0] == "setLocalTime" && fn.count() == 7 ) {
02435 bool ok(false);
02436 int yr(0), mth(0), day(0) ,hr(0), min(0), sec(0);
02437 yr = fn[1].toInt(&ok);
02438 if ( ok ) mth = fn[2].toInt(&ok);
02439 if ( ok ) day = fn[3].toInt(&ok);
02440 if ( ok ) hr = fn[4].toInt(&ok);
02441 if ( ok ) min = fn[5].toInt(&ok);
02442 if ( ok ) sec = fn[6].toInt(&ok);
02443 if ( ok ) {
02444 changeDateTime( geo()->LTtoUT( KStarsDateTime( ExtDate(yr, mth, day), QTime(hr,min,sec) ) ) );
02445 cmdCount++;
02446 } else {
02447 kdWarning() << i18n( "Could not set time: %1 / %2 / %3 ; %4:%5:%6" )
02448 .arg(day).arg(mth).arg(yr).arg(hr).arg(min).arg(sec) << endl;
02449 }
02450 } else if ( fn[0] == "changeViewOption" && fn.count() == 3 ) {
02451 bool bOk(false), nOk(false), dOk(false);
02452
02453
02454 bool bVal(false);
02455 if ( fn[2].lower() == "true" ) { bOk = true; bVal = true; }
02456 if ( fn[2].lower() == "false" ) { bOk = true; bVal = false; }
02457 if ( fn[2] == "1" ) { bOk = true; bVal = true; }
02458 if ( fn[2] == "0" ) { bOk = true; bVal = false; }
02459
02460
02461 int nVal = fn[2].toInt( &nOk );
02462
02463
02464 double dVal = fn[2].toDouble( &dOk );
02465
02466 if ( fn[1] == "FOVName" ) { Options::setFOVName( fn[2] ); cmdCount++; }
02467 if ( fn[1] == "FOVSize" && dOk ) { Options::setFOVSize( (float)dVal ); cmdCount++; }
02468 if ( fn[1] == "FOVShape" && nOk ) { Options::setFOVShape( nVal ); cmdCount++; }
02469 if ( fn[1] == "FOVColor" ) { Options::setFOVColor( fn[2] ); cmdCount++; }
02470 if ( fn[1] == "ShowStars" && bOk ) { Options::setShowStars( bVal ); cmdCount++; }
02471 if ( fn[1] == "ShowMessier" && bOk ) { Options::setShowMessier( bVal ); cmdCount++; }
02472 if ( fn[1] == "ShowMessierImages" && bOk ) { Options::setShowMessierImages( bVal ); cmdCount++; }
02473 if ( fn[1] == "ShowCLines" && bOk ) { Options::setShowCLines( bVal ); cmdCount++; }
02474 if ( fn[1] == "ShowCNames" && bOk ) { Options::setShowCNames( bVal ); cmdCount++; }
02475 if ( fn[1] == "ShowNGC" && bOk ) { Options::setShowNGC( bVal ); cmdCount++; }
02476 if ( fn[1] == "ShowIC" && bOk ) { Options::setShowIC( bVal ); cmdCount++; }
02477 if ( fn[1] == "ShowMilkyWay" && bOk ) { Options::setShowMilkyWay( bVal ); cmdCount++; }
02478 if ( fn[1] == "ShowGrid" && bOk ) { Options::setShowGrid( bVal ); cmdCount++; }
02479 if ( fn[1] == "ShowEquator" && bOk ) { Options::setShowEquator( bVal ); cmdCount++; }
02480 if ( fn[1] == "ShowEcliptic" && bOk ) { Options::setShowEcliptic( bVal ); cmdCount++; }
02481 if ( fn[1] == "ShowHorizon" && bOk ) { Options::setShowHorizon( bVal ); cmdCount++; }
02482 if ( fn[1] == "ShowGround" && bOk ) { Options::setShowGround( bVal ); cmdCount++; }
02483 if ( fn[1] == "ShowSun" && bOk ) { Options::setShowSun( bVal ); cmdCount++; }
02484 if ( fn[1] == "ShowMoon" && bOk ) { Options::setShowMoon( bVal ); cmdCount++; }
02485 if ( fn[1] == "ShowMercury" && bOk ) { Options::setShowMercury( bVal ); cmdCount++; }
02486 if ( fn[1] == "ShowVenus" && bOk ) { Options::setShowVenus( bVal ); cmdCount++; }
02487 if ( fn[1] == "ShowMars" && bOk ) { Options::setShowMars( bVal ); cmdCount++; }
02488 if ( fn[1] == "ShowJupiter" && bOk ) { Options::setShowJupiter( bVal ); cmdCount++; }
02489 if ( fn[1] == "ShowSaturn" && bOk ) { Options::setShowSaturn( bVal ); cmdCount++; }
02490 if ( fn[1] == "ShowUranus" && bOk ) { Options::setShowUranus( bVal ); cmdCount++; }
02491 if ( fn[1] == "ShowNeptune" && bOk ) { Options::setShowNeptune( bVal ); cmdCount++; }
02492 if ( fn[1] == "ShowPluto" && bOk ) { Options::setShowPluto( bVal ); cmdCount++; }
02493 if ( fn[1] == "ShowAsteroids" && bOk ) { Options::setShowAsteroids( bVal ); cmdCount++; }
02494 if ( fn[1] == "ShowComets" && bOk ) { Options::setShowComets( bVal ); cmdCount++; }
02495 if ( fn[1] == "ShowPlanets" && bOk ) { Options::setShowPlanets( bVal ); cmdCount++; }
02496 if ( fn[1] == "ShowDeepSky" && bOk ) { Options::setShowDeepSky( bVal ); cmdCount++; }
02497 if ( fn[1] == "ShowStarNames" && bOk ) { Options::setShowStarNames( bVal ); cmdCount++; }
02498 if ( fn[1] == "ShowStarMagnitudes" && bOk ) { Options::setShowStarMagnitudes( bVal ); cmdCount++; }
02499 if ( fn[1] == "ShowAsteroidNames" && bOk ) { Options::setShowAsteroidNames( bVal ); cmdCount++; }
02500 if ( fn[1] == "ShowCometNames" && bOk ) { Options::setShowCometNames( bVal ); cmdCount++; }
02501 if ( fn[1] == "ShowPlanetNames" && bOk ) { Options::setShowPlanetNames( bVal ); cmdCount++; }
02502 if ( fn[1] == "ShowPlanetImages" && bOk ) { Options::setShowPlanetImages( bVal ); cmdCount++; }
02503
02504 if ( fn[1] == "UseAltAz" && bOk ) { Options::setUseAltAz( bVal ); cmdCount++; }
02505 if ( fn[1] == "UseRefraction" && bOk ) { Options::setUseRefraction( bVal ); cmdCount++; }
02506 if ( fn[1] == "UseAutoLabel" && bOk ) { Options::setUseAutoLabel( bVal ); cmdCount++; }
02507 if ( fn[1] == "UseAutoTrail" && bOk ) { Options::setUseAutoTrail( bVal ); cmdCount++; }
02508 if ( fn[1] == "UseAnimatedSlewing" && bOk ) { Options::setUseAnimatedSlewing( bVal ); cmdCount++; }
02509 if ( fn[1] == "FadePlanetTrails" && bOk ) { Options::setFadePlanetTrails( bVal ); cmdCount++; }
02510 if ( fn[1] == "SlewTimeScale" && dOk ) { Options::setSlewTimeScale( dVal ); cmdCount++; }
02511 if ( fn[1] == "ZoomFactor" && dOk ) { Options::setZoomFactor( dVal ); cmdCount++; }
02512 if ( fn[1] == "MagLimitDrawStar" && dOk ) { Options::setMagLimitDrawStar( dVal ); cmdCount++; }
02513 if ( fn[1] == "MagLimitDrawStarZoomOut" && dOk ) { Options::setMagLimitDrawStarZoomOut( dVal ); cmdCount++; }
02514 if ( fn[1] == "MagLimitDrawDeepSky" && dOk ) { Options::setMagLimitDrawDeepSky( dVal ); cmdCount++; }
02515 if ( fn[1] == "MagLimitDrawDeepSkyZoomOut" && dOk ) { Options::setMagLimitDrawDeepSkyZoomOut( dVal ); cmdCount++; }
02516 if ( fn[1] == "MagLimitDrawStarInfo" && dOk ) { Options::setMagLimitDrawStarInfo( dVal ); cmdCount++; }
02517 if ( fn[1] == "MagLimitHideStar" && dOk ) { Options::setMagLimitHideStar( dVal ); cmdCount++; }
02518 if ( fn[1] == "MagLimitAsteroid" && dOk ) { Options::setMagLimitAsteroid( dVal ); cmdCount++; }
02519 if ( fn[1] == "MagLimitAsteroidName" && dOk ) { Options::setMagLimitAsteroidName( dVal ); cmdCount++; }
02520 if ( fn[1] == "MaxRadCometName" && dOk ) { Options::setMaxRadCometName( dVal ); cmdCount++; }
02521
02522
02523 if ( fn[1] == "UseLatinConstellationNames" && bOk ) {
02524 Options::setUseLatinConstellNames( true );
02525 Options::setUseLocalConstellNames( false );
02526 Options::setUseAbbrevConstellNames( false );
02527 cmdCount++;
02528 }
02529 if ( fn[1] == "UseLocalConstellationNames" && bOk ) {
02530 Options::setUseLatinConstellNames( false );
02531 Options::setUseLocalConstellNames( true );
02532 Options::setUseAbbrevConstellNames( false );
02533 cmdCount++;
02534 }
02535 if ( fn[1] == "UseAbbrevConstellationNames" && bOk ) {
02536 Options::setUseLatinConstellNames( false );
02537 Options::setUseLocalConstellNames( false );
02538 Options::setUseAbbrevConstellNames( true );
02539 cmdCount++;
02540 }
02541 } else if ( fn[0] == "setGeoLocation" && ( fn.count() == 3 || fn.count() == 4 ) ) {
02542 QString city( fn[1] ), province( "" ), country( fn[2] );
02543 if ( fn.count() == 4 ) {
02544 province = fn[2];
02545 country = fn[3];
02546 }
02547
02548 bool cityFound( false );
02549 for (GeoLocation *loc = geoList.first(); loc; loc = geoList.next()) {
02550 if ( loc->translatedName() == city &&
02551 ( province.isEmpty() || loc->translatedProvince() == province ) &&
02552 loc->translatedCountry() == country ) {
02553
02554 cityFound = true;
02555 setLocation( *loc );
02556 cmdCount++;
02557 break;
02558 }
02559 }
02560
02561 if ( !cityFound )
02562 kdWarning() << i18n( "Could not set location named %1, %2, %3" ).arg(city).arg(province).arg(country) << endl;
02563 }
02564 }
02565 }
02566
02567 if ( cmdCount ) return true;
02568 return false;
02569 }
02570
02571 void KStarsData::appendTelescopeObject(SkyObject * object)
02572 {
02573 INDITelescopeList.append(object);
02574 }
02575
02576 void KStarsData::saveTimeBoxShaded( bool b ) { Options::setShadeTimeBox( b ); }
02577 void KStarsData::saveGeoBoxShaded( bool b ) { Options::setShadeGeoBox( b ); }
02578 void KStarsData::saveFocusBoxShaded( bool b ) { Options::setShadeFocusBox( b ); }
02579 void KStarsData::saveTimeBoxPos( QPoint p ) { Options::setPositionTimeBox( p ); }
02580 void KStarsData::saveGeoBoxPos( QPoint p ) { Options::setPositionGeoBox( p ); }
02581 void KStarsData::saveFocusBoxPos( QPoint p ) { Options::setPositionFocusBox( p ); }
02582
02583 #include "kstarsdata.moc"