Пример #1
0
void CatalogComponent::update( KSNumbers * ) {
    if ( selected() ) {
        KStarsData *data = KStarsData::Instance();
        foreach ( SkyObject *obj, m_ObjectList ) {
            DeepSkyObject *dso  = dynamic_cast< DeepSkyObject * >( obj );
            StarObject *so = dynamic_cast< StarObject *>( obj );
            Q_ASSERT( dso || so ); // We either have stars, or deep sky objects
            if( dso ) {
                // Update the deep sky object if need be
                if ( dso->updateID != data->updateID() ) {
                    dso->updateID = data->updateID();
                    if ( dso->updateNumID != data->updateNumID() ) {
                        dso->updateCoords( data->updateNum() );

                    }
                    dso->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
                }
            }
            else {
                // Do exactly the same thing for stars
                if ( so->updateID != data->updateID() ) {
                    so->updateID = data->updateID();
                    if ( so->updateNumID != data->updateNumID() ) {
                        so->updateCoords( data->updateNum() );
                    }
                    so->EquatorialToHorizontal( data->lst(), data->geo()->lat() );
                }
            }
        }
        this->updateID = data->updateID();
    }
Пример #2
0
DeepSkyObject::DeepSkyObject( const DeepSkyObject &o )
    : SkyObject( o )
    , PositionAngle( o.PositionAngle )
    , m_image( o.m_image )
    , UGC( o.UGC )
    , PGC( o.PGC )
    , MajorAxis( o.MajorAxis )
    , MinorAxis( o.MinorAxis )
    , Catalog( o.Catalog )
{
    customCat = NULL;
    Flux = o.flux();
    setMag( o.mag() );
    updateID = updateNumID = 0;
}
Пример #3
0
QString KStars::getObjectDataXML( const QString &objectName ) {
    SkyObject *target = data()->objectNamed( objectName );
    if ( !target ) {
        return QString( "<xml></xml>" );
    }
    QString output;
    QXmlStreamWriter stream( &output );
    stream.setAutoFormatting( true );
    stream.writeStartDocument();
    stream.writeStartElement( "object" );
    stream.writeTextElement( "Name", target->name() );
    stream.writeTextElement( "Alt_Name", target->name2() );
    stream.writeTextElement( "Long_Name", target->longname() );
    stream.writeTextElement( "Constellation", KStarsData::Instance()->skyComposite()->getConstellationBoundary()->constellationName( target ) );
    stream.writeTextElement( "RA_HMS", target->ra().toHMSString() );
    stream.writeTextElement( "Dec_DMS", target->dec().toDMSString() );
    stream.writeTextElement( "RA_J2000_HMS", target->ra0().toHMSString() );
    stream.writeTextElement( "Dec_J2000_DMS", target->dec0().toDMSString() );
    stream.writeTextElement( "RA_Degrees", QString::number( target->ra().Degrees() ) );
    stream.writeTextElement( "Dec_Degrees", QString::number( target->dec().Degrees() ) );
    stream.writeTextElement( "RA_J2000_Degrees", QString::number( target->ra0().Degrees() ) );
    stream.writeTextElement( "Dec_J2000_Degrees", QString::number( target->dec0().Degrees() ) );
    stream.writeTextElement( "Type", target->typeName() );
    stream.writeTextElement( "Magnitude", QString::number( target->mag(), 'g', 2 ) );
    stream.writeTextElement( "Position_Angle", QString::number( target->pa(), 'g', 3 ) );
    StarObject *star = dynamic_cast< StarObject* >( target );
    DeepSkyObject *dso = dynamic_cast< DeepSkyObject* >( target );
    if ( star ) {
        stream.writeTextElement( "Spectral_Type",  star->sptype() );
        stream.writeTextElement( "Genetive_Name", star->gname() );
        stream.writeTextElement( "Greek_Letter", star->greekLetter() );
        stream.writeTextElement( "Proper_Motion", QString::number( star->pmMagnitude() ) );
        stream.writeTextElement( "Proper_Motion_RA", QString::number( star->pmRA() ) );
        stream.writeTextElement( "Proper_Motion_Dec", QString::number( star->pmDec() ) );
        stream.writeTextElement( "Parallax_mas", QString::number( star->parallax() ) );
        stream.writeTextElement( "Distance_pc", QString::number( star->distance() ) );
        stream.writeTextElement( "Henry_Draper", QString::number( star->getHDIndex() ) );
        stream.writeTextElement( "BV_Index", QString::number( star->getBVIndex() ) );
    }
    else if ( dso ) {
        stream.writeTextElement( "Catalog", dso->catalog() );
        stream.writeTextElement( "Major_Axis", QString::number( dso->a() ) );
        stream.writeTextElement( "Minor_Axis", QString::number( dso->a() * dso->e() ) );
    }
    stream.writeEndElement(); // object
    stream.writeEndDocument();
    return output;
}
Пример #4
0
QString SkyObjItem::getSurfaceBrightness() const
{
    /** Surface Brightness is applicable only for extended light sources like
      * Deep-Sky Objects. Here we use the formula SB = m + log10(a*b/4)
      * where m is the magnitude of the sky-object. a and b are the major and minor
      * axis lengths of the objects respectively in arcminutes. SB is the surface
      * brightness obtained in mag * arcminutes^-2
      */

    DeepSkyObject *dso = (DeepSkyObject *)m_So;
    float SB = m_So->mag() + 2.5 * log10(dso->a() * dso->b() / 4);

    switch(getType())
    {
    case Galaxy:
    case Nebula:
        return KGlobal::locale()->formatNumber(SB, 2) + " mag/arcmin^2";
    default:
        return QString(" --"); // Not applicable for other sky-objects
    }
}
Пример #5
0
void CatalogDB::GetAllObjects(const QString &catalog,
                              QList< SkyObject* > &sky_list,
                              QList < QPair <int, QString> > &object_names,
                              CatalogComponent *catalog_ptr) {
    sky_list.clear();
    QString selected_catalog = QString::number(FindCatalog(catalog));
    skydb_.open();
    QSqlQuery get_query(skydb_);
    get_query.prepare("SELECT Epoch, Type, RA, Dec, Magnitude, Prefix, "
                      "IDNumber, LongName, MajorAxis, MinorAxis, "
                      "PositionAngle, Flux FROM ObjectDesignation JOIN DSO "
                      "JOIN Catalog WHERE Catalog.id = :catID AND "
                      "ObjectDesignation.id_Catalog = Catalog.id AND "
                      "ObjectDesignation.UID_DSO = DSO.UID");
    get_query.bindValue("catID", selected_catalog);

//     kWarning() << get_query.lastQuery();
//     kWarning() << get_query.lastError();
//     kWarning() << FindCatalog(catalog);

    if (!get_query.exec()) {
        kWarning() << get_query.lastQuery();
        kWarning() << get_query.lastError();
    }

    while (get_query.next()) {

        int cat_epoch = get_query.value(0).toInt();
        unsigned char iType = get_query.value(1).toInt();
        dms RA(get_query.value(2).toDouble());
        dms Dec(get_query.value(3).toDouble());
        float mag = get_query.value(4).toFloat();
        QString catPrefix = get_query.value(5).toString();
        int id_number_in_catalog = get_query.value(6).toInt();
        QString lname = get_query.value(7).toString();
        float a = get_query.value(8).toFloat();
        float b = get_query.value(9).toFloat();
        float PA = get_query.value(10).toFloat();
        float flux = get_query.value(11).toFloat();

        QString name = catPrefix + ' ' + QString::number(id_number_in_catalog);
        SkyPoint t;
        t.set(RA, Dec);

        if (cat_epoch == 1950) {
            // Assume B1950 epoch
            t.B1950ToJ2000();  // t.ra() and t.dec() are now J2000.0
                               // coordinates
        } else if (cat_epoch == 2000) {
            // Do nothing
                 { }
               } else {
                 // FIXME: What should we do?
                 // FIXME: This warning will be printed for each line in the
                 //        catalog rather than once for the entire catalog
                 kWarning() << "Unknown epoch while dealing with custom "
                               "catalog. Will ignore the epoch and assume"
                               " J2000.0";
        }

        RA = t.ra();
        Dec = t.dec();

        if (iType == 0) {  // Add a star
            StarObject *o = new StarObject(RA, Dec, mag, lname);
            sky_list.append(o);
        } else {  // Add a deep-sky object
            DeepSkyObject *o = new DeepSkyObject(iType, RA, Dec, mag,
                                                 name, QString(), lname,
                                                 catPrefix, a, b, -PA);
            o->setFlux(flux);
            o->setCustomCatalog(catalog_ptr);

            sky_list.append(o);

            // Add name to the list of object names
            if (!name.isEmpty()) {
                object_names.append(qMakePair<int,QString>(iType, name));
            }
        }

        if (!lname.isEmpty() && lname != name) {
            object_names.append(qMakePair<int,QString>(iType, lname));
        }
    }

    get_query.clear();
    skydb_.close();
}
Пример #6
0
void DetailsTable::createGeneralTable(SkyObject *obj)
{
    clearContents();

    QTextCursor cursor = m_Document->rootFrame()->firstCursorPosition();

    //Fill in the data fields
    //Contents depend on type of object
    StarObject *s = 0;
    DeepSkyObject *dso = 0;
    KSPlanetBase *ps = 0;
    QString pname, oname;

    QString objNamesVal, objTypeVal, objDistVal, objSizeVal, objMagVal, objBvVal, objIllumVal;
    QString objSizeLabel, objMagLabel;

    switch(obj->type())
    {
    case SkyObject::STAR:
        {
            s = (StarObject *)obj;

            objNamesVal = s->longname();

            if(s->getHDIndex() != 0)
            {
                if(!s->longname().isEmpty())
                {
                    objNamesVal = s->longname() + QString(", HD%1").arg(QString::number(s->getHDIndex())) ;
                }

                else
                {
                    objNamesVal = QString(", HD%1").arg(QString::number(s->getHDIndex()));
                }
            }

            objTypeVal = s->sptype() + ' ' + i18n("star");
            objMagVal = i18nc("number in magnitudes", "%1 mag", KGlobal::locale()->formatNumber(s->mag(), 1)); //show to tenths place

            if(s->getBVIndex() < 30.0)
            {
                objBvVal = QString::number(s->getBVIndex(), 'g', 2);
            }

            //distance
            if(s->distance() > 2000. || s->distance() < 0.)  // parallax < 0.5 mas
            {
                objDistVal = i18nc("larger than 2000 parsecs", "> 2000 pc");
            }

            else if(s->distance() > 50.0) //show to nearest integer
            {
                objDistVal = i18nc("number in parsecs", "%1 pc", KGlobal::locale()->formatNumber(s->distance(), 0));
            }

            else if(s->distance() > 10.0) //show to tenths place
            {
                objDistVal = i18nc("number in parsecs", "%1 pc", KGlobal::locale()->formatNumber(s->distance(), 1));
            }

            else //show to hundredths place
            {
                objDistVal = i18nc("number in parsecs", "%1 pc", KGlobal::locale()->formatNumber(s->distance(), 2));
            }

            //Note multiplicity/variablility in angular size label
            if(s->isMultiple() && s->isVariable())
            {
                objSizeLabel = i18nc("the star is a multiple star", "multiple") + ',';
                objSizeVal = i18nc("the star is a variable star", "variable");
            }

            else if(s->isMultiple())
            {
                objSizeLabel = i18nc("the star is a multiple star", "multiple");
            }

            else if(s->isVariable())
            {
                objSizeLabel = i18nc("the star is a variable star", "variable");
            }

            objIllumVal = "--";

            break; //End of stars case
        }

    case SkyObject::ASTEROID:  //[fall through to planets]

    case SkyObject::COMET:     //[fall through to planets]

    case SkyObject::MOON:      //[fall through to planets]

    case SkyObject::PLANET:
        {
            ps = (KSPlanetBase *)obj;

            objNamesVal = ps->longname();
            //Type is "G5 star" for Sun
            if(ps->name() == "Sun")
            {
                objTypeVal = i18n("G5 star");
            }

            else if(ps->name() == "Moon")
            {
                objTypeVal = ps->translatedName();
            }

            else if(ps->name() == i18n("Pluto") || ps->name() == "Ceres" || ps->name() == "Eris") // TODO: Check if Ceres / Eris have translations and i18n() them
            {
                objTypeVal = i18n("Dwarf planet");
            }

            else
            {
                objTypeVal = ps->typeName();
            }

            //Magnitude: The moon displays illumination fraction instead
            if(obj->name() == "Moon")
            {
                objIllumVal = QString("%1 %").arg(KGlobal::locale()->formatNumber(((KSMoon *)obj)->illum()*100., 0));
            }

            objMagVal = i18nc("number in magnitudes", "%1 mag", KGlobal::locale()->formatNumber(ps->mag(), 1)); //show to tenths place

            //Distance from Earth.  The moon requires a unit conversion
            if(ps->name() == "Moon")
            {
                objDistVal = i18nc("distance in kilometers", "%1 km", KGlobal::locale()->formatNumber(ps->rearth() * AU_KM ));
            }

            else
            {
                objDistVal = i18nc("distance in Astronomical Units", "%1 AU", KGlobal::locale()->formatNumber(ps->rearth()));
            }

            //Angular size; moon and sun in arcmin, others in arcsec
            if(ps->angSize())
            {
                if(ps->name() == "Sun" || ps->name() == "Moon")
                {
                    // Needn't be a plural form because sun / moon will never contract to 1 arcminute
                    objSizeVal = i18nc("angular size in arcminutes", "%1 arcmin", KGlobal::locale()->formatNumber(ps->angSize()));
                }

                else
                {
                    objSizeVal = i18nc("angular size in arcseconds","%1 arcsec", KGlobal::locale()->formatNumber(ps->angSize() * 60.0));
                }
            }

            else
            {
                objSizeVal = "--";
            }

            break; //End of planets/comets/asteroids case
        }

    default: //Deep-sky objects
        {
            dso = (DeepSkyObject *)obj;

            //Show all names recorded for the object
            if(!dso->longname().isEmpty() && dso->longname() != dso->name())
            {
                pname = dso->translatedLongName();
                oname = dso->translatedName();
            }

            else
            {
                pname = dso->translatedName();
            }

            if(!dso->translatedName2().isEmpty())
            {
                if(oname.isEmpty())
                {
                    oname = dso->translatedName2();
                }

                else
                {
                    oname += ", " + dso->translatedName2();
                }
            }

            if(dso->ugc() != 0)
            {
                if(!oname.isEmpty())
                {
                    oname += ", ";
                }

                oname += "UGC " + QString::number(dso->ugc());
            }
            if(dso->pgc() != 0)
            {
                if(!oname.isEmpty())
                {
                    oname += ", ";
                }

                oname += "PGC " + QString::number(dso->pgc());
            }

            if(!oname.isEmpty())
            {
                pname += ", " + oname;
            }

            objNamesVal = pname;

            objTypeVal = dso->typeName();

            if(dso->type() == SkyObject::RADIO_SOURCE)
            {
                objMagLabel = i18nc("integrated flux at a frequency", "Flux(%1):", dso->customCatalog()->fluxFrequency());
                objMagVal = i18nc("integrated flux value", "%1 %2", KGlobal::locale()->formatNumber(dso->flux(), 1),
                                  dso->customCatalog()->fluxUnit()); //show to tenths place
            }

            else if(dso->mag() > 90.0)
            {
                objMagVal = "--";
            }

            else
            {
                objMagVal = i18nc("number in magnitudes", "%1 mag", KGlobal::locale()->formatNumber(dso->mag(), 1)); //show to tenths place
            }

            //No distances at this point...
            objDistVal = "--";

            //Only show decimal place for small angular sizes
            if(dso->a() > 10.0)
            {
                objSizeVal = i18nc("angular size in arcminutes", "%1 arcmin", KGlobal::locale()->formatNumber(dso->a(), 0));
            }

            else if(dso->a())
            {
                objSizeVal = i18nc("angular size in arcminutes", "%1 arcmin", KGlobal::locale()->formatNumber(dso->a(), 1));
            }

            else
            {
                objSizeVal = "--";
            }

            break; //End of deep-space objects case
        }
    }

    //Common to all types:
    if(obj->type() == SkyObject::CONSTELLATION )
    {
        objTypeVal = KStarsData::Instance()->skyComposite()->getConstellationBoundary()->constellationName(obj);
    }

    else
    {
        objTypeVal = i18nc("%1 type of sky object (planet, asteroid etc), %2 name of a constellation", "%1 in %2", objTypeVal,
                           KStarsData::Instance()->skyComposite()->getConstellationBoundary()->constellationName(obj));
    }

    QVector<QTextLength> constraints;
    constraints << QTextLength(QTextLength::PercentageLength, 25)
                << QTextLength(QTextLength::PercentageLength, 25)
                << QTextLength(QTextLength::PercentageLength, 25)
                << QTextLength(QTextLength::PercentageLength, 25);
    m_TableFormat.setColumnWidthConstraints(constraints);

    QTextTable *table = cursor.insertTable(5, 4, m_TableFormat);
    table->mergeCells(0, 0, 1, 4);
    QTextBlockFormat centered;
    centered.setAlignment(Qt::AlignCenter);
    table->cellAt(0, 0).firstCursorPosition().setBlockFormat(centered);
    table->cellAt(0, 0).firstCursorPosition().insertText(i18n("General"), m_TableTitleCharFormat);

    table->mergeCells(1, 1, 1, 3);
    table->cellAt(1, 0).firstCursorPosition().insertText(i18n("Names:"), m_ItemNameCharFormat);
    table->cellAt(1, 0).firstCursorPosition().setBlockFormat(centered);
    table->cellAt(1, 1).firstCursorPosition().insertText(objNamesVal, m_ItemValueCharFormat);

    table->cellAt(2, 0).firstCursorPosition().insertText(i18n("Type:"), m_ItemNameCharFormat);
    table->cellAt(2, 0).firstCursorPosition().setBlockFormat(centered);
    table->cellAt(2, 1).firstCursorPosition().insertText(objTypeVal, m_ItemValueCharFormat);

    table->cellAt(3, 0).firstCursorPosition().insertText(i18n("Distance:"), m_ItemNameCharFormat);
    table->cellAt(3, 0).firstCursorPosition().setBlockFormat(centered);
    table->cellAt(3, 1).firstCursorPosition().insertText(objDistVal, m_ItemValueCharFormat);

    table->cellAt(4, 0).firstCursorPosition().insertText(i18n("Size:"), m_ItemNameCharFormat);
    table->cellAt(4, 0).firstCursorPosition().setBlockFormat(centered);
    table->cellAt(4, 1).firstCursorPosition().insertText(objSizeVal, m_ItemValueCharFormat);

    table->cellAt(2, 2).firstCursorPosition().insertText(i18n("Magnitude:"), m_ItemNameCharFormat);
    table->cellAt(2, 2).firstCursorPosition().setBlockFormat(centered);
    table->cellAt(2, 3).firstCursorPosition().insertText(objMagVal, m_ItemValueCharFormat);

    table->cellAt(3, 2).firstCursorPosition().insertText(i18n("B-V index:"), m_ItemNameCharFormat);
    table->cellAt(3, 2).firstCursorPosition().setBlockFormat(centered);
    table->cellAt(3, 3).firstCursorPosition().insertText(objBvVal, m_ItemValueCharFormat);

    table->cellAt(4, 2).firstCursorPosition().insertText(i18n("Illumination:"), m_ItemNameCharFormat);
    table->cellAt(4, 2).firstCursorPosition().setBlockFormat(centered);
    table->cellAt(4, 3).firstCursorPosition().insertText(objIllumVal, m_ItemValueCharFormat);
}
Пример #7
0
void DeepSkyComponent::loadData()
{

    KStarsData* data = KStarsData::Instance();
    //Check whether we need to concatenate a split NGC/IC catalog
    //(i.e., if user has downloaded the Steinicke catalog)
    mergeSplitFiles();

    QList< QPair<QString,KSParser::DataTypes> > sequence;
    QList<int> widths;
    sequence.append(qMakePair(QString("Flag"), KSParser::D_QSTRING));
    widths.append(1);

    sequence.append(qMakePair(QString("ID"), KSParser::D_INT));
    widths.append(4);

    sequence.append(qMakePair(QString("suffix"), KSParser::D_QSTRING));
    widths.append(1);

    sequence.append(qMakePair(QString("RA_H"), KSParser::D_INT));
    widths.append(2);

    sequence.append(qMakePair(QString("RA_M"),KSParser::D_INT));
    widths.append(2);

    sequence.append(qMakePair(QString("RA_S"),KSParser::D_FLOAT));
    widths.append(4);

    sequence.append(qMakePair(QString("D_Sign"),KSParser::D_QSTRING));
    widths.append(2);

    sequence.append(qMakePair(QString("Dec_d"),KSParser::D_INT));
    widths.append(2);

    sequence.append(qMakePair(QString("Dec_m"),KSParser::D_INT));
    widths.append(2);

    sequence.append(qMakePair(QString("Dec_s"),KSParser::D_INT));
    widths.append(2);

    sequence.append(qMakePair(QString("BMag"),KSParser::D_QSTRING));
    widths.append(6);

    sequence.append(qMakePair(QString("type"),KSParser::D_INT));
    widths.append(2);

    sequence.append(qMakePair(QString("a"),KSParser::D_FLOAT));
    widths.append(6);

    sequence.append(qMakePair(QString("b"),KSParser::D_FLOAT));
    widths.append(6);

    sequence.append(qMakePair(QString("pa"),KSParser::D_QSTRING));
    widths.append(4);

    sequence.append(qMakePair(QString("PGC"),KSParser::D_INT));
    widths.append(7);

    sequence.append(qMakePair(QString("other cat"),KSParser::D_QSTRING));
    widths.append(4);

    sequence.append(qMakePair(QString("other1"),KSParser::D_QSTRING));
    widths.append(6);

    sequence.append(qMakePair(QString("other2"),KSParser::D_QSTRING));
    widths.append(6);

    sequence.append(qMakePair(QString("Messr"),KSParser::D_QSTRING));
    widths.append(2);

    sequence.append(qMakePair(QString("MessrNum"),KSParser::D_INT));
    widths.append(4);

    sequence.append(qMakePair(QString("Longname"),KSParser::D_QSTRING));
    //No width to be appended for last sequence object

    QString file_name = KSPaths::locate(QStandardPaths::GenericDataLocation, QString("ngcic.dat") );
    KSParser deep_sky_parser(file_name, '#', sequence, widths);

    deep_sky_parser.SetProgress( i18n("Loading NGC/IC objects"), 13444, 10 );
    qDebug() << "Loading NGC/IC objects";

    QHash<QString,QVariant> row_content;
    while (deep_sky_parser.HasNextRow()) {
        row_content = deep_sky_parser.ReadNextRow();

        QString iflag;
        QString cat;
        iflag = row_content["Flag"].toString().mid( 0, 1 ); //check for NGC/IC catalog flag
        /*
        Q_ASSERT(iflag == "I" || iflag == "N" || iflag == " ");
        // (spacetime): ^ Why an assert? Change in implementation of ksparser
        //  might result in crash for no reason.
        // n.b. We also allow non-NGC/IC objects which have a blank iflag
        */

        float mag(1000.0);
        int type, ingc, imess(-1), pa;
        int pgc, ugc;
        QString ss, name, name2, longname;
        QString cat2;

        // Designation
        if ( iflag == "I" ) cat = "IC";
        else if ( iflag == "N" ) cat = "NGC";

        ingc = row_content["ID"].toInt();  // NGC/IC catalog number
        if ( ingc==0 ) cat.clear(); //object is not in NGC or IC catalogs

        QString suffix = row_content["suffix"].toString(); // multipliticity suffixes, eg: the 'A' in NGC 4945A

        Q_ASSERT( suffix.isEmpty() || ( suffix.at( 0 ) >= QChar( 'A' ) && suffix.at( 0 ) <= QChar( 'Z' ) ) || (suffix.at( 0 ) >= QChar( 'a' ) && suffix.at( 0 ) <= QChar( 'z' ) ) );

        //coordinates
        int rah = row_content["RA_H"].toInt();
        int ram = row_content["RA_M"].toInt();
        float ras = row_content["RA_S"].toFloat();
        QString sgn = row_content["D_Sign"].toString();
        int dd = row_content["Dec_d"].toInt();
        int dm = row_content["Dec_m"].toInt();
        int ds = row_content["Dec_s"].toInt();

        if ( !( (0.0 <= rah && rah < 24.0) ||
             (0.0 <= ram && ram < 60.0) ||
             (0.0 <= ras && ras < 60.0) ||
             (0.0 <= dd && dd <= 90.0) ||
             (0.0 <= dm && dm < 60.0) ||
               (0.0 <= ds && ds < 60.0) ) ) {
          qDebug() << "Bad coordinates while processing NGC/IC object: " << cat << ingc;
          qDebug() << "RA H:M:S = " << rah << ":" << ram << ":" << ras << "; Dec D:M:S = " << dd << ":" << dm << ":" << ds;
          Q_ASSERT( false );
        }

        //Ignore lines with no coordinate values if not debugging
        if (rah==0 && ram==0 && ras==0)
            continue;

        //B magnitude
        ss = row_content["BMag"].toString();
        if (ss == "") { mag = 99.9f; } else { mag = ss.toFloat(); }

        //object type
        type = row_content["type"].toInt();

        //major and minor axes
        float a = row_content["a"].toFloat();
        float b = row_content["b"].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 = row_content["pa"].toString();
        if (ss == "" ) { pa = 90; } else { pa = 90 - ss.toInt(); }

        //PGC number
        pgc = row_content["PGC"].toInt();

        //UGC number
        if (row_content["other cat"].toString().trimmed() == "UGC") {
            ugc = row_content["other1"].toString().toInt();
        } else {
            ugc = 0;
        }

        //Messier number
        if ( row_content["Messr"].toString().trimmed() == "M" ) {
            cat2 = cat;
            if ( ingc == 0 ) cat2.clear();
            cat = 'M';
            imess = row_content["MessrNum"].toInt();
        }

        longname = row_content["Longname"].toString();

        dms r;
        r.setH( rah, ram, int(ras) );
        dms d( dd, dm, ds );

        if ( sgn == "-" ) { d.setD( -1.0*d.Degrees() ); }

        bool hasName = true;
        QString snum;
        if (cat=="IC" || cat=="NGC") {
            snum.setNum(ingc);
	    name = cat + ' ' + ( ( suffix.isEmpty() ) ? snum : ( snum + suffix ) );
        } else if (cat == "M") {
            snum.setNum( imess );
            name = cat + ' ' + snum; // Note: Messier has no suffixes
            if (cat2 == "NGC" || cat2 == "IC") {
                snum.setNum( ingc );
		name2 = cat2 + ' ' + ( ( suffix.isEmpty() ) ? snum : ( snum + suffix ) );
            } else {
                name2.clear();
            }
        }
        else {
            if (!longname.isEmpty()) name = longname;
            else {
                hasName = false;
                name = i18n( "Unnamed Object" );
            }
        }

        name = i18nc("object name (optional)", name.toLatin1().constData());
        if (!longname.isEmpty())
            longname = i18nc("object name (optional)", longname.toLatin1().constData());

        // 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 );
        o->EquatorialToHorizontal( data->lst(), data->geo()->lat() );

        // Add the name(s) to the nameHash for fast lookup -jbb
        if ( hasName) {
            nameHash[ name.toLower() ] = o;
            if ( ! longname.isEmpty() ) nameHash[ longname.toLower() ] = o;
            if ( ! name2.isEmpty() ) nameHash[ name2.toLower() ] = o;
        }

        Trixel trixel = m_skyMesh->index(o);

        //Assign object to general DeepSkyObjects list,
        //and a secondary list based on its catalog.
        m_DeepSkyList.append( o );
        appendIndex( o, &m_DeepSkyIndex, trixel );

        if ( o->isCatalogM()) {
            m_MessierList.append( o );
            appendIndex( o, &m_MessierIndex, trixel );
        }
        else if (o->isCatalogNGC() ) {
            m_NGCList.append( o );
            appendIndex( o, &m_NGCIndex, trixel );
        }
        else if ( o->isCatalogIC() ) {
            m_ICList.append( o );
            appendIndex( o, &m_ICIndex, trixel );
        }
        else {
            m_OtherList.append( o );
            appendIndex( o, &m_OtherIndex, trixel );
        }

        // JM: VERY INEFFICIENT. Disabling for now until we figure out how to deal with dups. QSet?
        //if ( ! name.isEmpty() && !objectNames(type).contains(name))
        if ( ! name.isEmpty() )
            objectNames(type).append( name );

        //Add long name to the list of object names
        //if ( ! longname.isEmpty() && longname != name  && !objectNames(type).contains(longname))
        if ( ! longname.isEmpty() && longname != name)
            objectNames(type).append( longname );

        deep_sky_parser.ShowProgress();
    }

    foreach(QStringList list, objectNames())
        list.removeDuplicates();
}