summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkarsh Simha <akarsh@kde.org>2016-10-01 10:15:39 (GMT)
committerAkarsh Simha <akarsh@kde.org>2016-10-01 10:17:01 (GMT)
commitb10766db6dd714337905394e4c240964381b1616 (patch)
tree1351c271e4386dc6b2f6d0d15e16b35dfd3d4dcb
parent94dc45f9511279d66f1923a2dc334b228803eeb7 (diff)
New workflow in the Observation Planner: Sort by % max. alt achieved
Adding a new workflow in the Observation Planner that helps find objects for observation without having to prepare a session plan with assigned times. 1. Add all objects that you want to observe to the Wish List 2. On the observing field, sort by the "Current Altitude" column in descending order. The column contains the percentage of the maximum altitude currently achieved by the object. The altitude uses the geographic location set in the observation planner, but _ignores_ the date field -- so it is really current in system clock time. 3. The list is automatically updated and dynamically sorted every 2 minutes, so you can always observe the objects at the top of the list. As objects rise and set, they move up/down the list. Improvements needed: 1. Support multiple wishlists, save wishlist, load wishlist etc. [ Or alternatively, move the feature to the session plan, although the session plan file format is more complicated] 2. Make the workflow more obvious (Any pointers on how to do this will be very helpful) 3. Support demotion of objects after "checking them off" 4. Have an option to demote objects that are in the Dobsonian hole. FEATURE: GUI: CCMAIL: kstars-devel@kde.org
-rw-r--r--kstars/tools/observinglist.cpp85
-rw-r--r--kstars/tools/observinglist.h10
2 files changed, 81 insertions, 14 deletions
diff --git a/kstars/tools/observinglist.cpp b/kstars/tools/observinglist.cpp
index 11b34b3..9d2b18d 100644
--- a/kstars/tools/observinglist.cpp
+++ b/kstars/tools/observinglist.cpp
@@ -144,6 +144,7 @@ ObservingList::ObservingList()
m_WishListSortModel = new QSortFilterProxyModel( this );
m_WishListSortModel->setSourceModel( m_WishListModel );
m_WishListSortModel->setDynamicSortFilter( true );
+ m_WishListSortModel->setSortRole( Qt::UserRole );
ui->WishListView->setModel( m_WishListSortModel );
ui->WishListView->horizontalHeader()->setStretchLastSection( true );
@@ -231,6 +232,28 @@ ObservingList::ObservingList()
m_NoImagePixmap = QPixmap(":/images/noimage.png").scaledToHeight(ui->ImagePreview->width());
+ m_altCostHelper = [ this ]( const SkyPoint &p ) -> QStandardItem * {
+ double inf = std::numeric_limits<double>::infinity();
+ double altCost = 0.;
+ QString itemText;
+ qDebug() << "p has Dec" << p.dec().toDMSString() << "and p.maxAlt( " << geo->lat()->toDMSString() << " ) returns " << p.maxAlt( *( geo->lat() ) );
+ if ( p.maxAlt( *( geo->lat() ) ) <= 0. ) {
+ altCost = -inf;
+ itemText = i18n( "Never rises" );
+ }
+ else {
+ altCost = ( p.alt().Degrees() / p.maxAlt( *( geo->lat() ) ) ) * 100.;
+ if ( altCost < 0 )
+ itemText = i18nc( "Short text to describe that object has not risen yet", "Not risen" );
+ else
+ itemText = QString::number( altCost, 'f', 0 ) + '%';
+ }
+
+ QStandardItem *altItem = new QStandardItem( itemText );
+ altItem->setData( altCost, Qt::UserRole );
+ return altItem;
+ };
+
slotLoadWishList(); //Load the wishlist from disk if present
m_CurrentObject = 0;
setSaveImagesButton();
@@ -240,6 +263,11 @@ ObservingList::ObservingList()
// Set up for the large-size view
bIsLarge = false;
slotToggleSize();
+
+ m_altitudeUpdater = new QTimer( this );
+ connect( m_altitudeUpdater, SIGNAL( timeout() ), this, SLOT( slotUpdateAltitudes() ) );
+ m_altitudeUpdater->start( 120000 ); // update altitudes every 2 minutes
+
}
ObservingList::~ObservingList()
@@ -302,17 +330,23 @@ void ObservingList::slotAddObject( SkyObject *obj, bool session, bool update ) {
QList<QStandardItem*> itemList;
+ auto getItemWithUserRole = [] ( const QString &itemText ) -> QStandardItem * {
+ QStandardItem *ret = new QStandardItem( itemText );
+ ret->setData( itemText, Qt::UserRole );
+ return ret;
+ };
+
// Fill itemlist with items that are common to both wishlist additions and session plan additions
- auto populateItemList = [ &itemList, &finalObjectName, &obj, &p, &smag ]() {
+ auto populateItemList = [ &getItemWithUserRole, &itemList, &finalObjectName, &obj, &p, &smag ]() {
itemList.clear();
- QStandardItem *keyItem = new QStandardItem( finalObjectName );
- keyItem->setData( QVariant::fromValue<void *>( static_cast<void *>( obj ) ), Qt::UserRole );
+ QStandardItem *keyItem = getItemWithUserRole( finalObjectName );
+ keyItem->setData( QVariant::fromValue<void *>( static_cast<void *>( obj ) ), Qt::UserRole + 1 );
itemList << keyItem // NOTE: The rest of the methods assume that the SkyObject pointer is available in the first column!
- << new QStandardItem( obj->translatedLongName() )
- << new QStandardItem( p.ra().toHMSString() )
- << new QStandardItem( p.dec().toDMSString() )
- << new QStandardItem( smag )
- << new QStandardItem( obj->typeName() );
+ << getItemWithUserRole( obj->translatedLongName() )
+ << getItemWithUserRole( p.ra().toHMSString() )
+ << getItemWithUserRole( p.dec().toDMSString() )
+ << getItemWithUserRole( smag )
+ << getItemWithUserRole( obj->typeName() );
};
//Insert object in the Wish List
@@ -326,7 +360,12 @@ void ObservingList::slotAddObject( SkyObject *obj, bool session, bool update ) {
//dec = p.dec().toDMSString();
populateItemList();
- itemList << new QStandardItem( QString::number( p.alt().Degrees(), 'f', 2 ) );
+ // FIXME: Instead sort by a "clever" observability score, calculated as follows:
+ // - First sort by (max altitude) - (current altitude) rounded off to the nearest
+ // - Weight by declination - latitude (in the northern hemisphere, southern objects get higher precedence)
+ // - Demote objects in the hole
+ SkyPoint p = obj->recomputeCoords( KStarsDateTime( QDateTime::currentDateTime() ), geo ); // Current => now
+ itemList << m_altCostHelper( p );
m_WishListModel->appendRow( itemList );
//Note addition in statusbar
@@ -357,10 +396,10 @@ void ObservingList::slotAddObject( SkyObject *obj, bool session, bool update ) {
//}
// TODO: Change the rest of the parameters to their appropriate datatypes.
populateItemList();
- itemList << new QStandardItem( KSUtils::constNameToAbbrev( KStarsData::Instance()->skyComposite()->constellationBoundary()->constellationName( obj ) ) )
+ itemList << getItemWithUserRole( KSUtils::constNameToAbbrev( KStarsData::Instance()->skyComposite()->constellationBoundary()->constellationName( obj ) ) )
<< BestTime
- << new QStandardItem( alt )
- << new QStandardItem( az );
+ << getItemWithUserRole( alt )
+ << getItemWithUserRole( az );
m_SessionModel->appendRow( itemList );
//Adding an object should trigger the modified flag
@@ -436,7 +475,7 @@ void ObservingList::slotRemoveSelectedObjects() {
QModelIndex sortIndex, index;
sortIndex = getActiveSortModel()->index( irow, 0 );
index = getActiveSortModel()->mapToSource( sortIndex );
- SkyObject *o = static_cast<SkyObject *>( index.data( Qt::UserRole ).value<void *>() );
+ SkyObject *o = static_cast<SkyObject *>( index.data( Qt::UserRole + 1 ).value<void *>() );
Q_ASSERT( o );
slotRemoveObject(o, sessionView);
}
@@ -705,7 +744,7 @@ void ObservingList::slotAVT() {
QPointer<AltVsTime> avt = new AltVsTime( KStars::Instance() );
foreach ( const QModelIndex &i, selectedItems ) {
if ( i.column() == 0 ) {
- SkyObject *o = static_cast<SkyObject *>( i.data( Qt::UserRole ).value<void *>() );
+ SkyObject *o = static_cast<SkyObject *>( i.data( Qt::UserRole + 1 ).value<void *>() );
Q_ASSERT( o );
avt->processObject( o );
}
@@ -1452,3 +1491,21 @@ QString ObservingList::getObjectName(const SkyObject *o, bool translated)
return finalObjectName;
}
+
+
+void ObservingList::slotUpdateAltitudes() {
+ // FIXME: Update upon gaining visibility, do not update when not visible
+ KStarsDateTime now( QDateTime::currentDateTime() );
+ qDebug() << "Updating altitudes in observation planner.";
+ for ( int irow = m_WishListModel->rowCount() - 1; irow >= 0; --irow ) {
+ QModelIndex idx = m_WishListSortModel->mapToSource( m_WishListSortModel->index( irow, 0 ) );
+ SkyObject *o = static_cast<SkyObject *>( idx.data( Qt::UserRole + 1 ).value<void *>() );
+ Q_ASSERT( o );
+ SkyPoint p = o->recomputeCoords( now, geo );
+ idx = m_WishListSortModel->mapToSource( m_WishListSortModel->index( irow, m_WishListSortModel->columnCount() - 1 ) );
+ QStandardItem *replacement = m_altCostHelper( p );
+ m_WishListModel->setData( idx, replacement->data( Qt::DisplayRole ), Qt::DisplayRole );
+ m_WishListModel->setData( idx, replacement->data( Qt::UserRole ), Qt::UserRole );
+ delete replacement;
+ }
+}
diff --git a/kstars/tools/observinglist.h b/kstars/tools/observinglist.h
index 6022cfa..4838816 100644
--- a/kstars/tools/observinglist.h
+++ b/kstars/tools/observinglist.h
@@ -24,10 +24,13 @@
#include <QAbstractTableModel>
#include <QDialog>
+#include <QTimer>
//#include <KIO/CopyJob>
#include "ui_observinglist.h"
+#include <functional>
+
class KSAlmanac;
class QSortFilterProxyModel;
class QStandardItemModel;
@@ -349,6 +352,11 @@ public slots:
*/
void slotEyepieceView();
+ /**
+ * @short Recalculate and update the values of the altitude in the wishlist for the current time
+ */
+ void slotUpdateAltitudes();
+
protected slots:
void slotClose();
@@ -401,6 +409,8 @@ private:
KSDssDownloader *m_dl;
QHash<SkyObject *, QPixmap> ImagePreviewHash;
QPixmap m_NoImagePixmap;
+ QTimer *m_altitudeUpdater;
+ std::function<QStandardItem *(const SkyPoint &)> m_altCostHelper;
};
#endif // OBSERVINGLIST_H_