Commit 0a7cb3af authored by Akarsh Simha's avatar Akarsh Simha

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:
parent 247a6e1d
......@@ -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)
......
......@@ -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" />
......
......@@ -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 )
{
......
......@@ -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;
......
......@@ -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();
}
......@@ -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" );
......
......@@ -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 );
......@@ -379,6 +383,14 @@ SkyObject* SkyMapComposite::objectNearest( SkyPoint *p, double &maxrad ) {
oBest = oTry;
}
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
......@@ -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()
......
......@@ -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
/***************************************************************************
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;
}
/***************************************************************************
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
<?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>