[kstars] kstars/tools: New workflow in the Observation Planner: Sort by % max. alt achieved

Akarsh Simha akarsh at kde.org
Sat Oct 1 10:22:17 UTC 2016


Git commit b10766db6dd714337905394e4c240964381b1616 by Akarsh Simha.
Committed on 01/10/2016 at 10:17.
Pushed by asimha into branch 'master'.

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 at kde.org

M  +71   -14   kstars/tools/observinglist.cpp
M  +10   -0    kstars/tools/observinglist.h

http://commits.kde.org/kstars/b10766db6dd714337905394e4c240964381b1616

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_


More information about the kde-doc-english mailing list