Index: datahandlers/catalogdb.h =================================================================== --- datahandlers/catalogdb.h +++ datahandlers/catalogdb.h @@ -152,6 +152,15 @@ **/ bool AddEntry(const CatalogEntryData &catalog_entry, int catid); + /** + * @brief Remove an entry from the database + * + * @note This public method opens and closes the database. + * + * @param entry_long_name Long name of the entry + **/ + bool RemoveCustomEntry(const QString &entry_long_name); + /** * @brief Returns database ID of the required catalog. * Returns -1 if not found. Index: datahandlers/catalogdb.cpp =================================================================== --- datahandlers/catalogdb.cpp +++ datahandlers/catalogdb.cpp @@ -397,6 +397,29 @@ return retVal; } +bool CatalogDB::RemoveCustomEntry(const QString &entry_long_name) +{ + if (!skydb_.open()) + { + qCWarning(KSTARS_CATALOG) << "Failed to open database to remove catalog entry!"; + qCWarning(KSTARS_CATALOG) << LastError(); + return false; + } + QSqlQuery remove_od(skydb_); + + remove_od.prepare("DELETE FROM ObjectDesignation WHERE LongName = :long_name;"); + remove_od.bindValue(":long_name", entry_long_name); + if (!remove_od.exec()) + { + qWarning() << "Query exec failed:"; + qWarning() << remove_od.lastQuery(); + qWarning() << skydb_.lastError(); + return false; + } + skydb_.close(); + return true; +} + QString CatalogDB::GetCatalogName(const QString &fname) { QDir::setCurrent(QDir::homePath()); // for files with relative path Index: kstars/auxiliary/skyobjectlistmodel.h =================================================================== --- kstars/auxiliary/skyobjectlistmodel.h +++ kstars/auxiliary/skyobjectlistmodel.h @@ -14,15 +14,15 @@ * * ***************************************************************************/ -#ifndef SKYOBJECTLISTMODEL_H_ -#define SKYOBJECTLISTMODEL_H_ +#pragma once #include #include class SkyObject; -/** @class SkyObjectListModel +/** + * @class SkyObjectListModel * A model used in Find Object Dialog in QML. Each entry is a QString (name of object) and pointer to * SkyObject itself * @@ -47,22 +47,23 @@ QHash roleNames() const override; /** - * @return index of object from skyObjects with name objectName. -1 if object with such - * name was not found - */ - int indexOf(QString objectName) const; + * @return index of object from skyObjects with name objectName. -1 if object with such + * name was not found + */ + int indexOf(const QString &objectName) const; /** - * @short filter - * @param regEx - * @return - */ - QStringList filter(QRegExp regEx); + * @short Filter the model + * @param regEx Regex + * @return Filtered string list + */ + QStringList filter(const QRegExp ®Ex); void setSkyObjectsList(QVector> sObjects); + public slots: + void removeSkyObject(SkyObject *object); + private: QVector> skyObjects; }; - -#endif Index: kstars/auxiliary/skyobjectlistmodel.cpp =================================================================== --- kstars/auxiliary/skyobjectlistmodel.cpp +++ kstars/auxiliary/skyobjectlistmodel.cpp @@ -25,12 +25,13 @@ QHash SkyObjectListModel::roleNames() const { QHash roles; + roles[Qt::DisplayRole] = "name"; roles[SkyObjectRole] = "skyobject"; return roles; } -int SkyObjectListModel::indexOf(QString objectName) const +int SkyObjectListModel::indexOf(const QString &objectName) const { for (int i = 0; i < skyObjects.size(); ++i) { @@ -59,7 +60,7 @@ return QVariant(); } -QStringList SkyObjectListModel::filter(QRegExp regEx) +QStringList SkyObjectListModel::filter(const QRegExp ®Ex) { QStringList filteredList; @@ -79,3 +80,15 @@ skyObjects = sObjects; endResetModel(); } + +void SkyObjectListModel::removeSkyObject(SkyObject *object) +{ + for (int i = 0; i < skyObjects.size(); ++i) + { + if (skyObjects[i].second == object) + { + skyObjects.remove(i); + return; + } + } +} Index: kstars/dialogs/finddialog.cpp =================================================================== --- kstars/dialogs/finddialog.cpp +++ kstars/dialogs/finddialog.cpp @@ -87,7 +87,8 @@ ui->FilterType->setCurrentIndex(0); // show all types of objects - fModel = new SkyObjectListModel(this); + fModel = new SkyObjectListModel(this); + connect(KStars::Instance()->map(), &SkyMap::removeSkyObject, fModel, &SkyObjectListModel::removeSkyObject); sortModel = new QSortFilterProxyModel(ui->SearchList); sortModel->setFilterCaseSensitivity(Qt::CaseInsensitive); sortModel->setSourceModel(fModel); Index: kstars/kspopupmenu.cpp =================================================================== --- kstars/kspopupmenu.cpp +++ kstars/kspopupmenu.cpp @@ -22,6 +22,7 @@ #include "kstars.h" #include "kstarsdata.h" #include "skymap.h" +#include "syncedcatalogcomponent.h" #include "skyobjects/skyobject.h" #include "skyobjects/starobject.h" #include "skyobjects/trailobject.h" @@ -500,6 +501,12 @@ addMenu(imageLinkSubMenu); } + // Look for a custom object + if (KStarsData::Instance()->skyComposite()->internetResolvedComponent()->hasObject(*obj)) + { + addAction(i18n("Remove From Local Catalog"), ks->map(), SLOT(slotRemoveCustomObject())); + } + if (showDSS) { addAction(i18nc("Sloan Digital Sky Survey", "Show SDSS Image"), ks->map(), SLOT(slotSDSS())); Index: kstars/skycomponents/skycomponent.h =================================================================== --- kstars/skycomponents/skycomponent.h +++ kstars/skycomponents/skycomponent.h @@ -195,7 +195,6 @@ inline QVector> &objectLists(int type) { return getObjectLists()[type]; } - protected: void removeFromNames(const SkyObject *obj); void removeFromLists(const SkyObject *obj); Index: kstars/skycomponents/syncedcatalogcomponent.h =================================================================== --- kstars/skycomponents/syncedcatalogcomponent.h +++ kstars/skycomponents/syncedcatalogcomponent.h @@ -15,14 +15,14 @@ * * ***************************************************************************/ -#ifndef SYNCEDCATALOGCOMPONENT_H -#define SYNCEDCATALOGCOMPONENT_H +#pragma once #include "catalogcomponent.h" #include "catalogentrydata.h" class DeepSkyObject; class SkyComposite; + /** * @class SyncedCatalogComponent * @@ -36,23 +36,44 @@ { public: /** - * @short Constructor - */ + * @short Constructor + * + * @param parent Parent item + * @param catname Catalog name + * @param showerrs Show errors + * @param index Index + */ SyncedCatalogComponent(SkyComposite *parent, const QString &catname, bool showerrs, int index); // virtual void draw( SkyPainter *skyp ); /** - * @short Create and insert a SkyObject from the given CatalogEntryData - * @return 0 upon failure, a valid SkyObject pointer otherwise. - */ + * @short Create and insert a SkyObject from the given CatalogEntryData + * + * @return 0 upon failure, a valid SkyObject pointer otherwise. + */ DeepSkyObject *addObject(CatalogEntryData catalogEntry); /** - * @short Edit an existing skyobject - * @note Will implement when required. - * @note Question: How do we match the object? Probably by internal catalog id. - */ + * @short Whether an object is in the database + * + * @return True if the object is in this database otherwise false. + */ + bool hasObject(SkyObject &object); + + /** + * @short Remove an object from the database + * + * @return True if the object is removed otherwise false. + */ + bool removeObject(SkyObject &object); + + /** + * @short Edit an existing skyobject + * + * @note Will implement when required. + * @note Question: How do we match the object? Probably by internal catalog id. + */ // bool editObject( SkyObject *object ); void loadData() override { _loadData(false); } @@ -60,8 +81,6 @@ // virtual bool selected(); private: - int m_catId; - int m_catCount; + int m_catId { 0 }; + int m_catCount { 0 }; }; - -#endif Index: kstars/skycomponents/syncedcatalogcomponent.cpp =================================================================== --- kstars/skycomponents/syncedcatalogcomponent.cpp +++ kstars/skycomponents/syncedcatalogcomponent.cpp @@ -17,10 +17,12 @@ /* Project Includes */ #include "syncedcatalogcomponent.h" -#include "kstarsdata.h" + +#include "catalogdata.h" #include "deepskyobject.h" +#include "kstarsdata.h" #include "Options.h" -#include "catalogdata.h" +#include "tools/nameresolver.h" /* KDE Includes */ @@ -95,7 +97,7 @@ this); // FIXME: What about stars? Are they treated as DeepSkyObjects, type CATALOG_STAR? -- asimha Q_ASSERT(newObj); - qDebug() << "Created new DSO for " << catalogEntry.long_name; + qDebug() << "Created new DSO for " << catalogEntry.long_name << " - type: " << newObj->type(); if (newObj->hasLongName()) { // newObj->setName( newObj->longname() ); @@ -113,3 +115,53 @@ << m_ObjectList.count() << " objects."; return newObj; } + +bool SyncedCatalogComponent::hasObject(SkyObject &object) +{ + if (object.hasLongName()) + { + if (objectNames()[object.type()].contains(object.longname())) + return true; + } else + if (objectNames()[object.type()].contains(object.name())) + { + return true; + } + return false; +} + +bool SyncedCatalogComponent::removeObject(SkyObject &object) +{ + QString name; + + if (object.hasLongName()) + { + name = object.longname(); + } else { + name = object.name(); + } + if (objectNames()[object.type()].contains(name)) + { + objectNames()[object.type()].removeAll(name); + objectLists()[object.type()].removeAll(QPair(name, &object)); + } else { + qWarning() << "Can't find SkyObject " << name << " in the synced catalog " << m_catName; + return false; + } + m_ObjectList.removeAll(&object); + qDebug() << "Remove SkyObject " << name << " from synced catalog " << m_catName; + // Remove the catalog entry + CatalogEntryData cedata = NameResolver::resolveName(name); + + if (!std::isnan(cedata.ra) && !std::isnan(cedata.dec)) + { + CatalogDB *db = KStarsData::Instance()->catalogdb(); + + if (!db->RemoveCustomEntry(name)) + { + qWarning() << "Can't find SkyObject " << name << " in the CatalogDB"; + return false; + } + } + return true; +} Index: kstars/skymap.h =================================================================== --- kstars/skymap.h +++ kstars/skymap.h @@ -387,6 +387,9 @@ */ void slotRemoveObjectLabel(); + /** Remove custom object from internet search in the local catalog */ + void slotRemoveCustomObject(); + /** @short Add a Planet Trail to ClickedObject. * @note Trails are added simply by calling KSPlanetBase::addToTrail() to add the first point. * as long as the trail is not empty, new points will be automatically appended to it. @@ -502,6 +505,9 @@ /** Emitted when a position is clicked */ void objectClicked(SkyObject *); + /** Emitted when a sky object is removed from the database */ + void removeSkyObject(SkyObject *object); + protected: /** Process keystrokes: * @li arrow keys Slew the map Index: kstars/skymap.cpp =================================================================== --- kstars/skymap.cpp +++ kstars/skymap.cpp @@ -20,8 +20,8 @@ #endif #include "skymap.h" -#include "ksasteroid.h" +#include "ksasteroid.h" #include "kstars_debug.h" #include "fov.h" #include "imageviewer.h" @@ -38,6 +38,7 @@ #include "skymapqdraw.h" #include "starhopperdialog.h" #include "starobject.h" +#include "syncedcatalogcomponent.h" #include "texturemanager.h" #include "dialogs/detaildialog.h" #include "printing/printingwizard.h" @@ -788,6 +789,18 @@ forceUpdate(); } +void SkyMap::slotRemoveCustomObject() +{ + SkyObject* object = clickedObject(); + + // The object must be removed from the catalog... + data->skyComposite()->internetResolvedComponent()->removeObject(*object); + // ...and then in the rest of the places. + emit removeSkyObject(object); + data->skyComposite()->removeFromNames(object); + data->skyComposite()->removeFromLists(object); +} + void SkyMap::slotAddObjectLabel() { data->skyComposite()->addNameLabel(clickedObject());