[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&¤tAlignmentPoint>=0&¤tAlignmentPoint<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&¤tAlignmentPoint>=0&¤tAlignmentPoint<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 > 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 > 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