summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkarsh Simha <akarsh@kde.org>2016-08-18 09:32:10 (GMT)
committerAkarsh Simha <akarsh@kde.org>2016-08-18 09:36:31 (GMT)
commit0a7cb3af6a92f02aac27438273ea170cfba995a5 (patch)
treee45b7781e28d388f3914be44cbcac3ccfce26068
parent247a6e1dee9ddb48512c21e757f1aa69e508efb9 (diff)
Introducing a new way of adding deep-sky objects into KStars
1. Create a new SyncedCatalogComponent catalog called "_Manual_Additions". This holds manually added DSOs that were not resolved from the internet. The concept is however the same -- it is a fake catalog for such custom added objects. 2. Build a UI for the purpose of manually introducing objects into this catalog. FEATURE: CCMAIL: kstars-devel@kde.org GUI:
-rw-r--r--kstars/CMakeLists.txt2
-rw-r--r--kstars/data/kstarsui.rc1
-rw-r--r--kstars/kstars.cpp1
-rw-r--r--kstars/kstars.h6
-rw-r--r--kstars/kstarsactions.cpp9
-rw-r--r--kstars/kstarsinit.cpp4
-rw-r--r--kstars/skycomponents/skymapcomposite.cpp20
-rw-r--r--kstars/skycomponents/skymapcomposite.h3
-rw-r--r--kstars/tools/adddeepskyobject.cpp293
-rw-r--r--kstars/tools/adddeepskyobject.h80
-rw-r--r--kstars/tools/adddeepskyobject.ui163
11 files changed, 512 insertions, 70 deletions
diff --git a/kstars/CMakeLists.txt b/kstars/CMakeLists.txt
index 6ef896d..aad4fe3 100644
--- a/kstars/CMakeLists.txt
+++ b/kstars/CMakeLists.txt
@@ -205,6 +205,7 @@ set(libkstarstools_SRCS
tools/eyepiecefield.cpp
tools/exporteyepieceview.cpp
tools/starhopperdialog.cpp
+ tools/adddeepskyobject.cpp
)
if(${KF5_VERSION} VERSION_EQUAL 5.18.0 OR ${KF5_VERSION} VERSION_GREATER 5.18.0)
@@ -265,6 +266,7 @@ ki18n_wrap_ui(libkstarstools_SRCS
tools/flagmanager.ui
tools/starhopperdialog.ui
tools/horizonmanager.ui
+ tools/adddeepskyobject.ui
)
if (${KF5_VERSION} VERSION_EQUAL 5.18.0 OR ${KF5_VERSION} VERSION_GREATER 5.18.0)
diff --git a/kstars/data/kstarsui.rc b/kstars/data/kstarsui.rc
index c0821b7..153fdcb 100644
--- a/kstars/data/kstarsui.rc
+++ b/kstars/data/kstarsui.rc
@@ -87,6 +87,7 @@
<Action name="update_satellites" />
<Action name="update_supernovae" />
</Menu>
+ <Action name="manual_add_dso" />
</Menu>
<Menu name="observation" noMerge="1"><text>&amp;Observation</text>
<Action name="obslist" />
diff --git a/kstars/kstars.cpp b/kstars/kstars.cpp
index ef027f9..1c07051 100644
--- a/kstars/kstars.cpp
+++ b/kstars/kstars.cpp
@@ -66,6 +66,7 @@ KStars::KStars( bool doSplash, bool clockrun, const QString &startdate )
//#if 0
m_WIView(0), m_ObsConditions(0), m_wiDock(0),
//#endif
+ m_addDSODialog(0),
DialogIsObsolete(false), StartClockRunning( clockrun ),
StartDateString( startdate )
{
diff --git a/kstars/kstars.h b/kstars/kstars.h
index af769d2..50cb7a0 100644
--- a/kstars/kstars.h
+++ b/kstars/kstars.h
@@ -58,6 +58,7 @@ class PrintingWizard;
class EkosManager;
class HorizonManager;
class EyepieceField;
+class AddDeepSkyObject;
class OpsCatalog;
class OpsGuides;
@@ -469,6 +470,9 @@ public Q_SLOTS:
/** Show the eyepiece view tool */
void slotEyepieceView( SkyPoint *sp, const QString &imagePath = QString() );
+ /** Show the add deep-sky object dialog */
+ void slotAddDeepSkyObject();
+
private slots:
/** action slot: open a dialog for setting the time and date */
@@ -683,6 +687,8 @@ private:
EkosManager *m_EkosManager;
#endif
+ AddDeepSkyObject *m_addDSODialog;
+
// FIXME Port to QML2
//#if 0
WIView *m_WIView;
diff --git a/kstars/kstarsactions.cpp b/kstars/kstarsactions.cpp
index c984c3c..c50afe2 100644
--- a/kstars/kstarsactions.cpp
+++ b/kstars/kstarsactions.cpp
@@ -80,6 +80,7 @@
#include "tools/wutdialog.h"
#include "tools/observinglist.h"
#include "tools/eyepiecefield.h"
+#include "tools/adddeepskyobject.h"
#ifdef HAVE_KF5WIT
#include "tools/whatsinteresting/wiview.h"
@@ -1486,3 +1487,11 @@ void KStars::slotUpdateSatellites()
{
data()->skyComposite()->satellites()->updateTLEs();
}
+
+void KStars::slotAddDeepSkyObject() {
+ if( ! m_addDSODialog ) {
+ Q_ASSERT( data() && data()->skyComposite() && data()->skyComposite()->manualAdditionsComponent() );
+ m_addDSODialog = new AddDeepSkyObject( this, data()->skyComposite()->manualAdditionsComponent() );
+ }
+ m_addDSODialog->show();
+}
diff --git a/kstars/kstarsinit.cpp b/kstars/kstarsinit.cpp
index 842b6fe..06939ef 100644
--- a/kstars/kstarsinit.cpp
+++ b/kstars/kstarsinit.cpp
@@ -356,6 +356,10 @@ void KStars::initActions() {
<< i18n("Startup Wizard..." )
<< QIcon::fromTheme("tools-wizard" );
+ // Manual data entry
+ actionCollection()->addAction( "manual_add_dso", this, SLOT( slotAddDeepSkyObject() ) )
+ << i18n( "Manually add a deep-sky object" );
+
// Updates actions
actionCollection()->addAction( "update_comets", this, SLOT( slotUpdateComets() ) )
<< i18n( "Update comets orbital elements" );
diff --git a/kstars/skycomponents/skymapcomposite.cpp b/kstars/skycomponents/skymapcomposite.cpp
index 34488b8..412df2a 100644
--- a/kstars/skycomponents/skymapcomposite.cpp
+++ b/kstars/skycomponents/skymapcomposite.cpp
@@ -94,11 +94,13 @@ SkyMapComposite::SkyMapComposite(SkyComposite *parent ) :
addComponent( m_ArtificialHorizon = new ArtificialHorizonComponent(this), 110);
m_internetResolvedCat = "_Internet_Resolved";
+ m_manualAdditionsCat = "_Manual_Additions";
addComponent( m_internetResolvedComponent = new SyncedCatalogComponent( this, m_internetResolvedCat, true, 0 ), 6 );
+ addComponent( m_manualAdditionsComponent = new SyncedCatalogComponent( this, m_manualAdditionsCat, true, 0 ), 6 );
m_CustomCatalogs = new SkyComposite( this );
QStringList allcatalogs = Options::showCatalogNames();
for ( int i=0; i < allcatalogs.size(); ++ i ) {
- if( allcatalogs.at(i) == m_internetResolvedCat ) // This is a special catalog
+ if( allcatalogs.at(i) == m_internetResolvedCat || allcatalogs.at(i) == m_manualAdditionsCat ) // This is a special catalog
continue;
m_CustomCatalogs->addComponent(
new CatalogComponent( this, allcatalogs.at(i), false, i ), 6 // FIXME: Should this be 6 or 5? See SkyMapComposite::reloadDeepSky()
@@ -150,6 +152,7 @@ void SkyMapComposite::update(KSNumbers *num )
//9. Custom catalogs
m_CustomCatalogs->update( num );
m_internetResolvedComponent->update( num );
+ m_manualAdditionsComponent->update( num );
//10. Stars
//m_Stars->update( data, num );
//m_CLines->update( data, num ); // MUST follow stars.
@@ -261,6 +264,7 @@ void SkyMapComposite::draw( SkyPainter *skyp )
m_CustomCatalogs->draw( skyp );
m_internetResolvedComponent->draw( skyp );
+ m_manualAdditionsComponent->draw( skyp );
m_Stars->draw( skyp );
@@ -380,6 +384,14 @@ SkyObject* SkyMapComposite::objectNearest( SkyPoint *p, double &maxrad ) {
}
rTry = maxrad;
+ oTry = m_manualAdditionsComponent->objectNearest( p, rTry );
+ rTry *= 0.5;
+ if ( rTry < rBest ) {
+ rBest = rTry;
+ oBest = oTry;
+ }
+
+ rTry = maxrad;
oTry = m_SolarSystem->objectNearest( p, rTry );
if( !dynamic_cast<KSComet *>( oTry ) && !dynamic_cast<KSAsteroid *>( oTry ) ) { // There are gazillions of faint asteroids and comets; we want to prevent them from getting precedence
rTry *= 0.25; // this is either sun, moon, or one of the major planets or their moons.
@@ -477,6 +489,8 @@ SkyObject* SkyMapComposite::findByName( const QString &name ) {
if ( o ) return o;
o = m_internetResolvedComponent->findByName( name );
if ( o ) return o;
+ o = m_manualAdditionsComponent->findByName( name );
+ if ( o ) return o;
o = m_CNames->findByName( name );
if ( o ) return o;
o = m_Stars->findByName( name );
@@ -585,9 +599,11 @@ void SkyMapComposite::reloadDeepSky() {
m_CustomCatalogs = new SkyComposite( this );
delete m_internetResolvedComponent;
addComponent( m_internetResolvedComponent = new SyncedCatalogComponent( this, m_internetResolvedCat, true, 0 ), 6 );
+ delete m_manualAdditionsComponent;
+ addComponent( m_manualAdditionsComponent = new SyncedCatalogComponent( this, m_manualAdditionsCat, true, 0 ), 6 );
QStringList allcatalogs = Options::showCatalogNames();
for ( int i=0; i < allcatalogs.size(); ++ i ) {
- if( allcatalogs.at(i) == m_internetResolvedCat ) // This is a special catalog
+ if( allcatalogs.at(i) == m_internetResolvedCat || allcatalogs.at(i) == m_manualAdditionsCat ) // These are special catalogs
continue;
m_CustomCatalogs->addComponent(
new CatalogComponent( this, allcatalogs.at(i), false, i ), 5 // FIXME: Should this be 6 or 5? See SkyMapComposite::SkyMapComposite()
diff --git a/kstars/skycomponents/skymapcomposite.h b/kstars/skycomponents/skymapcomposite.h
index a865436..6de619e 100644
--- a/kstars/skycomponents/skymapcomposite.h
+++ b/kstars/skycomponents/skymapcomposite.h
@@ -175,6 +175,7 @@ public:
SupernovaeComponent* supernovaeComponent();
ArtificialHorizonComponent* artificialHorizon();
inline SyncedCatalogComponent* internetResolvedComponent() { return m_internetResolvedComponent; }
+ inline SyncedCatalogComponent* manualAdditionsComponent() { return m_manualAdditionsComponent; }
//Accessors for StarComponent
SkyObject* findStarByGenetiveName( const QString name );
@@ -231,6 +232,7 @@ private:
SatellitesComponent *m_Satellites;
SupernovaeComponent *m_Supernovae;
SyncedCatalogComponent *m_internetResolvedComponent;
+ SyncedCatalogComponent *m_manualAdditionsComponent;
SkyMesh* m_skyMesh;
SkyLabeler* m_skyLabeler;
@@ -243,6 +245,7 @@ private:
QHash<int, QStringList> m_ObjectNames;
QHash<QString, QString> m_ConstellationNames;
QString m_internetResolvedCat; // Holds the name of the internet resolved catalog
+ QString m_manualAdditionsCat;
};
#endif
diff --git a/kstars/tools/adddeepskyobject.cpp b/kstars/tools/adddeepskyobject.cpp
new file mode 100644
index 0000000..5b7bef4
--- /dev/null
+++ b/kstars/tools/adddeepskyobject.cpp
@@ -0,0 +1,293 @@
+/***************************************************************************
+ adddeepskyobject.cpp - K Desktop Planetarium
+ -------------------
+ begin : Wed 17 Aug 2016 20:22:58 CDT
+ copyright : (c) 2016 by Akarsh Simha
+ email : akarsh.simha@kdemail.net
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+/* Project Includes */
+#include "adddeepskyobject.h"
+
+/* KDE Includes */
+#include <KMessageBox>
+
+/* Qt Includes */
+#include <QInputDialog>
+
+AddDeepSkyObject::AddDeepSkyObject( QWidget *parent, SyncedCatalogComponent *catalog ) :
+ QDialog( parent ), m_catalog( catalog ), ui( new Ui::AddDeepSkyObject ) {
+ Q_ASSERT( catalog );
+ ui->setupUi( this );
+
+ // Set up various things in the dialog so it is ready to be shown
+ for( int k = 0; k < SkyObject::NUMBER_OF_KNOWN_TYPES; ++k ) {
+ ui->typeComboBox->addItem( SkyObject::typeName( k ) );
+ }
+
+ ui->typeComboBox->addItem( SkyObject::typeName( SkyObject::TYPE_UNKNOWN ) );
+ ui->catalogNameEdit->setEnabled( false );
+ ui->catalogNameEdit->setText( catalog->name() );
+
+ resetView();
+
+ // Connections
+ // connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
+ connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(slotOk()));
+ QAbstractButton *resetButton = ui->buttonBox->button( QDialogButtonBox::Reset );
+ connect( resetButton, SIGNAL( clicked() ), this, SLOT( resetView() ) );
+ connect( ui->fillFromTextButton, SIGNAL( clicked() ), this, SLOT( slotFillFromText() ) );
+
+ // Show the UI
+ show();
+}
+
+AddDeepSkyObject::~AddDeepSkyObject() {
+ delete ui;
+}
+
+void AddDeepSkyObject::fillFromText( const QString &text ) {
+ // Parse text to fill in the options
+
+ // TODO: Add code to match and guess object type, to match blue magnitude.
+
+ QRegularExpression matchJ2000Line( "^(.*)(?:J2000|ICRS|FK5|\\(2000(?:\\.0)?\\))(.*)$" );
+ matchJ2000Line.setPatternOptions( QRegularExpression::MultilineOption );
+ QRegularExpression matchCoords( "(?:^|[^-\\d])([-+]?\\d\\d?)(?:h ?|[^\\d]?° ?|:| +)(\\d\\d)(?:m ?|\' ?|:| +)(\\d\\d(?:\\.\\d+)?)(?:s|\"|\'\')?\\b" );
+ QRegularExpression findMag1( "(?:[mM]ag(?:nitudes?)?|V(?=\\b))(?:\\s*=|:)?\\s*(-?\\d{1,2}(?:\\.\\d{1,3})?)" );
+ QRegularExpression findMag2( "\\b-?\\d{1,2}(\\.\\d{1,3})?\\s*[mM]ag\\b");
+ QRegularExpression findSize1( "\\b(\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\s*[xX×]\\s*(\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\b" );
+ QRegularExpression findSize2( "\\b(?:[Ss]ize|[Dd]imensions?|[Dd]iameter)[: ](\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\b" );
+ QRegularExpression findMajorAxis( "\\b[Mm]ajor\\s*[Aa]xis:?\\s*(\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\b" );
+ QRegularExpression findMinorAxis( "\\b[Mm]inor\\s*[Aa]xis:?\\s*(\\d{1,3}(?:\\.\\d{1,2})?)\\s*(°|\'|\"|\'\')?\\b" );
+ QRegularExpression findPA( "\\b(?:[Pp]osition *[Aa]ngle|PA|[pP]\\.[aA]\\.):?\\s*(\\d{1,3}(\\.\\d{1,2})?)(?:°|[Ddeg])?\\b" );
+ QRegularExpression findName1( "\\b(?:[nN]ames?[: ]|[iI]dent(?:ifier)?:|[dD]esignation:)\\s*\"?([-+\'A-Za-z0-9 ]*)\"?\\b" );
+ QStringList catalogNames;
+ catalogNames << "NGC" << "IC" << "M" << "PGC" << "UGC" << "MCG" << "ESO" << "SDSS" << "LEDA"
+ << "IRAS" << "PNG" << "Abell" << "ACO" << "HCG" << "CGCG" << "[IV]+Zw" << "Hickson"
+ << "AGC" << "2MASS" << "RCS2" << "Terzan" << "PN [A-Z0-9]" << "VV" << "PK" << "GSC2"
+ << "LBN" << "LDN" << "Caldwell" << "HIP" << "AM" << "vdB" << "B" << "Shk";
+ QRegularExpression findName2( "\\b(" + catalogNames.join( "|" ) + ")\\s+(J?[-+0-9\\.]+[A-Da-h]?)\\b" );
+ QRegularExpression findName3( "\\b([A-Za-z]+[0-9]?)\\s+(J?[-+0-9]+[A-Da-h]?)\\b" );
+
+ QString coordText = QString();
+ bool coordsFound = false, magFound = false, sizeFound = false, nameFound = false, positionAngleFound = false;
+ dms RA, Dec;
+ float mag = NaN::f;
+ float majorAxis = NaN::f;
+ float minorAxis = NaN::f;
+ float positionAngle = 0;
+ QString name;
+ QRegularExpressionMatch rmatch;
+ if ( countNonOverlappingMatches( text, matchCoords ) == 2 ) {
+ coordText = text;
+ }
+ else if ( countNonOverlappingMatches( text, matchCoords ) > 2 ) {
+ qDebug() << "Found more than 2 coordinate matches. Trying to match J2000 line.";
+ if ( text.indexOf( matchJ2000Line, 0, &rmatch ) >= 0 ) {
+ coordText = rmatch.captured( 1 ) + rmatch.captured( 2 );
+ qDebug() << "Found a J2000 line match: " << coordText;
+ if ( countNonOverlappingMatches( coordText, matchCoords ) != 2 )
+ coordText = QString(); // Give up
+ }
+ }
+ if ( !coordText.isEmpty() ) {
+ int coord1 = coordText.indexOf( matchCoords, 0, &rmatch );
+ Q_ASSERT( coord1 >= 0 );
+ RA = dms( rmatch.captured( 1 ) + ' ' + rmatch.captured( 2 ) + ' ' + rmatch.captured( 3 ), false );
+ int coord2 = coordText.indexOf( matchCoords, coord1 + rmatch.captured( 0 ).length(), &rmatch );
+ Q_ASSERT( coord2 >= 0 );
+ Dec = dms( rmatch.captured( 1 ) + ' ' + rmatch.captured( 2 ) + ' ' + rmatch.captured( 3 ), true );
+ qDebug() << "Extracted coordinates: " << RA.toHMSString() << " " << Dec.toDMSString();
+ coordsFound = true;
+ }
+ else {
+ QStringList matches;
+ qDebug() << "Could not extract RA/Dec. Found " << countNonOverlappingMatches( text, matchCoords, &matches ) << " coordinate matches:";
+ qDebug() << matches;
+ }
+
+ nameFound = true;
+ if ( text.contains( findName1, &rmatch ) ) { // Explicit name search
+ qDebug() << "Found explicit name field: " << rmatch.captured( 1 ) << " in text " << rmatch.captured( 0 );
+ name = rmatch.captured( 1 );
+ }
+ else if ( text.contains( findName2, &rmatch ) ) {
+ qDebug() << "Found known catalog field: " << ( name = rmatch.captured( 1 ) + ' ' + rmatch.captured( 2 ) ) << " in text " << rmatch.captured( 0 );
+ }
+ else if ( text.contains( findName3, &rmatch ) ) {
+ qDebug() << "Found something that looks like a catalog designation: " << ( name = rmatch.captured( 1 ) + ' ' + rmatch.captured( 2 ) ) << " in text " << rmatch.captured( 0 );
+ }
+ else {
+ qDebug() << "Could not find name.";
+ nameFound = false;
+ }
+
+ magFound = true;
+ if ( text.contains( findMag1, &rmatch ) ) {
+ qDebug() << "Found magnitude: " << rmatch.captured( 1 ) << " in text " << rmatch.captured( 0 );
+ mag = rmatch.captured( 1 ).toFloat();
+ }
+ else if ( text.contains( findMag2, &rmatch ) ) {
+ qDebug() << "Found magnitude: " << rmatch.captured( 1 ) << " in text " << rmatch.captured( 0 );
+ mag = rmatch.captured( 1 ).toFloat();
+ }
+ else {
+ qDebug() << "Could not find magnitude.";
+ magFound = false;
+ }
+
+ sizeFound = true;
+ if ( text.contains( findSize1, &rmatch ) ) {
+ qDebug() << "Found size: " << rmatch.captured( 1 ) << " x " << rmatch.captured( 3 ) << " with units " << rmatch.captured( 4 ) << " in text " << rmatch.captured( 0 );
+ majorAxis = rmatch.captured( 1 ).toFloat();
+ QString unitText2;
+ if ( rmatch.captured( 2 ).isEmpty() ) {
+ unitText2 = rmatch.captured( 4 );
+ }
+ else {
+ unitText2 = rmatch.captured( 2 );
+ }
+
+ if ( unitText2.contains( "°" ) )
+ majorAxis *= 60;
+ else if ( unitText2.contains( "\"" ) || unitText2.contains( "\'\'" ) )
+ majorAxis /= 60;
+
+ minorAxis = rmatch.captured( 3 ).toFloat();
+ if ( rmatch.captured( 4 ).contains( "°" ) )
+ minorAxis *= 60;
+ else if ( rmatch.captured( 4 ).contains( "\"" ) || rmatch.captured( 4 ).contains( "\'\'" ) )
+ minorAxis /= 60;
+ qDebug() << "Major axis = " << majorAxis << "; minor axis = " << minorAxis << " in arcmin";
+ }
+ else if ( text.contains( findSize2, &rmatch ) ) {
+ majorAxis = rmatch.captured( 1 ).toFloat();
+ if ( rmatch.captured( 2 ).contains( "°" ) )
+ majorAxis *= 60;
+ else if ( rmatch.captured( 2 ).contains( "\"" ) || rmatch.captured( 2 ).contains( "\'\'" ) )
+ majorAxis /= 60;
+ minorAxis = majorAxis;
+ }
+ else if ( text.contains( findMajorAxis, &rmatch ) ) {
+ majorAxis = rmatch.captured( 1 ).toFloat();
+ if ( rmatch.captured( 2 ).contains( "°" ) )
+ majorAxis *= 60;
+ else if ( rmatch.captured( 2 ).contains( "\"" ) || rmatch.captured( 2 ).contains( "\'\'" ) )
+ majorAxis /= 60;
+ minorAxis = majorAxis;
+ if ( text.contains( findMinorAxis, &rmatch ) ) {
+ minorAxis = rmatch.captured( 1 ).toFloat();
+ if ( rmatch.captured( 2 ).contains( "°" ) )
+ minorAxis *= 60;
+ else if ( rmatch.captured( 2 ).contains( "\"" ) || rmatch.captured( 2 ).contains( "\'\'" ) )
+ minorAxis /= 60;
+ }
+ }
+
+
+ else {
+ qDebug() << "Could not find size."; // FIXME: Improve to include separate major and minor axis matches, and size matches for round objects.
+ sizeFound = false;
+ }
+
+ positionAngleFound = true;
+ if ( text.contains( findPA, &rmatch ) ) {
+ qDebug() << "Found position angle: " << rmatch.captured( 1 ) << " in text " << rmatch.captured( 0 );
+ positionAngle = rmatch.captured( 1 ).toFloat();
+ }
+ else {
+ qDebug() << "Could not find position angle.";
+ positionAngleFound = false;
+ }
+
+ if ( nameFound )
+ ui->longNameEdit->setText( name );
+ if ( magFound )
+ ui->visualMagnitudeInput->setValue( mag ); // Improve band identification (V vs. B)
+ if ( coordsFound ) {
+ ui->raInput->setDMS( RA.toHMSString() );
+ ui->decInput->setDMS( Dec.toDMSString() );
+ }
+ if ( positionAngleFound )
+ ui->positionAngleInput->setValue( positionAngle );
+ if ( sizeFound ) {
+ ui->majorAxisInput->setValue( majorAxis );
+ ui->minorAxisInput->setValue( minorAxis );
+ }
+}
+
+void AddDeepSkyObject::resetView() {
+ ui->actualTypeDisplay->setText( SkyObject::typeName( SkyObject::TYPE_UNKNOWN ) );
+ ui->catalogIDInput->setValue( m_catalog->objectList().count() );
+ ui->blueMagnitudeInput->setValue( 99.99 );
+ ui->visualMagnitudeInput->setValue( 99.99 );
+ ui->typeComboBox->setCurrentIndex( ui->typeComboBox->count() - 1 );
+ ui->majorAxisInput->setValue( 0.0 );
+ ui->minorAxisInput->setValue( 0.0 );
+ ui->positionAngleInput->setValue( 0.0 );
+ ui->longNameEdit->setText( QString() );
+ ui->raInput->setDMS( QString() );
+ ui->decInput->setDMS( QString() );
+}
+
+bool AddDeepSkyObject::slotOk() {
+ // Formulate a CatalogEntryData object
+ CatalogEntryData centry;
+ bool ok;
+
+ centry.magnitude = ui->visualMagnitudeInput->value();
+ centry.flux = ui->blueMagnitudeInput->value();
+ centry.ra = ui->raInput->createDms( false, &ok ).Degrees();
+ centry.dec = ui->decInput->createDms( true, &ok ).Degrees();
+ centry.major_axis = ui->majorAxisInput->value();
+ centry.minor_axis = ui->minorAxisInput->value();
+ centry.long_name = ui->longNameEdit->text();
+ centry.type = ui->typeComboBox->currentIndex();
+ centry.position_angle = ui->positionAngleInput->value();
+ if( centry.type == ui->typeComboBox->count() - 1 )
+ centry.type = SkyObject::TYPE_UNKNOWN;
+
+ // Insert it into the catalog
+ bool success = m_catalog->addObject( centry );
+
+ if( !success ) {
+ // Display error message
+ KMessageBox::sorry( 0, i18n( "Could not add deep-sky object. See console for error message!" ), i18n( "Add deep-sky object" ) );
+ }
+ // Accept the dialog
+
+ return success;
+}
+
+void AddDeepSkyObject::slotFillFromText() {
+ bool ok = false;
+ QString text = QInputDialog::getMultiLineText( this, i18n( "Add deep-sky object : enter text" ),
+ i18n( "Enter the data to guess parameters from:" ), QString(), &ok );
+ if ( ok )
+ fillFromText( text );
+}
+
+int AddDeepSkyObject::countNonOverlappingMatches( const QString &string, const QRegularExpression &regExp, QStringList *list ) {
+ int count = 0;
+ int matchIndex = -1;
+ int lastMatchLength = 1;
+ QRegularExpressionMatch rmatch;
+ while ( ( matchIndex = string.indexOf( regExp, matchIndex + lastMatchLength, &rmatch ) ) >= 0 ) {
+ ++count;
+ lastMatchLength = rmatch.captured( 0 ).length();
+ if ( list )
+ list->append( rmatch.captured( 0 ) );
+ }
+ return count;
+}
diff --git a/kstars/tools/adddeepskyobject.h b/kstars/tools/adddeepskyobject.h
new file mode 100644
index 0000000..fa0ceec
--- /dev/null
+++ b/kstars/tools/adddeepskyobject.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+ adddeepskyobject.h - K Desktop Planetarium
+ -------------------
+ begin : Wed 17 Aug 2016 20:23:05 CDT
+ copyright : (c) 2016 by Akarsh Simha
+ email : akarsh.simha@kdemail.net
+***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+
+#ifndef ADDDEEPSKYOBJECT_H
+#define ADDDEEPSKYOBJECT_H
+
+#include "ui_adddeepskyobject.h"
+#include "syncedcatalogcomponent.h"
+#include <QString>
+#include <QRegularExpression>
+
+/**
+ * @class AddDeepSkyObject
+ * @short Allows the user to add an object to a @sa SyncedCatalogComponent
+ * @author Akarsh Simha <akarsh@kde.org>
+ */
+
+class AddDeepSkyObject : public QDialog, public Ui::AddDeepSkyObject {
+
+ Q_OBJECT;
+
+ public:
+
+ /**
+ * @short Constructor
+ */
+ AddDeepSkyObject( QWidget *parent, SyncedCatalogComponent *catalog );
+
+ /**
+ * @short Destructor
+ */
+ ~AddDeepSkyObject();
+
+ /**
+ * @short Fills the dialog from a text by trying to guess fields
+ */
+ void fillFromText( const QString &text );
+
+ public slots:
+
+ /**
+ * @short Accept the dialog and add the entry to the catalog
+ */
+ bool slotOk();
+
+ /**
+ * @short Resets the entries in the dialog
+ */
+ void resetView();
+
+ /**
+ * @short Gathers the text and calls fillFromText() to parse the text
+ */
+ void slotFillFromText();
+
+ private:
+
+ int countNonOverlappingMatches( const QString &string, const QRegularExpression &regExp, QStringList *list = 0 );
+
+ SyncedCatalogComponent *m_catalog;
+ Ui::AddDeepSkyObject *ui;
+};
+
+#endif
diff --git a/kstars/tools/adddeepskyobject.ui b/kstars/tools/adddeepskyobject.ui
index 64fee79..3e8705a 100644
--- a/kstars/tools/adddeepskyobject.ui
+++ b/kstars/tools/adddeepskyobject.ui
@@ -1,41 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>Dialog</class>
- <widget class="QDialog" name="Dialog">
+ <class>AddDeepSkyObject</class>
+ <widget class="QDialog" name="AddDeepSkyObject">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>708</width>
- <height>468</height>
+ <width>703</width>
+ <height>470</height>
</rect>
</property>
<property name="windowTitle">
<string>Add/Edit Deep Sky Object</string>
</property>
- <widget class="QDialogButtonBox" name="buttonBox">
- <property name="geometry">
- <rect>
- <x>350</x>
- <y>430</y>
- <width>341</width>
- <height>32</height>
- </rect>
- </property>
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="standardButtons">
- <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
- </property>
- </widget>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>681</width>
- <height>150</height>
+ <height>115</height>
</rect>
</property>
<property name="sizePolicy">
@@ -47,7 +31,7 @@
<property name="minimumSize">
<size>
<width>0</width>
- <height>150</height>
+ <height>115</height>
</size>
</property>
<property name="title">
@@ -63,19 +47,6 @@
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
- <item row="1" column="3">
- <widget class="QComboBox" name="catalogComboBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="editable">
- <bool>true</bool>
- </property>
- </widget>
- </item>
<item row="3" column="3" colspan="3">
<widget class="QLineEdit" name="longNameEdit"/>
</item>
@@ -88,7 +59,7 @@
</sizepolicy>
</property>
<property name="text">
- <string>Numeric ID*:</string>
+ <string>Numeric ID:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@@ -113,11 +84,17 @@
</item>
<item row="1" column="5">
<widget class="QSpinBox" name="catalogIDInput">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="minimum">
+ <number>-1</number>
+ </property>
<property name="maximum">
<number>99999999</number>
</property>
<property name="value">
- <number>1</number>
+ <number>-1</number>
</property>
</widget>
</item>
@@ -150,36 +127,33 @@
</property>
</widget>
</item>
+ <item row="1" column="3">
+ <widget class="QLineEdit" name="catalogNameEdit">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
- <widget class="QLabel" name="label_4">
- <property name="geometry">
- <rect>
- <x>20</x>
- <y>100</y>
- <width>631</width>
- <height>41</height>
- </rect>
- </property>
- <property name="text">
- <string>*As of this version the primary designation necessarily has to have a catalog and a unique numeric ID with no suffix. As a workaround when needed, consider using alternate designations, or create fake catalogs of miscellaneous objects, and use the long name to include the designation of your choice.</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
</widget>
<widget class="QGroupBox" name="groupBox_2">
<property name="geometry">
<rect>
<x>10</x>
- <y>170</y>
+ <y>130</y>
<width>461</width>
- <height>91</height>
+ <height>111</height>
</rect>
</property>
<property name="title">
- <string>Coordinates (J2000)</string>
+ <string>Coordinates (J2000 / ICRS)</string>
</property>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
@@ -205,7 +179,7 @@
</widget>
</item>
<item>
- <widget class="dmsBox" name="raInput" native="true"/>
+ <widget class="dmsBox" name="raInput"/>
</item>
<item>
<widget class="QLabel" name="label_6">
@@ -224,7 +198,7 @@
</widget>
</item>
<item>
- <widget class="dmsBox" name="decInput" native="true"/>
+ <widget class="dmsBox" name="decInput"/>
</item>
</layout>
</widget>
@@ -233,7 +207,7 @@
<property name="geometry">
<rect>
<x>310</x>
- <y>270</y>
+ <y>250</y>
<width>381</width>
<height>101</height>
</rect>
@@ -247,7 +221,7 @@
<x>20</x>
<y>30</y>
<width>341</width>
- <height>61</height>
+ <height>70</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
@@ -342,9 +316,9 @@
<property name="geometry">
<rect>
<x>480</x>
- <y>170</y>
+ <y>130</y>
<width>211</width>
- <height>91</height>
+ <height>111</height>
</rect>
</property>
<property name="title">
@@ -413,7 +387,7 @@
<property name="geometry">
<rect>
<x>10</x>
- <y>270</y>
+ <y>250</y>
<width>291</width>
<height>101</height>
</rect>
@@ -427,7 +401,7 @@
<x>20</x>
<y>30</y>
<width>251</width>
- <height>61</height>
+ <height>68</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout_2">
@@ -472,7 +446,7 @@
<property name="geometry">
<rect>
<x>10</x>
- <y>380</y>
+ <y>360</y>
<width>681</width>
<height>31</height>
</rect>
@@ -488,7 +462,7 @@
<property name="geometry">
<rect>
<x>10</x>
- <y>410</y>
+ <y>400</y>
<width>681</width>
<height>16</height>
</rect>
@@ -497,13 +471,66 @@
<string>** Major and minor axes are in arcminutes, position angle is in degrees.</string>
</property>
</widget>
+ <widget class="QWidget" name="horizontalLayoutWidget_3">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>420</y>
+ <width>681</width>
+ <height>41</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QPushButton" name="fillFromTextButton">
+ <property name="text">
+ <string>Guess from &amp;Text</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
+ </property>
+ <property name="centerButtons">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>dmsBox</class>
+ <extends>QLineEdit</extends>
+ <header>widgets/dmsbox.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
- <receiver>Dialog</receiver>
+ <receiver>AddDeepSkyObject</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
@@ -519,7 +546,7 @@
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
- <receiver>Dialog</receiver>
+ <receiver>AddDeepSkyObject</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">