[kstars] kstars: + Adding Mount Model and Solution results view by Robert Lancaster

Jasem Mutlaq null at kde.org
Wed Mar 8 11:41:50 UTC 2017


Git commit 29813c4457f844a9c164a4954d4177eb018ad748 by Jasem Mutlaq.
Committed on 08/03/2017 at 11:38.
Pushed by mutlaqja into branch 'master'.

+ Adding Mount Model and Solution results view by Robert Lancaster
+ More work toward support for INDI astrometry drivr

CCMAIL:kstars-devel at kde.org

M  +1    -0    kstars/CMakeLists.txt
M  +664  -20   kstars/ekos/align/align.cpp
M  +45   -0    kstars/ekos/align/align.h
M  +955  -727  kstars/ekos/align/align.ui
A  +224  -0    kstars/ekos/align/mountmodel.ui
M  +72   -21   kstars/ekos/align/remoteastrometryparser.cpp
M  +5    -4    kstars/ekos/align/remoteastrometryparser.h
M  +13   -0    kstars/ekos/ekosmanager.cpp

https://commits.kde.org/kstars/29813c4457f844a9c164a4954d4177eb018ad748

diff --git a/kstars/CMakeLists.txt b/kstars/CMakeLists.txt
index bca9a91be..4bfd75f6b 100644
--- a/kstars/CMakeLists.txt
+++ b/kstars/CMakeLists.txt
@@ -134,6 +134,7 @@ if (INDI_FOUND)
                     ekos/align/opsalign.ui
                     ekos/align/opsastrometrycfg.ui
                     ekos/align/opsastrometryindexfiles.ui
+                    ekos/align/mountmodel.ui
                     # Focus
                     ekos/focus/focus.ui
                     # Mount
diff --git a/kstars/ekos/align/align.cpp b/kstars/ekos/align/align.cpp
index 30c9c1e43..a841256f1 100644
--- a/kstars/ekos/align/align.cpp
+++ b/kstars/ekos/align/align.cpp
@@ -43,6 +43,10 @@
 #include "opsastrometrycfg.h"
 #include "opsastrometryindexfiles.h"
 
+#include "skymapcomposite.h"
+#include "dialogs/finddialog.h"
+#include "ui_mountmodel.h"
+
 #include <basedevice.h>
 
 #define PAH_CUTOFF_FOV              30                   // Minimum FOV width in arcminutes for PAH to work
@@ -245,6 +249,125 @@ Align::Align()
         appendLogText(i18n("Warning: If using astrometry.net v0.68 or above, remove the --no-fits2fits from the astrometry options."));
 
     hemisphere = KStarsData::Instance()->geo()->lat()->Degrees() > 0 ? NORTH_HEMISPHERE : SOUTH_HEMISPHERE;
+
+    double accuracyRadius=accuracySpin->value();
+
+    alignPlot->setBackground(QBrush(Qt::black));
+    alignPlot->setSelectionTolerance(10);
+
+    alignPlot->xAxis->setBasePen(QPen(Qt::white, 1));
+    alignPlot->yAxis->setBasePen(QPen(Qt::white, 1));
+
+    alignPlot->xAxis->setTickPen(QPen(Qt::white, 1));
+    alignPlot->yAxis->setTickPen(QPen(Qt::white, 1));
+
+    alignPlot->xAxis->setSubTickPen(QPen(Qt::white, 1));
+    alignPlot->yAxis->setSubTickPen(QPen(Qt::white, 1));
+
+    alignPlot->xAxis->setTickLabelColor(Qt::white);
+    alignPlot->yAxis->setTickLabelColor(Qt::white);
+
+    alignPlot->xAxis->setLabelColor(Qt::white);
+    alignPlot->yAxis->setLabelColor(Qt::white);
+
+    alignPlot->xAxis->setLabelFont(QFont(font().family(), 10));
+    alignPlot->yAxis->setLabelFont(QFont(font().family(), 10));
+
+    alignPlot->xAxis->setLabelPadding(2);
+    alignPlot->yAxis->setLabelPadding(2);
+
+    alignPlot->xAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
+    alignPlot->yAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
+    alignPlot->xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
+    alignPlot->yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
+    alignPlot->xAxis->grid()->setZeroLinePen(QPen(Qt::yellow));
+    alignPlot->yAxis->grid()->setZeroLinePen(QPen(Qt::yellow));
+
+    alignPlot->xAxis->setLabel(i18n("dRA (arcsec)"));
+    alignPlot->yAxis->setLabel(i18n("dDE (arcsec)"));
+
+    alignPlot->xAxis->setRange(-accuracyRadius*3, accuracyRadius*3);
+    alignPlot->yAxis->setRange(-accuracyRadius*3, accuracyRadius*3);
+
+    alignPlot->setInteractions(QCP::iRangeZoom);
+    alignPlot->setInteraction(QCP::iRangeDrag, true);
+
+    alignPlot->addGraph();
+    alignPlot->graph(0)->setLineStyle(QCPGraph::lsNone);
+    alignPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, Qt::white, 15));
+
+    buildTarget();
+
+    connect(alignPlot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(handlePointTooltip(QMouseEvent*)));
+    connect(rightLayout, SIGNAL(splitterMoved(int,int)), this, SLOT(handleVerticalPlotSizeChange()));
+    connect(alignSplitter, SIGNAL(splitterMoved(int,int)), this, SLOT(handleHorizontalPlotSizeChange()));
+    connect(accuracySpin, SIGNAL(valueChanged(int)), this, SLOT(buildTarget()));
+
+    alignPlot->resize(190, 190);
+    alignPlot->replot();
+
+    solutionTable->setColumnWidth(0,70);
+    solutionTable->setColumnWidth(1,75);
+    solutionTable->setColumnWidth(2,80);
+    solutionTable->setColumnWidth(3,30);
+    solutionTable->setColumnWidth(4,100);
+    solutionTable->setColumnWidth(5,100);
+
+    clearAllSolutionsB->setIcon(QIcon::fromTheme("application-exit", QIcon(":/icons/breeze/default/application-exit.svg") ));
+    clearAllSolutionsB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+    removeSolutionB->setIcon(QIcon::fromTheme("list-remove", QIcon(":/icons/breeze/default/list-remove.svg") ));
+    removeSolutionB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+
+    mountModel.setupUi(&mountModelDialog);
+    mountModelDialog.setWindowTitle("Mount Model Tool");
+    mountModelDialog.setWindowFlags(Qt::Tool| Qt::WindowStaysOnTopHint);
+    mountModel.alignTable->setColumnWidth(0,70);
+    mountModel.alignTable->setColumnWidth(1,75);
+    mountModel.alignTable->setColumnWidth(2,80);
+    mountModel.alignTable->setColumnWidth(3,30);
+
+    mountModel.alignTable->verticalHeader()->setDragDropOverwriteMode(false);
+    mountModel.alignTable->verticalHeader()->setSectionsMovable(true);
+    mountModel.alignTable->verticalHeader()->setDragEnabled(true);
+    mountModel.alignTable->verticalHeader()->setDragDropMode(QAbstractItemView::InternalMove);
+    connect(mountModel.alignTable->verticalHeader(), SIGNAL(sectionMoved(int, int , int)), this, SLOT(moveAlignPoint(int, int , int)));
+
+    mountModel.clearAllAlignB->setIcon(QIcon::fromTheme("application-exit", QIcon(":/icons/breeze/default/application-exit.svg") ));
+    mountModel.clearAllAlignB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+    mountModel.removeAlignB->setIcon(QIcon::fromTheme("list-remove", QIcon(":/icons/breeze/default/list-remove.svg") ));
+    mountModel.removeAlignB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+    mountModel.addAlignB->setIcon(QIcon::fromTheme("list-add", QIcon(":/icons/breeze/default/list-add.svg") ));
+    mountModel.addAlignB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+    mountModel.findAlignB->setIcon(QIcon::fromTheme("edit-find", QIcon(":/icons/breeze/default/edit-find.svg") ));
+    mountModel.findAlignB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+    mountModel.wizardAlignB->setIcon(QIcon::fromTheme("tools-wizard", QIcon(":/icons/breeze/default/tools-wizard.svg") ));
+    mountModel.wizardAlignB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+    mountModel.stopAlignB->setIcon(QIcon::fromTheme("media-playback-stop", QIcon(":/icons/breeze/default/media-playback-stop.svg") ));
+    mountModel.stopAlignB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+    mountModel.startAlignB->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/icons/breeze/default/media-playback-start.svg") ));
+    mountModel.startAlignB->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+
+    connect(clearAllSolutionsB, SIGNAL(clicked()), this, SLOT(slotClearAllSolutionPoints()));
+    connect(removeSolutionB, SIGNAL(clicked()), this, SLOT(slotRemoveSolutionPoint()));
+    connect(mountModelB, SIGNAL(clicked()), this, SLOT(slotMountModel()));
+    connect(solutionTable, SIGNAL(cellClicked(int, int)), this, SLOT(selectSolutionTableRow(int, int)));
+
+    connect(mountModel.clearAllAlignB, SIGNAL(clicked()), this, SLOT(slotClearAllAlignPoints()));
+    connect(mountModel.removeAlignB, SIGNAL(clicked()), this, SLOT(slotRemoveAlignPoint()));
+    connect(mountModel.addAlignB, SIGNAL(clicked()), this, SLOT(slotAddAlignPoint()));
+    connect(mountModel.findAlignB, SIGNAL(clicked()), this, SLOT(slotFindAlignObject()));
+    connect(mountModel.stopAlignB, SIGNAL(clicked()), this, SLOT(resetAlignmentProcedure()));
+    connect(mountModel.startAlignB, SIGNAL(clicked()), this, SLOT(startStopAlignmentProcedure()));
+
+
 }
 
 Align::~Align()
@@ -263,6 +386,370 @@ Align::~Align()
     foreach(QString dirFile, dir.entryList())
         dir.remove(dirFile);
 }
+void Align::selectSolutionTableRow(int row, int column){
+    solutionTable->selectRow(row);
+    for(int i=0;i<alignPlot->itemCount();i++){
+        QCPAbstractItem *abstractItem=alignPlot->item(i);
+        if(abstractItem){
+            QCPItemText *item = qobject_cast<QCPItemText*>(abstractItem);
+            if(item){
+                if(i==row){
+                    item->setColor(Qt::black);
+                    item->setBrush(Qt::yellow);
+                }else{
+                    item->setColor(Qt::red);
+                    item->setBrush(Qt::white);
+                }
+            }
+        }
+    }
+    alignPlot->replot();
+}
+
+void Align::handleHorizontalPlotSizeChange(){
+      alignPlot->xAxis->setScaleRatio(alignPlot->yAxis,1.0);
+      alignPlot->replot();
+}
+
+void Align::handleVerticalPlotSizeChange(){
+      alignPlot->yAxis->setScaleRatio(alignPlot->xAxis,1.0);
+      alignPlot->replot();
+}
+
+void Align::resizeEvent(QResizeEvent * event){
+    if(event->oldSize().width()!=-1){
+        if(event->oldSize().width()!=size().width())
+            handleHorizontalPlotSizeChange();
+        else if(event->oldSize().height()!=size().height())
+            handleVerticalPlotSizeChange();
+    }
+}
+
+
+void Align::handlePointTooltip(QMouseEvent* event){
+
+    QCPAbstractItem *item =alignPlot->itemAt(event->localPos());
+    if(item){
+        QCPItemText *label = qobject_cast<QCPItemText*>(item);
+        if(label){
+            QString labelText=label->text();
+            int point=labelText.toInt()-1;
+
+            QToolTip::hideText();
+            QToolTip::showText(event->globalPos(),
+                               tr("<table>"
+                                      "<tr>"
+                                        "<th colspan=\"2\">Object %L1: %L2</th>"
+                                      "</tr>"
+                                      "<tr>"
+                                        "<td>RA:</td><td>%L3</td>"
+                                      "</tr>"
+                                      "<tr>"
+                                        "<td>DE:</td><td>%L4</td>"
+                                      "</tr>"
+                                      "<tr>"
+                                        "<td>dRA:</td><td>%L5</td>"
+                                      "</tr>"
+                                      "<tr>"
+                                        "<td>dDE:</td><td>%L6</td>"
+                                      "</tr>"
+                                  "</table>").
+                               arg(point+1).
+                               arg(solutionTable->item(point, 2)->text()).
+                               arg(solutionTable->item(point, 0)->text()).
+                               arg(solutionTable->item(point, 1)->text()).
+                               arg(solutionTable->item(point, 4)->text()).
+                               arg(solutionTable->item(point, 5)->text()),
+                               alignPlot, alignPlot->rect());
+        }
+    }
+}
+
+
+void Align::buildTarget(){
+    double accuracyRadius=accuracySpin->value();
+    if(centralTarget){
+       concentricRings->data()->clear();
+       redTarget->data()->clear();
+       yellowTarget->data()->clear();
+       centralTarget->data()->clear();
+    }else{
+        concentricRings = new QCPCurve(alignPlot->xAxis, alignPlot->yAxis);
+        redTarget = new QCPCurve(alignPlot->xAxis, alignPlot->yAxis);
+        yellowTarget = new QCPCurve(alignPlot->xAxis, alignPlot->yAxis);
+        centralTarget = new QCPCurve(alignPlot->xAxis, alignPlot->yAxis);
+    }
+    const int pointCount = 200;
+    QVector<QCPCurveData> circleRings(pointCount*(5));//Have to multiply by the number of rings, Rings at : 25%, 50%, 75%, 125%, 175%
+    QVector<QCPCurveData> circleCentral(pointCount);
+    QVector<QCPCurveData> circleYellow(pointCount);
+    QVector<QCPCurveData> circleRed(pointCount);
+
+    int circleRingPt=0;
+    for (int i=0; i<pointCount; i++)
+    {
+      double theta = i/(double)(pointCount)*2*M_PI;
+
+      for(double ring=1; ring < 8; ring++){
+          if(ring !=4 && ring != 6){
+            if(i%(9-(int)ring)==0){ //This causes fewer points to draw on the inner circles.
+                circleRings[circleRingPt] = QCPCurveData(circleRingPt, accuracyRadius*ring*0.25*qCos(theta), accuracyRadius*ring*0.25*qSin(theta));
+                circleRingPt++;
+            }
+          }
+      }
+
+      circleCentral[i] = QCPCurveData(i, accuracyRadius*qCos(theta), accuracyRadius*qSin(theta));
+      circleYellow[i] = QCPCurveData(i, accuracyRadius*1.5*qCos(theta), accuracyRadius*1.5*qSin(theta));
+      circleRed[i] = QCPCurveData(i, accuracyRadius*2*qCos(theta), accuracyRadius*2*qSin(theta));
+    }
+
+    concentricRings->setLineStyle(QCPCurve::lsNone);
+    concentricRings->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc,  QColor(255, 255, 255, 150), 1));
+
+    concentricRings->data()->set(circleRings, true);
+    redTarget->data()->set(circleRed, true);
+    yellowTarget->data()->set(circleYellow, true);
+    centralTarget->data()->set(circleCentral, true);
+
+    concentricRings->setPen(QPen(Qt::white));
+    redTarget->setPen(QPen(Qt::red));
+    yellowTarget->setPen(QPen(Qt::yellow));
+    centralTarget->setPen(QPen(Qt::green));
+
+    concentricRings->setBrush(Qt::NoBrush);
+    redTarget->setBrush(QBrush(QColor(255, 0, 0, 50)));
+    yellowTarget->setBrush(QBrush(QColor(0, 255, 0, 50))); //Note this is actually yellow.  It is green on top of red with equal opacity.
+    centralTarget->setBrush(QBrush(QColor(0, 255, 0, 50)));
+
+    if(alignPlot->size().width()>0)
+        alignPlot->replot();
+}
+
+void Align::slotClearAllSolutionPoints(){
+
+    solutionTable->setRowCount(0);
+    alignPlot->graph(0)->data()->clear();
+    alignPlot->clearItems();
+    buildTarget();
+
+    double accuracyRadius=accuracySpin->value();
+    alignPlot->xAxis->setRange(-accuracyRadius*3, accuracyRadius*3);
+    alignPlot->yAxis->setRange(-accuracyRadius*3, accuracyRadius*3);
+
+    alignPlot->xAxis->setScaleRatio(alignPlot->yAxis,1.0);
+
+    alignPlot->replot();
+}
+
+void Align::slotClearAllAlignPoints(){
+
+    mountModel.alignTable->setRowCount(0);
+}
+
+void Align::slotRemoveSolutionPoint(){
+    QCPAbstractItem *abstractItem=alignPlot->item(solutionTable->currentRow());
+    if(abstractItem){
+        QCPItemText *item = qobject_cast<QCPItemText*>(abstractItem);
+        if(item){
+            double point=item->position->key();
+            alignPlot->graph(0)->data()->remove(point);
+        }
+    }
+    alignPlot->removeItem(solutionTable->currentRow());
+    for(int i=0;i<alignPlot->itemCount();i++){
+        QCPAbstractItem *abstractItem=alignPlot->item(i);
+        if(abstractItem){
+            QCPItemText *item = qobject_cast<QCPItemText*>(abstractItem);
+            if(item)
+                item->setText(QString::number(i+1));
+        }
+    }
+    solutionTable->removeRow(solutionTable->currentRow());
+    alignPlot->replot();
+}
+
+void Align::slotRemoveAlignPoint(){
+    mountModel.alignTable->removeRow(mountModel.alignTable->currentRow());
+}
+
+void Align::moveAlignPoint(int logicalIndex, int oldVisualIndex, int newVisualIndex)
+{
+    for (int i=0; i < mountModel.alignTable->columnCount(); i++)
+    {
+        QTableWidgetItem *oldItem = mountModel.alignTable->takeItem(oldVisualIndex, i);
+        QTableWidgetItem *newItem = mountModel.alignTable->takeItem(newVisualIndex, i);
+
+        mountModel.alignTable->setItem(newVisualIndex, i, oldItem);
+        mountModel.alignTable->setItem(oldVisualIndex, i, newItem);
+    }
+    disconnect(mountModel.alignTable->verticalHeader(), SIGNAL(sectionMoved(int, int , int)), this, SLOT(moveAlignPoint(int, int , int)));
+    mountModel.alignTable->verticalHeader()->moveSection(newVisualIndex,oldVisualIndex);
+    connect(mountModel.alignTable->verticalHeader(), SIGNAL(sectionMoved(int, int , int)), this, SLOT(moveAlignPoint(int, int , int)));
+
+}
+
+void Align::slotMountModel(){
+    mountModelDialog.show();
+}
+
+
+void Align::slotAddAlignPoint(){
+    int currentRow = mountModel.alignTable->rowCount();
+    mountModel.alignTable->insertRow(currentRow);
+
+    QTableWidgetItem *disabledBox= new QTableWidgetItem();
+    disabledBox->setFlags(Qt::ItemIsSelectable);
+    mountModel.alignTable->setItem(currentRow, 3, disabledBox);
+}
+
+void Align::slotFindAlignObject() {
+   QPointer<FindDialog> fd = new FindDialog( KStars::Instance() );
+   if ( fd->exec() == QDialog::Accepted ) {
+       SkyObject *o = fd->targetObject();
+       if( o != 0 ) {
+           int currentRow = mountModel.alignTable->rowCount();
+           mountModel.alignTable->insertRow(currentRow);
+
+           QString ra_report, dec_report;
+           getFormattedCoords(o->ra().Hours(),o->dec().Degrees(),ra_report, dec_report);
+
+           QTableWidgetItem *RAReport = new QTableWidgetItem();
+           RAReport->setText(ra_report);
+           RAReport->setTextAlignment(Qt::AlignHCenter);
+           mountModel.alignTable->setItem(currentRow, 0, RAReport);
+
+           QTableWidgetItem *DECReport = new QTableWidgetItem();
+           DECReport->setText(dec_report);
+           DECReport->setTextAlignment(Qt::AlignHCenter);
+           mountModel.alignTable->setItem(currentRow, 1, DECReport);
+
+           QTableWidgetItem *ObjNameReport = new QTableWidgetItem();
+           ObjNameReport->setText(o->name());
+           ObjNameReport->setTextAlignment(Qt::AlignHCenter);
+           mountModel.alignTable->setItem(currentRow, 2, ObjNameReport);
+
+           QTableWidgetItem *disabledBox= new QTableWidgetItem();
+           disabledBox->setFlags(Qt::ItemIsSelectable);
+           mountModel.alignTable->setItem(currentRow, 3, disabledBox);
+       }
+   }
+   delete fd;
+}
+
+void Align::resetAlignmentProcedure(){
+    mountModel.alignTable->setCellWidget(currentAlignmentPoint, 3,new QWidget());
+    QTableWidgetItem *statusReport = new QTableWidgetItem();
+    statusReport->setFlags(Qt::ItemIsSelectable);
+    statusReport->setIcon(QIcon(":/icons/breeze/default/security-medium.svg"));
+    mountModel.alignTable->setItem(currentAlignmentPoint, 3, statusReport);
+
+    appendLogText(i18n("The Mount Model Tool is Reset."));
+    mountModel.startAlignB->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/icons/breeze/default/media-playback-start.svg") ));
+    mountModelRunning=false;
+    currentAlignmentPoint=0;
+}
+
+bool Align::alignmentPointsAreBad(){
+    for (int i=0; i < mountModel.alignTable->rowCount(); i++)
+    {
+        QTableWidgetItem *raCell=mountModel.alignTable->item(i,0);
+        if(!raCell)
+            return true;
+        QString raString=raCell->text();
+        if(dms().setFromString(raString,false)==false)
+            return true;
+
+        QTableWidgetItem *decCell=mountModel.alignTable->item(i,1);
+        if(!decCell)
+            return true;
+        QString decString=decCell->text();
+        if(dms().setFromString(decString,true)==false)
+            return true;
+    }
+    return false;
+}
+
+void Align::startStopAlignmentProcedure(){
+    if(!mountModelRunning){
+        if(mountModel.alignTable->rowCount()>0){
+            if(alignmentPointsAreBad()){
+                 KMessageBox::error(0, i18n("Please Check the Alignment Points."));
+                return;
+            }
+            if(currentAlignmentPoint==0){
+                for(int row=0;row<mountModel.alignTable->rowCount();row++){
+                    QTableWidgetItem *statusReport = new QTableWidgetItem();
+                    statusReport->setIcon(QIcon());
+                    mountModel.alignTable->setItem(row, 3, statusReport);
+                }
+            }
+            mountModel.startAlignB->setIcon(QIcon::fromTheme("media-playback-pause", QIcon(":/icons/breeze/default/media-playback-pause.svg") ));
+            mountModelRunning=true;
+            appendLogText(i18n("The Mount Model Tool is Starting."));
+            startAlignmentPoint();
+        }
+    }else{
+        mountModel.startAlignB->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/icons/breeze/default/media-playback-start.svg") ));
+        mountModel.alignTable->setCellWidget(currentAlignmentPoint, 3,new QWidget());
+        appendLogText(i18n("The Mount Model Tool is Paused."));
+        mountModelRunning=false;
+
+        QTableWidgetItem *statusReport = new QTableWidgetItem();
+        statusReport->setFlags(Qt::ItemIsSelectable);
+        statusReport->setIcon(QIcon(":/icons/breeze/default/security-medium.svg"));
+        mountModel.alignTable->setItem(currentAlignmentPoint, 3, statusReport);
+    }
+
+}
+
+void Align::startAlignmentPoint(){
+    if(mountModelRunning&&currentAlignmentPoint>=0&&currentAlignmentPoint<mountModel.alignTable->rowCount()){
+        QTableWidgetItem *raCell=mountModel.alignTable->item(currentAlignmentPoint,0);
+        QString raString=raCell->text();
+        dms raDMS  = dms::fromString(raString,false);
+        double ra = raDMS.Hours();
+
+        QTableWidgetItem *decCell=mountModel.alignTable->item(currentAlignmentPoint,1);
+        QString decString=decCell->text();
+        dms decDMS = dms::fromString(decString,true);
+        double dec= decDMS.Degrees();
+
+        QProgressIndicator *alignIndicator = new QProgressIndicator(this);
+        mountModel.alignTable->setCellWidget(currentAlignmentPoint, 3, alignIndicator);
+        alignIndicator->startAnimation();
+
+        targetCoord.setRA(ra);
+        targetCoord.setDec(dec);
+
+        Slew();
+    }
+}
+
+void Align::finishAlignmentPoint(bool solverSucceeded){
+    if(mountModelRunning&&currentAlignmentPoint>=0&&currentAlignmentPoint<mountModel.alignTable->rowCount()){
+        mountModel.alignTable->setCellWidget(currentAlignmentPoint, 3,new QWidget());
+        QTableWidgetItem *statusReport = new QTableWidgetItem();
+        statusReport->setFlags(Qt::ItemIsSelectable);
+        if(solverSucceeded)
+            statusReport->setIcon(QIcon(":/icons/breeze/default/security-high.svg"));
+        else
+            statusReport->setIcon(QIcon(":/icons/breeze/default/security-low.svg"));
+        mountModel.alignTable->setItem(currentAlignmentPoint, 3, statusReport);
+
+
+        currentAlignmentPoint++;
+
+        if(currentAlignmentPoint<mountModel.alignTable->rowCount()){
+            startAlignmentPoint();
+        } else{
+            mountModelRunning=false;
+            mountModel.startAlignB->setIcon(QIcon::fromTheme("media-playback-start", QIcon(":/icons/breeze/default/media-playback-start.svg") ));
+            appendLogText(i18n("The Mount Model Tool is Finished."));
+            currentAlignmentPoint=0;
+        }
+    }
+}
 
 bool Align::isParserOK()
 {
@@ -323,13 +810,14 @@ void Align::setSolverType(int type)
         if (remoteParser != NULL)
         {
             parser = remoteParser;
-            (dynamic_cast<RemoteAstrometryParser*>(parser))->setCCD(currentCCD);
+            (dynamic_cast<RemoteAstrometryParser*>(parser))->setAstrometryDevice(remoteParserDevice);
             return;
         }
 
         remoteParser = new Ekos::RemoteAstrometryParser();
         parser = remoteParser;
-        (dynamic_cast<RemoteAstrometryParser*>(parser))->setCCD(currentCCD);
+        (dynamic_cast<RemoteAstrometryParser*>(parser))->setAstrometryDevice(remoteParserDevice);
+
         break;
     }
 
@@ -375,8 +863,8 @@ void Align::checkCCD(int ccdNum)
     {
         currentCCD = CCDs.at(ccdNum);
 
-        if (solverTypeGroup->checkedId() == SOLVER_REMOTE)
-            (dynamic_cast<RemoteAstrometryParser*>(parser))->setCCD(currentCCD);
+        //if (solverTypeGroup->checkedId() == SOLVER_REMOTE)
+            //(dynamic_cast<RemoteAstrometryParser*>(parser))->setCCD(currentCCD);
     }
 
     FOVScopeCombo->setCurrentIndex(guideScopeCCDs.contains(currentCCD->getDeviceName()) ? ISD::CCD::TELESCOPE_GUIDE : ISD::CCD::TELESCOPE_PRIMARY);
@@ -859,16 +1347,18 @@ bool Align::captureAndSolve()
    connect(currentCCD, SIGNAL(newExposureValue(ISD::CCDChip*,double,IPState)), this, SLOT(checkCCDExposureProgress(ISD::CCDChip*,double,IPState)));
 
    // In case of remote solver, we set mode to UPLOAD_BOTH
-   if (solverTypeGroup->checkedId() == SOLVER_REMOTE)
+   if (solverTypeGroup->checkedId() == SOLVER_REMOTE && remoteParser)
    {
-       rememberUploadMode = currentCCD->getUploadMode();
-       currentCCD->setUploadMode(ISD::CCD::UPLOAD_BOTH);
-
+       //rememberUploadMode = currentCCD->getUploadMode();
+       //currentCCD->setUploadMode(ISD::CCD::UPLOAD_BOTH);
        // For solver remote we need to start solver BEFORE capture
-       startSolving(QString());
+       //startSolving(QString());
+
+       // Enable remote parse
+       dynamic_cast<RemoteAstrometryParser*>(remoteParser)->setEnabled(true);
    }
-   else
-   {
+   //else
+   //{
        if (currentCCD->getUploadMode() == ISD::CCD::UPLOAD_LOCAL)
        {
            rememberUploadMode = ISD::CCD::UPLOAD_LOCAL;
@@ -881,7 +1371,7 @@ bool Align::captureAndSolve()
        dir.setFilter(QDir::Files);
        foreach(QString dirFile, dir.entryList())
            dir.remove(dirFile);
-   }
+   //}
 
    currentCCD->setTransformFormat(ISD::CCD::FORMAT_FITS);
 
@@ -1069,6 +1559,41 @@ void Align::startSolving(const QString &filename, bool isGenerated)
         targetCoord.setDec(dec);
     }
 
+    int currentRow = solutionTable->rowCount();
+    solutionTable->insertRow(currentRow);
+    for(int i=4;i<6;i++){
+        QTableWidgetItem *disabledBox= new QTableWidgetItem();
+        disabledBox->setFlags(Qt::ItemIsSelectable);
+        solutionTable->setItem(currentRow, i, disabledBox);
+    }
+
+    QTableWidgetItem *RAReport = new QTableWidgetItem();
+    RAReport->setText(ScopeRAOut->text());
+    RAReport->setTextAlignment(Qt::AlignHCenter);
+    RAReport->setFlags(Qt::ItemIsSelectable);
+    solutionTable->setItem(currentRow, 0, RAReport);
+
+    QTableWidgetItem *DECReport = new QTableWidgetItem();
+    DECReport->setText(ScopeDecOut->text());
+    DECReport->setTextAlignment(Qt::AlignHCenter);
+    DECReport->setFlags(Qt::ItemIsSelectable);
+    solutionTable->setItem(currentRow, 1, DECReport);
+
+    double maxrad = 1000.0/Options::zoomFactor();
+    SkyObject *so = KStarsData::Instance()->skyComposite()->objectNearest(new SkyPoint(dms(ra*15),dms(dec)), maxrad );
+    if (so){
+        QTableWidgetItem *ObjNameReport = new QTableWidgetItem();
+        ObjNameReport->setText(so->name());
+        ObjNameReport->setTextAlignment(Qt::AlignHCenter);
+        ObjNameReport->setFlags(Qt::ItemIsSelectable);
+        solutionTable->setItem(currentRow, 2, ObjNameReport);
+    }
+
+    QProgressIndicator *alignIndicator = new QProgressIndicator(this);
+    solutionTable->setCellWidget(currentRow, 3, alignIndicator);
+    alignIndicator->startAnimation();
+
+
     Options::setSolverType(solverTypeGroup->checkedId());
     //Options::setSolverOptions(solverOptions->text());
     Options::setGuideScopeCCDs(guideScopeCCDs);
@@ -1106,6 +1631,12 @@ void Align::solverFinished(double orientation, double ra, double dec, double pix
 
     alignTimer.stop();
 
+    if (solverTypeGroup->checkedId() == SOLVER_REMOTE && remoteParser)
+    {
+        // Disable remote parse
+        dynamic_cast<RemoteAstrometryParser*>(remoteParser)->setEnabled(false);
+    }
+
     int binx, biny;
     ISD::CCDChip *targetChip = currentCCD->getChip(useGuideHead ? ISD::CCDChip::GUIDE_CCD : ISD::CCDChip::PRIMARY_CCD);
     targetChip->getBinning(&binx, &biny);
@@ -1154,6 +1685,52 @@ void Align::solverFinished(double orientation, double ra, double dec, double pix
      SolverRAOut->setText(ra_dms);
      SolverDecOut->setText(dec_dms);
 
+     int currentRow = solutionTable->rowCount()-1;
+
+     QTableWidgetItem *dRAReport = new QTableWidgetItem();
+     if(dRAReport){
+         dRAReport->setText(QString::number(raDiff,'f',3)+"\"");
+         dRAReport->setTextAlignment(Qt::AlignHCenter);
+         dRAReport->setFlags(Qt::ItemIsSelectable);
+         solutionTable->setItem(currentRow, 4, dRAReport);
+     }
+
+     QTableWidgetItem *dDECReport = new QTableWidgetItem();
+     if(dDECReport){
+         dDECReport->setText(QString::number(deDiff,'f',3)+"\"");
+         dDECReport->setTextAlignment(Qt::AlignHCenter);
+         dDECReport->setFlags(Qt::ItemIsSelectable);
+         solutionTable->setItem(currentRow, 5, dDECReport);
+     }
+
+     double raPlot=raDiff;
+     double decPlot=deDiff;
+     alignPlot->graph(0)->addData(raPlot, decPlot);
+
+     QCPItemText *textLabel = new QCPItemText(alignPlot);
+     textLabel->setPositionAlignment(Qt::AlignVCenter|Qt::AlignHCenter);
+
+     textLabel->position->setType(QCPItemPosition::ptPlotCoords);
+     textLabel->position->setCoords(raPlot,decPlot);
+     textLabel->setColor(Qt::red);
+     textLabel->setPadding(QMargins(0,0,0,0));
+     textLabel->setBrush(Qt::white);
+     //textLabel->setBrush(Qt::NoBrush);
+     textLabel->setPen(Qt::NoPen);
+     textLabel->setText(" " + QString::number(solutionTable->rowCount()) + " ");
+     textLabel->setFont(QFont(font().family(), 8));
+
+
+     if(!alignPlot->xAxis->range().contains(raDiff)){
+        alignPlot->graph(0)->rescaleKeyAxis(true);
+        alignPlot->yAxis->setScaleRatio(alignPlot->xAxis,1.0);
+     }
+     if(!alignPlot->yAxis->range().contains(deDiff)){
+        alignPlot->graph(0)->rescaleValueAxis(true);
+        alignPlot->xAxis->setScaleRatio(alignPlot->yAxis,1.0);
+     }
+     alignPlot->replot();
+
      if (Options::astrometrySolverWCS())
      {
          INumberVectorProperty *ccdRotation = currentCCD->getBaseDevice()->getNumber("CCD_ROTATION");
@@ -1196,32 +1773,69 @@ void Align::solverFinished(double orientation, double ra, double dec, double pix
      //if (syncR->isChecked() || nothingR->isChecked() || targetDiff <= accuracySpin->value())
      // CONTINUE HERE
 
+     solutionTable->setCellWidget(currentRow, 3,new QWidget());
+     QTableWidgetItem *statusReport = new QTableWidgetItem();
+     statusReport->setFlags(Qt::ItemIsSelectable);
+
      switch (currentGotoMode)
      {
         case GOTO_SYNC:
          executeGOTO();
+
+         statusReport->setIcon(QIcon(":/icons/breeze/default/security-high.svg"));
+         solutionTable->setItem(currentRow, 3, statusReport);
+         if(mountModelRunning)
+            finishAlignmentPoint(true);
+
          return;
          break;
 
         case GOTO_SLEW:
          if (loadSlewState == IPS_BUSY || targetDiff > accuracySpin->value())
          {
+
              if (loadSlewState == IPS_IDLE && ++solverIterations == MAXIMUM_SOLVER_ITERATIONS)
              {
                  appendLogText(i18n("Maximum number of iterations reached. Solver failed."));
+
+                 statusReport->setIcon(QIcon(":/icons/breeze/default/security-low.svg"));
+                 solutionTable->setItem(currentRow, 3, statusReport);
+
                  solverFailed();
+                 if(mountModelRunning)
+                    finishAlignmentPoint(false);
                  return;
              }
 
-             //executeMode();
+             targetAccuracyNotMet=true;
+
+             statusReport->setIcon(QIcon(":/icons/breeze/default/security-medium.svg"));
+             solutionTable->setItem(currentRow, 3, statusReport);
+
              executeGOTO();
              return;
          }
 
+         statusReport->setIcon(QIcon(":/icons/breeze/default/security-high.svg"));
+         solutionTable->setItem(currentRow, 3, statusReport);
+
          appendLogText(i18n("Target is within acceptable range. Astrometric solver is successful."));
+         if(mountModelRunning){
+            finishAlignmentPoint(true);
+            if(mountModelRunning)
+                return;
+         }
          break;
 
         case GOTO_NOTHING:
+
+         statusReport->setIcon(QIcon(":/icons/breeze/default/security-high.svg"));
+         solutionTable->setItem(currentRow, 3, statusReport);
+         if(mountModelRunning){
+            finishAlignmentPoint(true);
+            if(mountModelRunning)
+                return;
+         }
          break;
 
      }
@@ -1267,6 +1881,14 @@ void Align::solverFailed()
 
     state = ALIGN_FAILED;
     emit newStatus(state);
+
+    int currentRow = solutionTable->rowCount()-1;
+
+    solutionTable->setCellWidget(currentRow, 3,new QWidget());
+    QTableWidgetItem *statusReport = new QTableWidgetItem();
+    statusReport->setIcon(QIcon(":/icons/breeze/default/security-low.svg"));
+    statusReport->setFlags(Qt::ItemIsSelectable);
+    solutionTable->setItem(currentRow, 3, statusReport);
 }
 
 void Align::abort()
@@ -1322,6 +1944,14 @@ void Align::abort()
 
     state = ALIGN_ABORTED;
     emit newStatus(state);
+
+    int currentRow = solutionTable->rowCount()-1;
+
+    solutionTable->setCellWidget(currentRow, 3,new QWidget());
+    QTableWidgetItem *statusReport = new QTableWidgetItem();
+    statusReport->setIcon(QIcon(":/icons/breeze/default/security-low.svg"));
+    statusReport->setFlags(Qt::ItemIsSelectable);
+    solutionTable->setItem(currentRow, 3, statusReport);
 }
 
 QList<double> Align::getSolutionResult()
@@ -1351,6 +1981,7 @@ void Align::clearLog()
 
 void Align::processTelescopeNumber(INumberVectorProperty *coord)
 {
+
     QString ra_dms, dec_dms;
 
     if (!strcmp(coord->name, "EQUATORIAL_EOD_COORD"))
@@ -1464,9 +2095,13 @@ void Align::processTelescopeNumber(INumberVectorProperty *coord)
                     QTimer::singleShot(delaySpin->value(), this, SLOT(captureAndSolve()));
                     return;
                 }
-                else if(currentGotoMode == GOTO_SLEW)
+                else if(currentGotoMode == GOTO_SLEW||mountModelRunning)
                 {
-                    appendLogText(i18n("Slew complete. Target accuracy is not met, running solver again..."));
+                    if(targetAccuracyNotMet)
+                        appendLogText(i18n("Slew complete. Target accuracy is not met, running solver again..."));
+                    else
+                        appendLogText(i18n("Slew complete. Solving Alignment Point. . ."));
+                    targetAccuracyNotMet=false;
 
                     state = ALIGN_PROGRESS;
                     emit newStatus(state);
@@ -1474,7 +2109,7 @@ void Align::processTelescopeNumber(INumberVectorProperty *coord)
                     QTimer::singleShot(delaySpin->value(), this, SLOT(captureAndSolve()));
                     return;
                 }
-                break;
+            break;
 
             default:
             {
@@ -2109,12 +2744,12 @@ void Align::getFormattedCoords(double ra, double dec, QString &ra_str, QString &
 
 void Align::loadAndSlew(QString fileURL)
 {
-    if (solverTypeGroup->checkedId() == SOLVER_REMOTE)
+    /*if (solverTypeGroup->checkedId() == SOLVER_REMOTE)
     {
         appendLogText(i18n("Load and Slew is not supported in remote solver mode."));
         loadSlewB->setEnabled(false);
         return;
-    }
+    }*/
 
     if (fileURL.isEmpty())
         fileURL = QFileDialog::getOpenFileName(KStars::Instance(), i18n("Load Image"), dirPath, "Images (*.fits *.fit *.jpg *.jpeg)");
@@ -2489,8 +3124,8 @@ void Align::toggleAlignWidgetFullScreen()
     {
         alignWidget->setParent(this);
         rightLayout->insertWidget(0, alignWidget);
-        rightLayout->setStretch(0, 2);
-        rightLayout->setStretch(1, 1);
+        //rightLayout->setStretch(0, 2);
+       // rightLayout->setStretch(1, 1);
         alignWidget->showNormal();
     }
     else
@@ -3068,4 +3703,13 @@ void Align::setMountStatus(ISD::Telescope::TelescopeStatus newState)
     }
 }
 
+void Align::setAstrometryDevice(ISD::GDInterface *newAstrometry)
+{
+    remoteParserDevice = newAstrometry;
+    remoteSolverR->setEnabled(true);
+
+    if (remoteParser)
+        remoteParser->setAstrometryDevice(remoteParserDevice);
+}
+
 }
diff --git a/kstars/ekos/align/align.h b/kstars/ekos/align/align.h
index 80215ceb3..d74eb0735 100644
--- a/kstars/ekos/align/align.h
+++ b/kstars/ekos/align/align.h
@@ -25,6 +25,8 @@
 #include "indi/indiccd.h"
 #include "indi/indistd.h"
 
+#include "ui_mountmodel.h"
+
 class FOV;
 class QProgressIndicator;
 
@@ -172,6 +174,12 @@ public:
     void setTelescope(ISD::GDInterface *newTelescope);
 
     /**
+     * @brief setAstrometryDevice
+     * @param newAstrometry
+     */
+    void setAstrometryDevice(ISD::GDInterface *newAstrometry);
+
+    /**
      * @brief CCD information is updated, sync them.
      */
     void syncCCDInfo();
@@ -321,6 +329,7 @@ public slots:
     // Update Mount module status
     void setMountStatus(ISD::Telescope::TelescopeStatus newState);
 
+
 private slots:
 
     /* Polar Alignment */
@@ -353,6 +362,27 @@ private slots:
     void startPAHRefreshProcess();
     void setPAHRefreshComplete();
 
+    //Solutions Display slots
+    void buildTarget();
+    void handlePointTooltip(QMouseEvent * event);
+    void handleVerticalPlotSizeChange();
+    void handleHorizontalPlotSizeChange();
+    void selectSolutionTableRow(int row, int column);
+    void slotClearAllSolutionPoints();
+    void slotRemoveSolutionPoint();
+    void slotMountModel();
+
+    //Mount Model Slots
+    void slotClearAllAlignPoints();
+    void slotRemoveAlignPoint();
+    void slotAddAlignPoint();
+    void slotFindAlignObject();
+    void resetAlignmentProcedure();
+    void startStopAlignmentProcedure();
+    void startAlignmentPoint();
+    void finishAlignmentPoint(bool solverSucceeded);
+    void moveAlignPoint(int logicalIndex, int oldVisualIndex, int newVisualIndex);
+
 signals:
         void newLog();
         void solverComplete(bool);
@@ -486,7 +516,9 @@ private:
     AstrometryParser *parser;
     OnlineAstrometryParser *onlineParser;
     OfflineAstrometryParser *offlineParser;
+
     RemoteAstrometryParser *remoteParser;
+    ISD::GDInterface *remoteParserDevice = NULL;
 
     // Pointers to our devices
     ISD::Telescope *currentTelescope;
@@ -566,6 +598,19 @@ private:
     OpsAlign *opsAlign;
     OpsAstrometryCfg *opsAstrometryCfg;
     OpsAstrometryIndexFiles *opsAstrometryIndexFiles;
+
+    void resizeEvent(QResizeEvent * event);
+    QCPCurve *centralTarget = NULL;
+    QCPCurve *yellowTarget = NULL;
+    QCPCurve *redTarget = NULL;
+    QCPCurve *concentricRings = NULL;
+    QDialog mountModelDialog;
+    Ui_mountModel mountModel;
+    int currentAlignmentPoint=0;
+    bool mountModelRunning=false;
+    bool targetAccuracyNotMet=false;
+
+    bool alignmentPointsAreBad();
 };
 
 }
diff --git a/kstars/ekos/align/align.ui b/kstars/ekos/align/align.ui
index 0649103b8..24a60ef17 100644
--- a/kstars/ekos/align/align.ui
+++ b/kstars/ekos/align/align.ui
@@ -6,32 +6,17 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>600</width>
-    <height>468</height>
+    <width>610</width>
+    <height>469</height>
    </rect>
   </property>
-  <layout class="QVBoxLayout" name="verticalLayout_11">
-   <property name="spacing">
-    <number>3</number>
-   </property>
-   <property name="leftMargin">
-    <number>3</number>
-   </property>
-   <property name="topMargin">
-    <number>3</number>
-   </property>
-   <property name="rightMargin">
-    <number>3</number>
-   </property>
-   <property name="bottomMargin">
-    <number>3</number>
-   </property>
+  <layout class="QVBoxLayout" name="verticalLayout_19">
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout_5" stretch="1,2">
      <item>
       <layout class="QVBoxLayout" name="verticalLayout">
        <property name="spacing">
-        <number>3</number>
+        <number>0</number>
        </property>
        <item>
         <layout class="QHBoxLayout" name="horizontalLayout_3">
@@ -689,8 +674,11 @@
             </item>
             <item>
              <widget class="QRadioButton" name="remoteSolverR">
+              <property name="enabled">
+               <bool>false</bool>
+              </property>
               <property name="toolTip">
-               <string>Use astrometry solver on remote machine running INDI server.</string>
+               <string>Use astrometry solver on remote machine running INDI server. You must select INDI Astrometry driver from Auxiliary drivers in your Ekos devices profile for this option to be enabled.</string>
               </property>
               <property name="text">
                <string>Remote</string>
@@ -720,655 +708,193 @@
        </item>
       </layout>
      </item>
-     <item>
-      <layout class="QVBoxLayout" name="rightLayout" stretch="2,1">
-       <item>
-        <widget class="QWidget" name="alignWidget" native="true">
-         <property name="sizePolicy">
-          <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-           <horstretch>0</horstretch>
-           <verstretch>0</verstretch>
-          </sizepolicy>
-         </property>
-         <property name="minimumSize">
-          <size>
-           <width>320</width>
-           <height>240</height>
-          </size>
-         </property>
-        </widget>
-       </item>
-       <item>
-        <widget class="QGroupBox" name="polarAlignmentHelperGroup">
-         <property name="enabled">
-          <bool>true</bool>
-         </property>
-         <property name="minimumSize">
-          <size>
-           <width>0</width>
-           <height>150</height>
-          </size>
-         </property>
-         <property name="title">
-          <string>Polar Alignment Assistant (Beta)</string>
-         </property>
-         <layout class="QVBoxLayout" name="verticalLayout_6">
-          <property name="spacing">
-           <number>3</number>
-          </property>
-          <property name="leftMargin">
-           <number>3</number>
-          </property>
-          <property name="topMargin">
-           <number>3</number>
-          </property>
-          <property name="rightMargin">
-           <number>3</number>
-          </property>
-          <property name="bottomMargin">
-           <number>3</number>
-          </property>
-          <item>
-           <widget class="QStackedWidget" name="PAHWidgets">
-            <property name="enabled">
-             <bool>false</bool>
-            </property>
-            <property name="toolTip">
-             <string><p>Polar Alignment Helper tool requires the following:</p><p>1. German Equatorial Mount</p><p>2. Wide FOV &gt; 1 degrees</p><p>For small FOVs, use the Legacy Polar Alignment Tool.</p></string>
-            </property>
-            <property name="frameShape">
-             <enum>QFrame::NoFrame</enum>
-            </property>
-            <property name="currentIndex">
-             <number>0</number>
-            </property>
-            <widget class="QWidget" name="PAHIntroPage">
-             <layout class="QVBoxLayout" name="verticalLayout_3">
-              <property name="spacing">
-               <number>3</number>
-              </property>
-              <property name="leftMargin">
-               <number>3</number>
-              </property>
-              <property name="topMargin">
-               <number>3</number>
-              </property>
-              <property name="rightMargin">
-               <number>3</number>
-              </property>
-              <property name="bottomMargin">
-               <number>3</number>
-              </property>
-              <item>
-               <widget class="QLabel" name="label_5">
-                <property name="text">
-                 <string><html><head/><body><p>This tool provides a simple method to polar align a German equatorial mount. <span style=" font-weight:600;">Unpark</span> your mount, <span style=" font-weight:600;">Point</span> toward the celestial pole, and <span style=" font-weight:600;">Engage</span> sidereal tracking.</p><p>Click <span style=" font-weight:600;">Start</span> to begin the process.</p></body></html></string>
-                </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_10">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <item>
-                 <widget class="QLabel" name="FOVDisabledLabel">
-                  <property name="text">
-                   <string><html><head/><body><p><span style=" font-weight:600; color:#ff5500;">Disabled: FOV must be 30 arcmins or wider.</span></p></body></html></string>
-                  </property>
-                  <property name="textFormat">
-                   <enum>Qt::RichText</enum>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <spacer name="horizontalSpacer_5">
-                  <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="QPushButton" name="PAHStartB">
-                  <property name="text">
-                   <string>Start</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-            <widget class="QWidget" name="PAHFirstCapturePage">
-             <layout class="QVBoxLayout" name="verticalLayout_5">
-              <property name="spacing">
-               <number>3</number>
-              </property>
-              <property name="leftMargin">
-               <number>3</number>
-              </property>
-              <property name="topMargin">
-               <number>3</number>
-              </property>
-              <property name="rightMargin">
-               <number>3</number>
-              </property>
-              <property name="bottomMargin">
-               <number>3</number>
-              </property>
-              <item>
-               <widget class="QLabel" name="label">
-                <property name="text">
-                 <string><html><head/><body><p>The assistant requires three images to find a solution. The first image shall now be captured and solved. Click <span style=" font-weight:600;">Capture</span> to start.</p></body></html></string>
-                </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_2">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <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="QPushButton" name="PAHFirstCaptureB">
-                  <property name="text">
-                   <string>Capture</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-            <widget class="QWidget" name="PAHFirstRotatePage">
-             <layout class="QVBoxLayout" name="verticalLayout_9">
-              <property name="spacing">
-               <number>3</number>
-              </property>
-              <property name="leftMargin">
-               <number>3</number>
-              </property>
-              <property name="topMargin">
-               <number>3</number>
-              </property>
-              <property name="rightMargin">
-               <number>3</number>
-              </property>
-              <property name="bottomMargin">
-               <number>3</number>
-              </property>
-              <item>
-               <widget class="QLabel" name="label_19">
-                <property name="text">
-                 <string><html><head/><body><p>Select direction and range of <span style=" font-style:italic;">first</span> mount rotation, then click <span style=" font-weight:600;">Rotate</span> to continue. To automate the rest of the process, check <span style=" font-weight:600;">Auto Mode</span>.</p></body></html></string>
-                </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_4">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <item>
-                 <widget class="QRadioButton" name="PAHFirstWestMeridianR">
-                  <property name="text">
-                   <string>West</string>
-                  </property>
-                  <property name="checked">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QRadioButton" name="PAHFirstEastMeridianR">
-                  <property name="text">
-                   <string>East</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QSpinBox" name="PAHFirstRotationSpin">
-                  <property name="minimum">
-                   <number>15</number>
-                  </property>
-                  <property name="maximum">
-                   <number>60</number>
-                  </property>
-                  <property name="singleStep">
-                   <number>15</number>
-                  </property>
-                  <property name="value">
-                   <number>30</number>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QLabel" name="label_11">
-                  <property name="text">
-                   <string>°</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <spacer name="horizontalSpacer_3">
-                  <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="QCheckBox" name="PAHAutoModeCheck">
-                  <property name="toolTip">
-                   <string><html><head/><body><p>Perform the remaining steps automatically</p></body></html></string>
-                  </property>
-                  <property name="text">
-                   <string>Auto Mode</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QPushButton" name="PAHFirstRotateB">
-                  <property name="text">
-                   <string>Rotate</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-            <widget class="QWidget" name="PAHSecondCapturePage">
-             <layout class="QVBoxLayout" name="verticalLayout_12">
-              <property name="spacing">
-               <number>3</number>
-              </property>
-              <property name="leftMargin">
-               <number>3</number>
-              </property>
-              <property name="topMargin">
-               <number>3</number>
-              </property>
-              <property name="rightMargin">
-               <number>3</number>
-              </property>
-              <property name="bottomMargin">
-               <number>3</number>
-              </property>
-              <item>
-               <widget class="QLabel" name="label_20">
-                <property name="text">
-                 <string><html><head/><body><p>The second image shall now be captured and solved. Click <span style=" font-weight:600;">Capture</span> to start.</p></body></html></string>
-                </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_7">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <item>
-                 <spacer name="horizontalSpacer_4">
-                  <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="QPushButton" name="PAHSecondCaptureB">
-                  <property name="text">
-                   <string>Capture</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-            <widget class="QWidget" name="PAHSecondRotatePage">
-             <layout class="QVBoxLayout" name="verticalLayout_16">
-              <item>
-               <widget class="QLabel" name="label_27">
-                <property name="text">
-                 <string><html><head/><body><p>Select direction and range of final mount rotation, then click <span style=" font-weight:600;">Rotate</span> to continue.</p></body></html></string>
-                </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_17">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <item>
-                 <widget class="QRadioButton" name="PAHSecondWestMeridianR">
-                  <property name="text">
-                   <string>West</string>
-                  </property>
-                  <property name="checked">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QRadioButton" name="PAHSecondEastMeridianR">
-                  <property name="text">
-                   <string>East</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QSpinBox" name="PAHSecondRotationSpin">
-                  <property name="minimum">
-                   <number>15</number>
-                  </property>
-                  <property name="maximum">
-                   <number>60</number>
-                  </property>
-                  <property name="singleStep">
-                   <number>15</number>
-                  </property>
-                  <property name="value">
-                   <number>30</number>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QLabel" name="label_25">
-                  <property name="text">
-                   <string>°</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <spacer name="horizontalSpacer_9">
-                  <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="QPushButton" name="PAHSecondRotateB">
-                  <property name="text">
-                   <string>Rotate</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-            <widget class="QWidget" name="PAHThirdCapturePage">
-             <layout class="QVBoxLayout" name="verticalLayout_17">
-              <item>
-               <widget class="QLabel" name="label_28">
-                <property name="text">
-                 <string><html><head/><body><p>The final image shall now be captured and solved. Click <span style=" font-weight:600;">Capture</span> to start.</p></body></html></string>
-                </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_18">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <item>
-                 <spacer name="horizontalSpacer_10">
-                  <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="QPushButton" name="PAHThirdCaptureB">
-                  <property name="text">
-                   <string>Capture</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-            <widget class="QWidget" name="PAHErrorPage">
-             <layout class="QVBoxLayout" name="verticalLayout_13">
-              <property name="spacing">
-               <number>3</number>
-              </property>
-              <property name="leftMargin">
-               <number>3</number>
-              </property>
-              <property name="topMargin">
-               <number>3</number>
-              </property>
-              <property name="rightMargin">
-               <number>3</number>
-              </property>
-              <property name="bottomMargin">
-               <number>3</number>
-              </property>
-              <item>
-               <widget class="QLabel" name="PAHErrorDescriptionLabel">
-                <property name="text">
-                 <string>Error Occurred</string>
-                </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
-                </property>
-               </widget>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_13">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <item>
-                 <spacer name="horizontalSpacer_6">
-                  <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="QPushButton" name="pushButton">
-                  <property name="text">
-                   <string>Restart</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-            <widget class="QWidget" name="PAHCorrectionPage">
-             <layout class="QVBoxLayout" name="verticalLayout_14">
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_14">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <item>
-                 <widget class="QLabel" name="label_23">
-                  <property name="toolTip">
-                   <string><html><head/><body><p>Angle between expected perfectly aligned mount center and the actual center</p></body></html></string>
-                  </property>
-                  <property name="text">
-                   <string>Polar Error:</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QLabel" name="PAHErrorLabel">
-                  <property name="text">
-                   <string>0</string>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <spacer name="horizontalSpacer_8">
-                  <property name="orientation">
-                   <enum>Qt::Horizontal</enum>
-                  </property>
-                  <property name="sizeHint" stdset="0">
-                   <size>
-                    <width>40</width>
-                    <height>20</height>
-                   </size>
-                  </property>
-                 </spacer>
-                </item>
-               </layout>
-              </item>
-              <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_16">
-                <property name="spacing">
-                 <number>3</number>
-                </property>
-                <item>
-                 <widget class="QLabel" name="label_26">
-                  <property name="sizePolicy">
-                   <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
-                    <horstretch>0</horstretch>
-                    <verstretch>0</verstretch>
-                   </sizepolicy>
-                  </property>
-                  <property name="text">
-                   <string><html><head/><body><p>Correction vector is plotted above. Select a bright star to reposition the correction vector. Click <span style=" font-weight:600;">Next</span> when done.</p></body></html></string>
-                  </property>
-                  <property name="wordWrap">
-                   <bool>true</bool>
-                  </property>
-                 </widget>
-                </item>
-                <item>
-                 <widget class="QPushButton" name="PAHCorrectionsNextB">
-                  <property name="text">
-                   <string>Next</string>
-                  </property>
-                 </widget>
-                </item>
-               </layout>
-              </item>
-             </layout>
-            </widget>
-            <widget class="QWidget" name="PAHRefreshPage">
-             <layout class="QVBoxLayout" name="verticalLayout_15">
+     <item>
+      <widget class="QSplitter" name="rightLayout">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="orientation">
+        <enum>Qt::Vertical</enum>
+       </property>
+       <widget class="QWidget" name="alignWidget" native="true">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="minimumSize">
+         <size>
+          <width>320</width>
+          <height>240</height>
+         </size>
+        </property>
+       </widget>
+       <widget class="QTabWidget" name="tabWidget">
+        <property name="currentIndex">
+         <number>0</number>
+        </property>
+        <widget class="QWidget" name="solutionResults">
+         <attribute name="title">
+          <string>Solution Results</string>
+         </attribute>
+         <layout class="QVBoxLayout" name="verticalLayout_11">
+          <property name="spacing">
+           <number>5</number>
+          </property>
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
+          <item>
+           <widget class="QLabel" name="label_15">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="text">
+             <string><html><head/><body><p>The resuls from Astrometric Solutions from the Capture and Solve Tool, the Load and Slew Tool, and the Mount Model Tool will be displayed below.</p></body></html></string>
+            </property>
+            <property name="wordWrap">
+             <bool>true</bool>
+            </property>
+           </widget>
+          </item>
+          <item>
+           <widget class="QSplitter" name="alignSplitter">
+            <property name="sizePolicy">
+             <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+              <horstretch>0</horstretch>
+              <verstretch>0</verstretch>
+             </sizepolicy>
+            </property>
+            <property name="orientation">
+             <enum>Qt::Horizontal</enum>
+            </property>
+            <widget class="QWidget" name="verticalLayoutWidget">
+             <layout class="QVBoxLayout" name="verticalLayout_20">
               <property name="spacing">
-               <number>3</number>
-              </property>
-              <property name="leftMargin">
-               <number>3</number>
-              </property>
-              <property name="topMargin">
-               <number>3</number>
+               <number>0</number>
               </property>
               <property name="rightMargin">
-               <number>3</number>
-              </property>
-              <property name="bottomMargin">
-               <number>3</number>
+               <number>0</number>
               </property>
               <item>
-               <widget class="QLabel" name="label_24">
-                <property name="text">
-                 <string><html><head/><body><p>Adjust mount's Altitude and Azimuth knobs until the selected star is centered within the crosshair. Click <span style=" font-weight:600;">Refresh</span> to begin continuous capture. Click <span style=" font-weight:600;">Done</span> when star is centered.</p></body></html></string>
-                </property>
-                <property name="wordWrap">
-                 <bool>true</bool>
+               <widget class="QTableWidget" name="solutionTable">
+                <property name="columnCount">
+                 <number>6</number>
                 </property>
+                <attribute name="horizontalHeaderDefaultSectionSize">
+                 <number>75</number>
+                </attribute>
+                <column>
+                 <property name="text">
+                  <string>RA</string>
+                 </property>
+                 <property name="textAlignment">
+                  <set>AlignCenter</set>
+                 </property>
+                </column>
+                <column>
+                 <property name="text">
+                  <string>Dec</string>
+                 </property>
+                 <property name="textAlignment">
+                  <set>AlignCenter</set>
+                 </property>
+                </column>
+                <column>
+                 <property name="text">
+                  <string>Obj Name</string>
+                 </property>
+                 <property name="textAlignment">
+                  <set>AlignCenter</set>
+                 </property>
+                </column>
+                <column>
+                 <property name="text">
+                  <string>~~</string>
+                 </property>
+                 <property name="textAlignment">
+                  <set>AlignCenter</set>
+                 </property>
+                </column>
+                <column>
+                 <property name="text">
+                  <string>dRA</string>
+                 </property>
+                 <property name="textAlignment">
+                  <set>AlignCenter</set>
+                 </property>
+                </column>
+                <column>
+                 <property name="text">
+                  <string>dDE</string>
+                 </property>
+                 <property name="textAlignment">
+                  <set>AlignCenter</set>
+                 </property>
+                </column>
                </widget>
               </item>
               <item>
-               <layout class="QHBoxLayout" name="horizontalLayout_15">
-                <property name="spacing">
-                 <number>3</number>
+               <layout class="QHBoxLayout" name="horizontalLayout_19">
+                <property name="topMargin">
+                 <number>0</number>
                 </property>
                 <item>
-                 <widget class="QPushButton" name="PAHRefreshB">
+                 <widget class="QPushButton" name="clearAllSolutionsB">
+                  <property name="minimumSize">
+                   <size>
+                    <width>32</width>
+                    <height>32</height>
+                   </size>
+                  </property>
+                  <property name="maximumSize">
+                   <size>
+                    <width>32</width>
+                    <height>32</height>
+                   </size>
+                  </property>
                   <property name="text">
-                   <string>Refresh</string>
+                   <string/>
                   </property>
                  </widget>
                 </item>
                 <item>
-                 <widget class="QSpinBox" name="PAHExposure">
-                  <property name="toolTip">
-                   <string>Exposure duration in seconds during refresh phase</string>
+                 <widget class="QPushButton" name="removeSolutionB">
+                  <property name="minimumSize">
+                   <size>
+                    <width>32</width>
+                    <height>32</height>
+                   </size>
                   </property>
-                  <property name="minimum">
-                   <number>1</number>
+                  <property name="maximumSize">
+                   <size>
+                    <width>32</width>
+                    <height>33</height>
+                   </size>
                   </property>
-                  <property name="maximum">
-                   <number>30</number>
+                  <property name="text">
+                   <string/>
                   </property>
                  </widget>
                 </item>
                 <item>
-                 <spacer name="horizontalSpacer_7">
+                 <spacer name="horizontalSpacer_11">
                   <property name="orientation">
                    <enum>Qt::Horizontal</enum>
                   </property>
@@ -1381,9 +907,9 @@
                  </spacer>
                 </item>
                 <item>
-                 <widget class="QPushButton" name="PAHDoneB">
+                 <widget class="QPushButton" name="mountModelB">
                   <property name="text">
-                   <string>Done</string>
+                   <string>Mount Model</string>
                   </property>
                  </widget>
                 </item>
@@ -1391,128 +917,825 @@
               </item>
              </layout>
             </widget>
+            <widget class="QCustomPlot" name="alignPlot" native="true">
+             <property name="sizePolicy">
+              <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+               <horstretch>0</horstretch>
+               <verstretch>0</verstretch>
+              </sizepolicy>
+             </property>
+             <property name="minimumSize">
+              <size>
+               <width>100</width>
+               <height>100</height>
+              </size>
+             </property>
+             <property name="baseSize">
+              <size>
+               <width>190</width>
+               <height>190</height>
+              </size>
+             </property>
+            </widget>
            </widget>
           </item>
+         </layout>
+        </widget>
+        <widget class="QWidget" name="polarAlignment">
+         <attribute name="title">
+          <string>Polar Alignment</string>
+         </attribute>
+         <layout class="QVBoxLayout" name="verticalLayout_18">
+          <property name="leftMargin">
+           <number>0</number>
+          </property>
+          <property name="topMargin">
+           <number>0</number>
+          </property>
+          <property name="rightMargin">
+           <number>0</number>
+          </property>
+          <property name="bottomMargin">
+           <number>0</number>
+          </property>
           <item>
-           <widget class="QPushButton" name="PAHRestartB">
-            <property name="text">
-             <string>Restart</string>
+           <widget class="QGroupBox" name="polarAlignmentHelperGroup">
+            <property name="enabled">
+             <bool>true</bool>
             </property>
-           </widget>
-          </item>
-          <item>
-           <widget class="QGroupBox" name="polarAlignmentGroup">
-            <property name="title">
-             <string>Legacy Polar Alignment Tool</string>
+            <property name="minimumSize">
+             <size>
+              <width>0</width>
+              <height>150</height>
+             </size>
             </property>
-            <property name="alignment">
-             <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+            <property name="title">
+             <string>Polar Alignment Assistant (Beta)</string>
             </property>
-            <layout class="QHBoxLayout" name="horizontalLayout_9">
+            <layout class="QVBoxLayout" name="verticalLayout_6">
+             <property name="spacing">
+              <number>3</number>
+             </property>
+             <property name="leftMargin">
+              <number>3</number>
+             </property>
+             <property name="topMargin">
+              <number>3</number>
+             </property>
+             <property name="rightMargin">
+              <number>3</number>
+             </property>
+             <property name="bottomMargin">
+              <number>3</number>
+             </property>
              <item>
-              <layout class="QVBoxLayout" name="verticalLayout_8">
-               <item>
-                <layout class="QHBoxLayout" name="horizontalLayout_6">
+              <widget class="QStackedWidget" name="PAHWidgets">
+               <property name="enabled">
+                <bool>false</bool>
+               </property>
+               <property name="toolTip">
+                <string><p>Polar Alignment Helper tool requires the following:</p><p>1. German Equatorial Mount</p><p>2. Wide FOV &gt; 1 degrees</p><p>For small FOVs, use the Legacy Polar Alignment Tool.</p></string>
+               </property>
+               <property name="frameShape">
+                <enum>QFrame::NoFrame</enum>
+               </property>
+               <property name="currentIndex">
+                <number>0</number>
+               </property>
+               <widget class="QWidget" name="PAHIntroPage">
+                <layout class="QVBoxLayout" name="verticalLayout_3">
                  <property name="spacing">
                   <number>3</number>
                  </property>
+                 <property name="leftMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="topMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="rightMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="bottomMargin">
+                  <number>3</number>
+                 </property>
                  <item>
-                  <widget class="QLabel" name="label_3">
+                  <widget class="QLabel" name="label_5">
                    <property name="text">
-                    <string>Az Error:</string>
+                    <string><html><head/><body><p>This tool provides a simple method to polar align a German equatorial mount. <span style=" font-weight:600;">Unpark</span> your mount, <span style=" font-weight:600;">Point</span> toward the celestial pole, and <span style=" font-weight:600;">Engage</span> sidereal tracking.</p><p>Click <span style=" font-weight:600;">Start</span> to begin the process.</p></body></html></string>
+                   </property>
+                   <property name="wordWrap">
+                    <bool>true</bool>
                    </property>
                   </widget>
                  </item>
                  <item>
-                  <widget class="QLineEdit" name="azError">
-                   <property name="readOnly">
+                  <layout class="QHBoxLayout" name="horizontalLayout_10">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <widget class="QLabel" name="FOVDisabledLabel">
+                     <property name="text">
+                      <string><html><head/><body><p><span style=" font-weight:600; color:#ff5500;">Disabled: FOV must be 30 arcmins or wider.</span></p></body></html></string>
+                     </property>
+                     <property name="textFormat">
+                      <enum>Qt::RichText</enum>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <spacer name="horizontalSpacer_5">
+                     <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="QPushButton" name="PAHStartB">
+                     <property name="text">
+                      <string>Start</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
+                </layout>
+               </widget>
+               <widget class="QWidget" name="PAHFirstCapturePage">
+                <layout class="QVBoxLayout" name="verticalLayout_5">
+                 <property name="spacing">
+                  <number>3</number>
+                 </property>
+                 <property name="leftMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="topMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="rightMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="bottomMargin">
+                  <number>3</number>
+                 </property>
+                 <item>
+                  <widget class="QLabel" name="label">
+                   <property name="text">
+                    <string><html><head/><body><p>The assistant requires three images to find a solution. The first image shall now be captured and solved. Click <span style=" font-weight:600;">Capture</span> to start.</p></body></html></string>
+                   </property>
+                   <property name="wordWrap">
                     <bool>true</bool>
                    </property>
                   </widget>
                  </item>
+                 <item>
+                  <layout class="QHBoxLayout" name="horizontalLayout_2">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <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="QPushButton" name="PAHFirstCaptureB">
+                     <property name="text">
+                      <string>Capture</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
                 </layout>
-               </item>
-               <item>
-                <widget class="QPushButton" name="measureAzB">
-                 <property name="enabled">
-                  <bool>true</bool>
+               </widget>
+               <widget class="QWidget" name="PAHFirstRotatePage">
+                <layout class="QVBoxLayout" name="verticalLayout_9">
+                 <property name="spacing">
+                  <number>3</number>
                  </property>
-                 <property name="text">
-                  <string>Measure Az Error</string>
+                 <property name="leftMargin">
+                  <number>3</number>
                  </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QPushButton" name="correctAzB">
-                 <property name="enabled">
-                  <bool>false</bool>
+                 <property name="topMargin">
+                  <number>3</number>
                  </property>
-                 <property name="text">
-                  <string>Correct Az Error</string>
+                 <property name="rightMargin">
+                  <number>3</number>
                  </property>
-                </widget>
-               </item>
-              </layout>
-             </item>
-             <item>
-              <widget class="Line" name="line_2">
-               <property name="orientation">
-                <enum>Qt::Vertical</enum>
-               </property>
-              </widget>
-             </item>
-             <item>
-              <layout class="QVBoxLayout" name="verticalLayout_10">
-               <item>
-                <layout class="QHBoxLayout" name="horizontalLayout_8">
+                 <property name="bottomMargin">
+                  <number>3</number>
+                 </property>
+                 <item>
+                  <widget class="QLabel" name="label_19">
+                   <property name="text">
+                    <string><html><head/><body><p>Select direction and range of <span style=" font-style:italic;">first</span> mount rotation, then click <span style=" font-weight:600;">Rotate</span> to continue. To automate the rest of the process, check <span style=" font-weight:600;">Auto Mode</span>.</p></body></html></string>
+                   </property>
+                   <property name="wordWrap">
+                    <bool>true</bool>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <layout class="QHBoxLayout" name="horizontalLayout_4">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <widget class="QRadioButton" name="PAHFirstWestMeridianR">
+                     <property name="text">
+                      <string>West</string>
+                     </property>
+                     <property name="checked">
+                      <bool>true</bool>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QRadioButton" name="PAHFirstEastMeridianR">
+                     <property name="text">
+                      <string>East</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QSpinBox" name="PAHFirstRotationSpin">
+                     <property name="minimum">
+                      <number>15</number>
+                     </property>
+                     <property name="maximum">
+                      <number>60</number>
+                     </property>
+                     <property name="singleStep">
+                      <number>15</number>
+                     </property>
+                     <property name="value">
+                      <number>30</number>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QLabel" name="label_11">
+                     <property name="text">
+                      <string>°</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <spacer name="horizontalSpacer_3">
+                     <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="QCheckBox" name="PAHAutoModeCheck">
+                     <property name="toolTip">
+                      <string><html><head/><body><p>Perform the remaining steps automatically</p></body></html></string>
+                     </property>
+                     <property name="text">
+                      <string>Auto Mode</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QPushButton" name="PAHFirstRotateB">
+                     <property name="text">
+                      <string>Rotate</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
+                </layout>
+               </widget>
+               <widget class="QWidget" name="PAHSecondCapturePage">
+                <layout class="QVBoxLayout" name="verticalLayout_12">
                  <property name="spacing">
                   <number>3</number>
                  </property>
+                 <property name="leftMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="topMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="rightMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="bottomMargin">
+                  <number>3</number>
+                 </property>
+                 <item>
+                  <widget class="QLabel" name="label_20">
+                   <property name="text">
+                    <string><html><head/><body><p>The second image shall now be captured and solved. Click <span style=" font-weight:600;">Capture</span> to start.</p></body></html></string>
+                   </property>
+                   <property name="wordWrap">
+                    <bool>true</bool>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <layout class="QHBoxLayout" name="horizontalLayout_7">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <spacer name="horizontalSpacer_4">
+                     <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="QPushButton" name="PAHSecondCaptureB">
+                     <property name="text">
+                      <string>Capture</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
+                </layout>
+               </widget>
+               <widget class="QWidget" name="PAHSecondRotatePage">
+                <layout class="QVBoxLayout" name="verticalLayout_16">
                  <item>
-                  <widget class="QLabel" name="label_4">
+                  <widget class="QLabel" name="label_27">
                    <property name="text">
-                    <string>Alt Error:</string>
+                    <string><html><head/><body><p>Select direction and range of final mount rotation, then click <span style=" font-weight:600;">Rotate</span> to continue.</p></body></html></string>
+                   </property>
+                   <property name="wordWrap">
+                    <bool>true</bool>
                    </property>
                   </widget>
                  </item>
                  <item>
-                  <widget class="QLineEdit" name="altError">
-                   <property name="readOnly">
+                  <layout class="QHBoxLayout" name="horizontalLayout_17">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <widget class="QRadioButton" name="PAHSecondWestMeridianR">
+                     <property name="text">
+                      <string>West</string>
+                     </property>
+                     <property name="checked">
+                      <bool>true</bool>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QRadioButton" name="PAHSecondEastMeridianR">
+                     <property name="text">
+                      <string>East</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QSpinBox" name="PAHSecondRotationSpin">
+                     <property name="minimum">
+                      <number>15</number>
+                     </property>
+                     <property name="maximum">
+                      <number>60</number>
+                     </property>
+                     <property name="singleStep">
+                      <number>15</number>
+                     </property>
+                     <property name="value">
+                      <number>30</number>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QLabel" name="label_25">
+                     <property name="text">
+                      <string>°</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <spacer name="horizontalSpacer_9">
+                     <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="QPushButton" name="PAHSecondRotateB">
+                     <property name="text">
+                      <string>Rotate</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
+                </layout>
+               </widget>
+               <widget class="QWidget" name="PAHThirdCapturePage">
+                <layout class="QVBoxLayout" name="verticalLayout_17">
+                 <item>
+                  <widget class="QLabel" name="label_28">
+                   <property name="text">
+                    <string><html><head/><body><p>The final image shall now be captured and solved. Click <span style=" font-weight:600;">Capture</span> to start.</p></body></html></string>
+                   </property>
+                   <property name="wordWrap">
                     <bool>true</bool>
                    </property>
                   </widget>
                  </item>
+                 <item>
+                  <layout class="QHBoxLayout" name="horizontalLayout_18">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <spacer name="horizontalSpacer_10">
+                     <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="QPushButton" name="PAHThirdCaptureB">
+                     <property name="text">
+                      <string>Capture</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
                 </layout>
-               </item>
-               <item>
-                <widget class="QPushButton" name="measureAltB">
-                 <property name="enabled">
-                  <bool>true</bool>
+               </widget>
+               <widget class="QWidget" name="PAHErrorPage">
+                <layout class="QVBoxLayout" name="verticalLayout_13">
+                 <property name="spacing">
+                  <number>3</number>
                  </property>
-                 <property name="text">
-                  <string>Measure Alt Error</string>
+                 <property name="leftMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="topMargin">
+                  <number>3</number>
                  </property>
-                </widget>
-               </item>
-               <item>
-                <widget class="QPushButton" name="correctAltB">
-                 <property name="enabled">
-                  <bool>false</bool>
+                 <property name="rightMargin">
+                  <number>3</number>
                  </property>
-                 <property name="text">
-                  <string>Correct Alt Error</string>
+                 <property name="bottomMargin">
+                  <number>3</number>
+                 </property>
+                 <item>
+                  <widget class="QLabel" name="PAHErrorDescriptionLabel">
+                   <property name="text">
+                    <string>Error Occurred</string>
+                   </property>
+                   <property name="wordWrap">
+                    <bool>true</bool>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <layout class="QHBoxLayout" name="horizontalLayout_13">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <spacer name="horizontalSpacer_6">
+                     <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="QPushButton" name="pushButton">
+                     <property name="text">
+                      <string>Restart</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
+                </layout>
+               </widget>
+               <widget class="QWidget" name="PAHCorrectionPage">
+                <layout class="QVBoxLayout" name="verticalLayout_14">
+                 <item>
+                  <layout class="QHBoxLayout" name="horizontalLayout_14">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <widget class="QLabel" name="label_23">
+                     <property name="toolTip">
+                      <string><html><head/><body><p>Angle between expected perfectly aligned mount center and the actual center</p></body></html></string>
+                     </property>
+                     <property name="text">
+                      <string>Polar Error:</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QLabel" name="PAHErrorLabel">
+                     <property name="text">
+                      <string>0</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <spacer name="horizontalSpacer_8">
+                     <property name="orientation">
+                      <enum>Qt::Horizontal</enum>
+                     </property>
+                     <property name="sizeHint" stdset="0">
+                      <size>
+                       <width>40</width>
+                       <height>20</height>
+                      </size>
+                     </property>
+                    </spacer>
+                   </item>
+                  </layout>
+                 </item>
+                 <item>
+                  <layout class="QHBoxLayout" name="horizontalLayout_16">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <widget class="QLabel" name="label_26">
+                     <property name="sizePolicy">
+                      <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
+                       <horstretch>0</horstretch>
+                       <verstretch>0</verstretch>
+                      </sizepolicy>
+                     </property>
+                     <property name="text">
+                      <string><html><head/><body><p>Correction vector is plotted above. Select a bright star to reposition the correction vector. Click <span style=" font-weight:600;">Next</span> when done.</p></body></html></string>
+                     </property>
+                     <property name="wordWrap">
+                      <bool>true</bool>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QPushButton" name="PAHCorrectionsNextB">
+                     <property name="text">
+                      <string>Next</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
+                </layout>
+               </widget>
+               <widget class="QWidget" name="PAHRefreshPage">
+                <layout class="QVBoxLayout" name="verticalLayout_15">
+                 <property name="spacing">
+                  <number>3</number>
+                 </property>
+                 <property name="leftMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="topMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="rightMargin">
+                  <number>3</number>
+                 </property>
+                 <property name="bottomMargin">
+                  <number>3</number>
                  </property>
-                </widget>
-               </item>
-              </layout>
+                 <item>
+                  <widget class="QLabel" name="label_24">
+                   <property name="text">
+                    <string><html><head/><body><p>Adjust mount's Altitude and Azimuth knobs until the selected star is centered within the crosshair. Click <span style=" font-weight:600;">Refresh</span> to begin continuous capture. Click <span style=" font-weight:600;">Done</span> when star is centered.</p></body></html></string>
+                   </property>
+                   <property name="wordWrap">
+                    <bool>true</bool>
+                   </property>
+                  </widget>
+                 </item>
+                 <item>
+                  <layout class="QHBoxLayout" name="horizontalLayout_15">
+                   <property name="spacing">
+                    <number>3</number>
+                   </property>
+                   <item>
+                    <widget class="QPushButton" name="PAHRefreshB">
+                     <property name="text">
+                      <string>Refresh</string>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <widget class="QSpinBox" name="PAHExposure">
+                     <property name="toolTip">
+                      <string>Exposure duration in seconds during refresh phase</string>
+                     </property>
+                     <property name="minimum">
+                      <number>1</number>
+                     </property>
+                     <property name="maximum">
+                      <number>30</number>
+                     </property>
+                    </widget>
+                   </item>
+                   <item>
+                    <spacer name="horizontalSpacer_7">
+                     <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="QPushButton" name="PAHDoneB">
+                     <property name="text">
+                      <string>Done</string>
+                     </property>
+                    </widget>
+                   </item>
+                  </layout>
+                 </item>
+                </layout>
+               </widget>
+              </widget>
+             </item>
+             <item>
+              <widget class="QPushButton" name="PAHRestartB">
+               <property name="text">
+                <string>Restart</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QGroupBox" name="polarAlignmentGroup">
+               <property name="title">
+                <string>Legacy Polar Alignment Tool</string>
+               </property>
+               <property name="alignment">
+                <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+               </property>
+               <layout class="QHBoxLayout" name="horizontalLayout_9">
+                <item>
+                 <layout class="QVBoxLayout" name="verticalLayout_8">
+                  <item>
+                   <layout class="QHBoxLayout" name="horizontalLayout_6">
+                    <property name="spacing">
+                     <number>3</number>
+                    </property>
+                    <item>
+                     <widget class="QLabel" name="label_3">
+                      <property name="text">
+                       <string>Az Error:</string>
+                      </property>
+                     </widget>
+                    </item>
+                    <item>
+                     <widget class="QLineEdit" name="azError">
+                      <property name="readOnly">
+                       <bool>true</bool>
+                      </property>
+                     </widget>
+                    </item>
+                   </layout>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="measureAzB">
+                    <property name="enabled">
+                     <bool>true</bool>
+                    </property>
+                    <property name="text">
+                     <string>Measure Az Error</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="correctAzB">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="text">
+                     <string>Correct Az Error</string>
+                    </property>
+                   </widget>
+                  </item>
+                 </layout>
+                </item>
+                <item>
+                 <widget class="Line" name="line_2">
+                  <property name="orientation">
+                   <enum>Qt::Vertical</enum>
+                  </property>
+                 </widget>
+                </item>
+                <item>
+                 <layout class="QVBoxLayout" name="verticalLayout_10">
+                  <item>
+                   <layout class="QHBoxLayout" name="horizontalLayout_8">
+                    <property name="spacing">
+                     <number>3</number>
+                    </property>
+                    <item>
+                     <widget class="QLabel" name="label_4">
+                      <property name="text">
+                       <string>Alt Error:</string>
+                      </property>
+                     </widget>
+                    </item>
+                    <item>
+                     <widget class="QLineEdit" name="altError">
+                      <property name="readOnly">
+                       <bool>true</bool>
+                      </property>
+                     </widget>
+                    </item>
+                   </layout>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="measureAltB">
+                    <property name="enabled">
+                     <bool>true</bool>
+                    </property>
+                    <property name="text">
+                     <string>Measure Alt Error</string>
+                    </property>
+                   </widget>
+                  </item>
+                  <item>
+                   <widget class="QPushButton" name="correctAltB">
+                    <property name="enabled">
+                     <bool>false</bool>
+                    </property>
+                    <property name="text">
+                     <string>Correct Alt Error</string>
+                    </property>
+                   </widget>
+                  </item>
+                 </layout>
+                </item>
+               </layout>
+              </widget>
              </item>
             </layout>
            </widget>
           </item>
          </layout>
         </widget>
-       </item>
-      </layout>
+       </widget>
+      </widget>
      </item>
     </layout>
    </item>
@@ -1521,19 +1744,24 @@
      <property name="orientation">
       <enum>Qt::Vertical</enum>
      </property>
-     <property name="sizeType">
-      <enum>QSizePolicy::Preferred</enum>
-     </property>
      <property name="sizeHint" stdset="0">
       <size>
        <width>20</width>
-       <height>10</height>
+       <height>40</height>
       </size>
      </property>
     </spacer>
    </item>
   </layout>
  </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QCustomPlot</class>
+   <extends>QWidget</extends>
+   <header>auxiliary/qcustomplot.h</header>
+   <container>1</container>
+  </customwidget>
+ </customwidgets>
  <tabstops>
   <tabstop>solveB</tabstop>
   <tabstop>loadSlewB</tabstop>
@@ -1571,7 +1799,7 @@
  <resources/>
  <connections/>
  <buttongroups>
-  <buttongroup name="solverTypeGroup"/>
   <buttongroup name="gotoModeButtonGroup"/>
+  <buttongroup name="solverTypeGroup"/>
  </buttongroups>
 </ui>
diff --git a/kstars/ekos/align/mountmodel.ui b/kstars/ekos/align/mountmodel.ui
new file mode 100644
index 000000000..95096c13f
--- /dev/null
+++ b/kstars/ekos/align/mountmodel.ui
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>mountModel</class>
+ <widget class="QDialog" name="mountModel">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>310</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Dialog</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string><html><head/><body><p>The Mount Model Tool uses the Alignment Module to help your mount build a pointing model.  This process is not required for Ekos to function, but for mounts that include an internal pointing model, this can help improve the pointing accuracy.</p></body></html></string>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <property name="topMargin">
+      <number>10</number>
+     </property>
+     <item>
+      <widget class="QPushButton" name="clearAllAlignB">
+       <property name="minimumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="removeAlignB">
+       <property name="minimumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="addAlignB">
+       <property name="minimumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="findAlignB">
+       <property name="minimumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="wizardAlignB">
+       <property name="minimumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QTableWidget" name="alignTable">
+     <column>
+      <property name="text">
+       <string>RA</string>
+      </property>
+      <property name="textAlignment">
+       <set>AlignCenter</set>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>DEC</string>
+      </property>
+      <property name="textAlignment">
+       <set>AlignCenter</set>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>Object</string>
+      </property>
+      <property name="textAlignment">
+       <set>AlignCenter</set>
+      </property>
+     </column>
+     <column>
+      <property name="text">
+       <string>~~</string>
+      </property>
+      <property name="textAlignment">
+       <set>AlignCenter</set>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <spacer name="horizontalSpacer">
+       <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="QPushButton" name="stopAlignB">
+       <property name="minimumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="startAlignB">
+       <property name="minimumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/kstars/ekos/align/remoteastrometryparser.cpp b/kstars/ekos/align/remoteastrometryparser.cpp
index 499437d5d..8800dbf01 100644
--- a/kstars/ekos/align/remoteastrometryparser.cpp
+++ b/kstars/ekos/align/remoteastrometryparser.cpp
@@ -27,7 +27,6 @@ namespace Ekos
 
 RemoteAstrometryParser::RemoteAstrometryParser() : AstrometryParser()
 {
-    currentCCD = NULL;
     solverRunning=false;
 }
 
@@ -37,7 +36,7 @@ RemoteAstrometryParser::~RemoteAstrometryParser()
 
 bool RemoteAstrometryParser::init()
 {    
-    return true;
+    return (remoteAstrometry != NULL);
 }
 
 void RemoteAstrometryParser::verifyIndexFiles(double, double)
@@ -46,17 +45,24 @@ void RemoteAstrometryParser::verifyIndexFiles(double, double)
 
 bool RemoteAstrometryParser::startSovler(const QString &filename,  const QStringList &args, bool generated)
 {
-    INDI_UNUSED(filename);
     INDI_UNUSED(generated);
 
-    solverRunning = true;
+    QFile fp(filename);
+    if (fp.open(QIODevice::ReadOnly) == false)
+    {
+        align->appendLogText(i18n("Cannot open file %1 for reading!", filename));
+        emit solverFailed();
+        return false;
+    }
 
-    ITextVectorProperty *solverSettings = currentCCD->getBaseDevice()->getText("ASTROMETRY_SETTINGS");
-    ISwitchVectorProperty *solverSwitch = currentCCD->getBaseDevice()->getSwitch("ASTROMETRY_SOLVER");
+    ITextVectorProperty *solverSettings = remoteAstrometry->getBaseDevice()->getText("ASTROMETRY_SETTINGS");
+    ISwitchVectorProperty *solverSwitch = remoteAstrometry->getBaseDevice()->getSwitch("ASTROMETRY_SOLVER");
+    IBLOBVectorProperty *solverBLOB = remoteAstrometry->getBaseDevice()->getBLOB("ASTROMETRY_DATA");
 
-    if (solverSettings == NULL || solverSwitch == NULL)
+    if (solverSettings == NULL || solverSwitch == NULL || solverBLOB == NULL)
     {
-        align->appendLogText(i18n("CCD does not support remote solver."));
+        align->appendLogText(i18n("Failed to find solver settings."));
+        fp.close();
         emit solverFailed();
         return false;
     }
@@ -79,8 +85,8 @@ bool RemoteAstrometryParser::startSovler(const QString &filename,  const QString
             IUSaveText(&solverSettings->tp[i], solverArgs.join(" ").toLatin1().constData());
     }
 
-    currentCCD->getDriverInfo()->getClientManager()->sendNewText(solverSettings);
-    INDI_D *guiDevice = GUIManager::Instance()->findGUIDevice(currentCCD->getDeviceName());
+    remoteAstrometry->getDriverInfo()->getClientManager()->sendNewText(solverSettings);
+    INDI_D *guiDevice = GUIManager::Instance()->findGUIDevice(remoteAstrometry->getDeviceName());
     if (guiDevice)
         guiDevice->updateTextGUI(solverSettings);
 
@@ -89,19 +95,64 @@ bool RemoteAstrometryParser::startSovler(const QString &filename,  const QString
     {
         IUResetSwitch(solverSwitch);
         enableSW->s = ISS_ON;
-        currentCCD->getDriverInfo()->getClientManager()->sendNewSwitch(solverSwitch);
+        remoteAstrometry->getDriverInfo()->getClientManager()->sendNewSwitch(solverSwitch);
     }
 
+    IBLOB *bp = &(solverBLOB->bp[0]);
+
+    bp->bloblen = bp->size = fp.size();
+
+    bp->blob = (uint8_t *) realloc (bp->blob, bp->size);
+    if (bp->blob == NULL)
+    {
+        align->appendLogText(i18n("Not enough memory for file %1", filename));
+        fp.close();
+        emit solverFailed();
+        return false;
+    }
+
+    memcpy(bp->blob, fp.readAll().constData(), bp->size);
+
+    solverRunning = true;
+
+    remoteAstrometry->getDriverInfo()->getClientManager()->sendOneBlob(bp);
+
     align->appendLogText(i18n("Starting remote solver..."));
     solverTimer.start();
 
     return true;
 }
 
+void RemoteAstrometryParser::setEnabled(bool enable)
+{
+    ISwitchVectorProperty *solverSwitch = remoteAstrometry->getBaseDevice()->getSwitch("ASTROMETRY_SOLVER");
+    if (solverSwitch == NULL)
+        return;
+
+    ISwitch *enableSW = IUFindSwitch(solverSwitch, "ASTROMETRY_SOLVER_ENABLE");
+    ISwitch *disableSW = IUFindSwitch(solverSwitch, "ASTROMETRY_SOLVER_DISABLE");
+
+    if (enableSW == NULL || disableSW == NULL)
+        return;
+
+    if (enable && enableSW->s == ISS_OFF)
+    {
+        IUResetSwitch(solverSwitch);
+        enableSW->s = ISS_ON;
+        remoteAstrometry->getDriverInfo()->getClientManager()->sendNewSwitch(solverSwitch);
+    }
+    else if (enable == false && disableSW->s == ISS_OFF)
+    {
+        IUResetSwitch(solverSwitch);
+        disableSW->s = ISS_ON;
+        remoteAstrometry->getDriverInfo()->getClientManager()->sendNewSwitch(solverSwitch);
+    }
+}
+
 bool RemoteAstrometryParser::stopSolver()
 {
     // Disable solver
-    ISwitchVectorProperty *svp = currentCCD->getBaseDevice()->getSwitch("ASTROMETRY_SOLVER");
+    ISwitchVectorProperty *svp = remoteAstrometry->getBaseDevice()->getSwitch("ASTROMETRY_SOLVER");
     if (!svp)
         return false;
 
@@ -110,7 +161,7 @@ bool RemoteAstrometryParser::stopSolver()
     {
         IUResetSwitch(svp);
         disableSW->s = ISS_ON;
-        currentCCD->getDriverInfo()->getClientManager()->sendNewSwitch(svp);
+        remoteAstrometry->getDriverInfo()->getClientManager()->sendNewSwitch(svp);
     }
 
     solverRunning=false;
@@ -119,20 +170,20 @@ bool RemoteAstrometryParser::stopSolver()
 
 }
 
-void RemoteAstrometryParser::setCCD(ISD::CCD *ccd)
+void RemoteAstrometryParser::setAstrometryDevice(ISD::GDInterface *device)
 {
-    if (ccd == currentCCD)
+    if (device == remoteAstrometry)
         return;
 
-    currentCCD = ccd;
+    remoteAstrometry = dynamic_cast<ISD::GenericDevice*>(device);
 
-    currentCCD->disconnect(this);
+    remoteAstrometry->disconnect(this);
 
-    connect(currentCCD, SIGNAL(switchUpdated(ISwitchVectorProperty*)), this, SLOT(checkCCDStatus(ISwitchVectorProperty*)));
-    connect(currentCCD, SIGNAL(numberUpdated(INumberVectorProperty*)), this, SLOT(checkCCDResults(INumberVectorProperty*)));
+    connect(remoteAstrometry, SIGNAL(switchUpdated(ISwitchVectorProperty*)), this, SLOT(checkStatus(ISwitchVectorProperty*)));
+    connect(remoteAstrometry, SIGNAL(numberUpdated(INumberVectorProperty*)), this, SLOT(checkResults(INumberVectorProperty*)));
 }
 
-void RemoteAstrometryParser::checkCCDStatus(ISwitchVectorProperty *svp)
+void RemoteAstrometryParser::checkStatus(ISwitchVectorProperty *svp)
 {
     if (solverRunning == false || strcmp(svp->name, "ASTROMETRY_SOLVER"))
         return;
@@ -146,7 +197,7 @@ void RemoteAstrometryParser::checkCCDStatus(ISwitchVectorProperty *svp)
     }
 }
 
-void RemoteAstrometryParser::checkCCDResults(INumberVectorProperty * nvp)
+void RemoteAstrometryParser::checkResults(INumberVectorProperty * nvp)
 {
     if (solverRunning == false || strcmp(nvp->name, "ASTROMETRY_RESULTS") || nvp->s != IPS_OK)
         return;
diff --git a/kstars/ekos/align/remoteastrometryparser.h b/kstars/ekos/align/remoteastrometryparser.h
index d889ba6e5..a53ce08ab 100644
--- a/kstars/ekos/align/remoteastrometryparser.h
+++ b/kstars/ekos/align/remoteastrometryparser.h
@@ -40,14 +40,15 @@ public:
     virtual bool startSovler(const QString &filename, const QStringList &args, bool generated=true);
     virtual bool stopSolver();
 
-    void setCCD(ISD::CCD *ccd);
+    void setAstrometryDevice(ISD::GDInterface *device);
+    void setEnabled(bool enable);
 
 public slots:
-    void checkCCDStatus(ISwitchVectorProperty * svp);
-    void checkCCDResults(INumberVectorProperty * nvp);
+    void checkStatus(ISwitchVectorProperty * svp);
+    void checkResults(INumberVectorProperty * nvp);
 
 private:
-    ISD::CCD *currentCCD;
+    ISD::GenericDevice *remoteAstrometry=NULL;
     bool solverRunning;
     bool captureRunning;
     Align *align;
diff --git a/kstars/ekos/ekosmanager.cpp b/kstars/ekos/ekosmanager.cpp
index 6dac2402a..87982fb78 100644
--- a/kstars/ekos/ekosmanager.cpp
+++ b/kstars/ekos/ekosmanager.cpp
@@ -1339,6 +1339,19 @@ void EkosManager::processNewProperty(INDI::Property* prop)
         return;
     }
 
+    if (!strcmp(prop->getName(), "ASTROMETRY_SOLVER"))
+    {
+        foreach(ISD::GDInterface *device, genericDevices)
+        {
+            if (!strcmp(device->getDeviceName(), prop->getDeviceName()))
+            {
+                initAlign();
+                alignProcess->setAstrometryDevice(device);
+                break;
+            }
+        }
+    }
+
     if (focusProcess && strstr(prop->getName(), "FOCUS_"))
     {
         focusProcess->checkFocuser();


More information about the Kstars-devel mailing list