File indexing completed on 2024-04-28 03:43:41
0001 /* 0002 SPDX-FileCopyrightText: 2022 Jasem Mutlaq <mutlaqja@ikarustech.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "framingassistant.h" 0008 #include "ui_framingassistant.h" 0009 #include "mosaictilesmanager.h" 0010 #include "kstars.h" 0011 #include "Options.h" 0012 #include "scheduler.h" 0013 #include "skymap.h" 0014 #include "ekos/manager.h" 0015 #include "projections/projector.h" 0016 0017 #include "ekos_scheduler_debug.h" 0018 0019 namespace Ekos 0020 { 0021 0022 FramingAssistant* FramingAssistant::Instance() 0023 { 0024 if (_FramingAssistant == nullptr) 0025 { 0026 _FramingAssistant = new FramingAssistant; 0027 } 0028 0029 return _FramingAssistant; 0030 } 0031 0032 FramingAssistant::FramingAssistant(): QDialog(KStars::Instance()), ui(new Ui::FramingAssistant()) 0033 { 0034 ui->setupUi(this); 0035 0036 // Initial optics information is taken from Ekos options 0037 ui->focalLenSpin->setValue(Options::telescopeFocalLength()); 0038 ui->pixelWSizeSpin->setValue(Options::cameraPixelWidth()); 0039 ui->pixelHSizeSpin->setValue(Options::cameraPixelHeight()); 0040 ui->cameraWSpin->setValue(Options::cameraWidth()); 0041 ui->cameraHSpin->setValue(Options::cameraHeight()); 0042 ui->rotationSpin->setValue(Options::cameraRotation()); 0043 0044 // Initial job location is the home path appended with the target name 0045 //ui->jobsDir->setText(QDir::cleanPath(QDir::homePath() + QDir::separator() + targetName.replace(' ', '_'))); 0046 //ui->selectJobsDirB->setIcon(QIcon::fromTheme("document-open-folder")); 0047 0048 // The update timer avoids stacking updates which crash the sky map renderer 0049 updateTimer = new QTimer(this); 0050 updateTimer->setSingleShot(true); 0051 updateTimer->setInterval(1000); 0052 connect(updateTimer, &QTimer::timeout, this, &Ekos::FramingAssistant::constructMosaic); 0053 0054 // Scope optics information 0055 // - Changing the optics configuration changes the FOV, which changes the target field dimensions 0056 connect(ui->focalLenSpin, &QDoubleSpinBox::editingFinished, this, &Ekos::FramingAssistant::calculateFOV); 0057 connect(ui->cameraWSpin, &QSpinBox::editingFinished, this, &Ekos::FramingAssistant::calculateFOV); 0058 connect(ui->cameraHSpin, &QSpinBox::editingFinished, this, &Ekos::FramingAssistant::calculateFOV); 0059 connect(ui->pixelWSizeSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, 0060 &Ekos::FramingAssistant::calculateFOV); 0061 connect(ui->pixelHSizeSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, 0062 &Ekos::FramingAssistant::calculateFOV); 0063 connect(ui->rotationSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, 0064 &Ekos::FramingAssistant::calculateFOV); 0065 0066 // Mosaic configuration 0067 // - Changing the target field dimensions changes the grid dimensions 0068 // - Changing the overlap field changes the grid dimensions (more intuitive than changing the field) 0069 // - Changing the grid dimensions changes the target field dimensions 0070 connect(ui->targetHFOVSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, 0071 &Ekos::FramingAssistant::updateGridFromTargetFOV); 0072 connect(ui->targetWFOVSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, 0073 &Ekos::FramingAssistant::updateGridFromTargetFOV); 0074 connect(ui->overlapSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, 0075 &Ekos::FramingAssistant::updateGridFromTargetFOV); 0076 connect(ui->mosaicWSpin, QOverload<int>::of(&QSpinBox::valueChanged), this, 0077 &Ekos::FramingAssistant::updateTargetFOVFromGrid); 0078 connect(ui->mosaicHSpin, QOverload<int>::of(&QSpinBox::valueChanged), this, 0079 &Ekos::FramingAssistant::updateTargetFOVFromGrid); 0080 0081 // Lazy update for s-shape 0082 connect(ui->reverseOddRows, &QCheckBox::toggled, this, [&]() 0083 { 0084 renderedHFOV = 0; 0085 updateTimer->start(); 0086 }); 0087 0088 // Buttons 0089 connect(ui->resetB, &QPushButton::clicked, this, &Ekos::FramingAssistant::updateTargetFOVFromGrid); 0090 connect(ui->selectJobsDirB, &QPushButton::clicked, this, &Ekos::FramingAssistant::saveJobsDirectory); 0091 connect(ui->fetchB, &QPushButton::clicked, this, &FramingAssistant::fetchINDIInformation); 0092 0093 // The sky map is a pixmap background, and the mosaic tiles are rendered over it 0094 //m_TilesScene = new MosaicTilesScene(this); 0095 m_SkyPixmapItem = m_TilesScene.addPixmap(targetPix); 0096 m_SkyPixmapItem->setTransformationMode(Qt::TransformationMode::SmoothTransformation); 0097 m_MosaicTilesManager = new MosaicTilesManager(this); 0098 connect(m_MosaicTilesManager, &MosaicTilesManager::newOffset, this, [this](const QPointF & offset) 0099 { 0100 // Find out new center 0101 QPointF cartesianCenter = SkyMap::Instance()->projector()->toScreen(&m_CenterPoint); 0102 QPointF destinationCenter = cartesianCenter + offset; 0103 SkyPoint newCenter = SkyMap::Instance()->projector()->fromScreen(destinationCenter, 0104 KStarsData::Instance()->lst(), 0105 KStarsData::Instance()->geo()->lat()); 0106 SkyPoint J2000Center = newCenter.catalogueCoord(KStars::Instance()->data()->ut().djd()); 0107 setCenter(J2000Center); 0108 updateTimer->start(); 0109 }); 0110 m_TilesScene.addItem(m_MosaicTilesManager); 0111 //ui->mosaicView->setScene(&m_TilesScene); 0112 0113 // Always use Equatorial Mode in Mosaic mode 0114 m_RememberAltAzOption = Options::useAltAz(); 0115 Options::setUseAltAz(false); 0116 m_RememberShowGround = Options::showGround(); 0117 Options::setShowGround(false); 0118 0119 // Rendering options 0120 // connect(ui->transparencySlider, QOverload<int>::of(&QSlider::valueChanged), this, [&](int v) 0121 // { 0122 // ui->transparencySlider->setToolTip(QString("%1%").arg(v)); 0123 // m_MosaicTilesManager->setPainterAlpha(v); 0124 // updateTimer->start(); 0125 // }); 0126 // connect(ui->transparencyAuto, &QCheckBox::toggled, this, [&](bool v) 0127 // { 0128 // ui->transparencySlider->setEnabled(!v); 0129 // if (v) 0130 // updateTimer->start(); 0131 // }); 0132 0133 // Job options 0134 connect(ui->alignEvery, QOverload<int>::of(&QSpinBox::valueChanged), this, &Ekos::FramingAssistant::rewordStepEvery); 0135 connect(ui->focusEvery, QOverload<int>::of(&QSpinBox::valueChanged), this, &Ekos::FramingAssistant::rewordStepEvery); 0136 emit ui->alignEvery->valueChanged(0); 0137 emit ui->focusEvery->valueChanged(0); 0138 0139 // Center, fetch optics and adjust size 0140 //setCenter(center); 0141 fetchINDIInformation(); 0142 adjustSize(); 0143 } 0144 0145 FramingAssistant::~FramingAssistant() 0146 { 0147 delete updateTimer; 0148 Options::setUseAltAz(m_RememberAltAzOption); 0149 Options::setShowGround(m_RememberShowGround); 0150 } 0151 0152 QString FramingAssistant::getJobsDir() const 0153 { 0154 return ui->jobsDir->text(); 0155 } 0156 0157 bool FramingAssistant::isScopeInfoValid() const 0158 { 0159 if (0 < ui->focalLenSpin->value()) 0160 if (0 < ui->cameraWSpin->value() && 0 < ui->cameraWSpin->value()) 0161 if (0 < ui->pixelWSizeSpin->value() && 0 < ui->pixelHSizeSpin->value()) 0162 return true; 0163 return false; 0164 } 0165 0166 double FramingAssistant::getTargetWFOV() const 0167 { 0168 double const xFOV = ui->cameraWFOVSpin->value() * (1 - ui->overlapSpin->value() / 100.0); 0169 return ui->cameraWFOVSpin->value() + xFOV * (ui->mosaicWSpin->value() - 1); 0170 } 0171 0172 double FramingAssistant::getTargetHFOV() const 0173 { 0174 double const yFOV = ui->cameraHFOVSpin->value() * (1 - ui->overlapSpin->value() / 100.0); 0175 return ui->cameraHFOVSpin->value() + yFOV * (ui->mosaicHSpin->value() - 1); 0176 } 0177 0178 double FramingAssistant::getTargetMosaicW() const 0179 { 0180 // If FOV is invalid, or target FOV is null, or target FOV is smaller than camera FOV, we get one tile 0181 if (!isScopeInfoValid() || !ui->targetWFOVSpin->value() || ui->targetWFOVSpin->value() <= ui->cameraWFOVSpin->value()) 0182 return 1; 0183 0184 // Else we get one tile, plus as many overlapping camera FOVs in the remnant of the target FOV 0185 double const xFOV = ui->cameraWFOVSpin->value() * (1 - ui->overlapSpin->value() / 100.0); 0186 int const tiles = 1 + ceil((ui->targetWFOVSpin->value() - ui->cameraWFOVSpin->value()) / xFOV); 0187 //Ekos::Manager::Instance()->schedulerModule()->appendLogText(QString("[W] Target FOV %1, camera FOV %2 after overlap %3, %4 tiles.").arg(ui->targetWFOVSpin->value()).arg(ui->cameraWFOVSpin->value()).arg(xFOV).arg(tiles)); 0188 return tiles; 0189 } 0190 0191 double FramingAssistant::getTargetMosaicH() const 0192 { 0193 // If FOV is invalid, or target FOV is null, or target FOV is smaller than camera FOV, we get one tile 0194 if (!isScopeInfoValid() || !ui->targetHFOVSpin->value() || ui->targetHFOVSpin->value() <= ui->cameraHFOVSpin->value()) 0195 return 1; 0196 0197 // Else we get one tile, plus as many overlapping camera FOVs in the remnant of the target FOV 0198 double const yFOV = ui->cameraHFOVSpin->value() * (1 - ui->overlapSpin->value() / 100.0); 0199 int const tiles = 1 + ceil((ui->targetHFOVSpin->value() - ui->cameraHFOVSpin->value()) / yFOV); 0200 //Ekos::Manager::Instance()->schedulerModule()->appendLogText(QString("[H] Target FOV %1, camera FOV %2 after overlap %3, %4 tiles.").arg(ui->targetHFOVSpin->value()).arg(ui->cameraHFOVSpin->value()).arg(yFOV).arg(tiles)); 0201 return tiles; 0202 } 0203 0204 //int FramingAssistant::exec() 0205 //{ 0206 // premosaicZoomFactor = Options::zoomFactor(); 0207 0208 // int const result = QDialog::exec(); 0209 0210 // // Revert various options 0211 // updateTimer->stop(); 0212 // SkyMap *map = SkyMap::Instance(); 0213 // if (map && 0 < premosaicZoomFactor) 0214 // map->setZoomFactor(premosaicZoomFactor); 0215 0216 // return result; 0217 //} 0218 0219 void FramingAssistant::saveJobsDirectory() 0220 { 0221 QString dir = QFileDialog::getExistingDirectory(KStars::Instance(), i18nc("@title:window", "FITS Save Directory"), 0222 ui->jobsDir->text()); 0223 0224 if (!dir.isEmpty()) 0225 ui->jobsDir->setText(dir); 0226 } 0227 0228 void FramingAssistant::setCenter(const SkyPoint &value) 0229 { 0230 m_CenterPoint = value; 0231 m_CenterPoint.apparentCoord(static_cast<long double>(J2000), KStars::Instance()->data()->ut().djd()); 0232 } 0233 0234 void FramingAssistant::calculateFOV() 0235 { 0236 if (!isScopeInfoValid()) 0237 return; 0238 0239 ui->fovGroup->setEnabled(true); 0240 0241 ui->targetWFOVSpin->setMinimum(ui->cameraWFOVSpin->value()); 0242 ui->targetHFOVSpin->setMinimum(ui->cameraHFOVSpin->value()); 0243 0244 Options::setTelescopeFocalLength(ui->focalLenSpin->value()); 0245 Options::setCameraPixelWidth(ui->pixelWSizeSpin->value()); 0246 Options::setCameraPixelHeight(ui->pixelHSizeSpin->value()); 0247 Options::setCameraWidth(ui->cameraWSpin->value()); 0248 Options::setCameraHeight(ui->cameraHSpin->value()); 0249 0250 // Calculate FOV in arcmins 0251 double const fov_x = 0252 206264.8062470963552 * ui->cameraWSpin->value() * ui->pixelWSizeSpin->value() / 60000.0 / ui->focalLenSpin->value(); 0253 double const fov_y = 0254 206264.8062470963552 * ui->cameraHSpin->value() * ui->pixelHSizeSpin->value() / 60000.0 / ui->focalLenSpin->value(); 0255 0256 ui->cameraWFOVSpin->setValue(fov_x); 0257 ui->cameraHFOVSpin->setValue(fov_y); 0258 0259 double const target_fov_w = getTargetWFOV(); 0260 double const target_fov_h = getTargetHFOV(); 0261 0262 if (ui->targetWFOVSpin->value() < target_fov_w) 0263 { 0264 bool const sig = ui->targetWFOVSpin->blockSignals(true); 0265 ui->targetWFOVSpin->setValue(target_fov_w); 0266 ui->targetWFOVSpin->blockSignals(sig); 0267 } 0268 0269 if (ui->targetHFOVSpin->value() < target_fov_h) 0270 { 0271 bool const sig = ui->targetHFOVSpin->blockSignals(true); 0272 ui->targetHFOVSpin->setValue(target_fov_h); 0273 ui->targetHFOVSpin->blockSignals(sig); 0274 } 0275 0276 updateTimer->start(); 0277 } 0278 0279 void FramingAssistant::updateTargetFOV() 0280 { 0281 KStars *ks = KStars::Instance(); 0282 SkyMap *map = SkyMap::Instance(); 0283 0284 // Render the required FOV 0285 renderedWFOV = ui->targetWFOVSpin->value();// * cos(ui->rotationSpin->value() * dms::DegToRad); 0286 renderedHFOV = ui->targetHFOVSpin->value();// * sin(ui->rotationSpin->value() * dms::DegToRad); 0287 0288 // Pick thrice the largest FOV to obtain a proper zoom 0289 double const spacing = ui->mosaicWSpin->value() < ui->mosaicHSpin->value() ? ui->mosaicHSpin->value() : 0290 ui->mosaicWSpin->value(); 0291 double const scale = 1.0 + 2.0 / (1.0 + spacing); 0292 double const renderedFOV = scale * (renderedWFOV < renderedHFOV ? renderedHFOV : renderedWFOV); 0293 0294 // Check the aspect ratio of the sky map, assuming the map zoom considers the width (see KStars::setApproxFOV) 0295 double const aspect_ratio = map->width() / map->height(); 0296 0297 // Set the zoom (in degrees) that gives the expected FOV for the map aspect ratio, and center the target 0298 ks->setApproxFOV(renderedFOV * aspect_ratio / 60.0); 0299 //center.EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat()); 0300 map->setClickedObject(nullptr); 0301 map->setClickedPoint(&m_CenterPoint); 0302 map->slotCenter(); 0303 0304 // Wait for the map to stop slewing, so that HiPS renders properly 0305 while(map->isSlewing()) 0306 qApp->processEvents(); 0307 qApp->processEvents(); 0308 0309 // Compute the horizontal and vertical resolutions, deduce the actual FOV of the map in arcminutes 0310 pixelsPerArcminRA = pixelsPerArcminDE = Options::zoomFactor() * dms::DegToRad / 60.0; 0311 0312 // Get the sky map image - don't bother subframing, it causes imprecision sometimes 0313 QImage fullSkyChart(QSize(map->width(), map->height()), QImage::Format_RGB32); 0314 map->exportSkyImage(&fullSkyChart, false); 0315 qApp->processEvents(); 0316 m_SkyPixmapItem->setPixmap(QPixmap::fromImage(fullSkyChart)); 0317 0318 // Relocate 0319 QRectF sceneRect = m_SkyPixmapItem->boundingRect().translated(-m_SkyPixmapItem->boundingRect().center()); 0320 m_TilesScene.setSceneRect(sceneRect); 0321 m_SkyPixmapItem->setOffset(sceneRect.topLeft()); 0322 m_SkyPixmapItem->setPos(QPointF()); 0323 0324 } 0325 0326 void FramingAssistant::resizeEvent(QResizeEvent *) 0327 { 0328 // Adjust scene rect to avoid rounding holes on border 0329 QRectF adjustedSceneRect(m_TilesScene.sceneRect()); 0330 adjustedSceneRect.setTop(adjustedSceneRect.top() + 2); 0331 adjustedSceneRect.setLeft(adjustedSceneRect.left() + 2); 0332 adjustedSceneRect.setRight(adjustedSceneRect.right() - 2); 0333 adjustedSceneRect.setBottom(adjustedSceneRect.bottom() - 2); 0334 0335 // ui->mosaicView->fitInView(adjustedSceneRect, Qt::KeepAspectRatioByExpanding); 0336 // ui->mosaicView->centerOn(QPointF()); 0337 } 0338 0339 void FramingAssistant::showEvent(QShowEvent *) 0340 { 0341 resizeEvent(nullptr); 0342 } 0343 0344 void FramingAssistant::resetFOV() 0345 { 0346 if (!isScopeInfoValid()) 0347 return; 0348 0349 ui->targetWFOVSpin->setValue(getTargetWFOV()); 0350 ui->targetHFOVSpin->setValue(getTargetHFOV()); 0351 } 0352 0353 void FramingAssistant::updateTargetFOVFromGrid() 0354 { 0355 if (!isScopeInfoValid()) 0356 return; 0357 0358 double const targetWFOV = getTargetWFOV(); 0359 double const targetHFOV = getTargetHFOV(); 0360 0361 if (ui->targetWFOVSpin->value() != targetWFOV) 0362 { 0363 bool const sig = ui->targetWFOVSpin->blockSignals(true); 0364 ui->targetWFOVSpin->setValue(targetWFOV); 0365 ui->targetWFOVSpin->blockSignals(sig); 0366 updateTimer->start(); 0367 } 0368 0369 if (ui->targetHFOVSpin->value() != targetHFOV) 0370 { 0371 bool const sig = ui->targetHFOVSpin->blockSignals(true); 0372 ui->targetHFOVSpin->setValue(targetHFOV); 0373 ui->targetHFOVSpin->blockSignals(sig); 0374 updateTimer->start(); 0375 } 0376 } 0377 0378 void FramingAssistant::updateGridFromTargetFOV() 0379 { 0380 if (!isScopeInfoValid()) 0381 return; 0382 0383 double const expectedW = getTargetMosaicW(); 0384 double const expectedH = getTargetMosaicH(); 0385 0386 if (expectedW != ui->mosaicWSpin->value()) 0387 { 0388 bool const sig = ui->mosaicWSpin->blockSignals(true); 0389 ui->mosaicWSpin->setValue(expectedW); 0390 ui->mosaicWSpin->blockSignals(sig); 0391 } 0392 0393 if (expectedH != ui->mosaicHSpin->value()) 0394 { 0395 bool const sig = ui->mosaicHSpin->blockSignals(true); 0396 ui->mosaicHSpin->setValue(expectedH); 0397 ui->mosaicHSpin->blockSignals(sig); 0398 } 0399 0400 // Update unconditionally, as we may be updating the overlap or the target FOV covered by the mosaic 0401 updateTimer->start(); 0402 } 0403 0404 void FramingAssistant::constructMosaic() 0405 { 0406 updateTimer->stop(); 0407 0408 if (!isScopeInfoValid()) 0409 return; 0410 0411 updateTargetFOV(); 0412 0413 if (m_MosaicTilesManager->getPA() != ui->rotationSpin->value()) 0414 Options::setCameraRotation(ui->rotationSpin->value()); 0415 0416 qCDebug(KSTARS_EKOS_SCHEDULER) << "Tile FOV in pixels W:" << ui->cameraWFOVSpin->value() * pixelsPerArcminRA << "H:" 0417 << ui->cameraHFOVSpin->value() * pixelsPerArcminDE; 0418 0419 m_MosaicTilesManager->setPos(0, 0); 0420 m_MosaicTilesManager->setSkyCenter(m_CenterPoint); 0421 m_MosaicTilesManager->setGridDimensions(ui->mosaicWSpin->value(), ui->mosaicHSpin->value()); 0422 m_MosaicTilesManager->setPositionAngle(ui->rotationSpin->value()); 0423 m_MosaicTilesManager->setSingleTileFOV(ui->cameraWFOVSpin->value() * pixelsPerArcminRA, 0424 ui->cameraHFOVSpin->value() * pixelsPerArcminDE); 0425 m_MosaicTilesManager->setMosaicFOV(ui->targetWFOVSpin->value() * pixelsPerArcminRA, 0426 ui->targetHFOVSpin->value() * pixelsPerArcminDE); 0427 m_MosaicTilesManager->setOverlap(ui->overlapSpin->value() / 100); 0428 m_MosaicTilesManager->setPixelScale(QSizeF(pixelsPerArcminRA * 60.0, pixelsPerArcminDE * 60.0)); 0429 m_MosaicTilesManager->updateTiles(m_MosaicTilesManager->mapToItem(m_SkyPixmapItem, 0430 m_SkyPixmapItem->boundingRect().center()), 0431 ui->reverseOddRows->checkState() == Qt::CheckState::Checked); 0432 0433 // ui->jobCountSpin->setValue(m_MosaicTilesManager->getWidth() * m_MosaicTilesManager->getHeight()); 0434 0435 // if (ui->transparencyAuto->isChecked()) 0436 // { 0437 // // Tiles should be more transparent when many are overlapped 0438 // // Overlap < 50%: low transparency, as only two tiles will overlap on a line 0439 // // 50% < Overlap < 75%: mid transparency, as three tiles will overlap one a line 0440 // // 75% < Overlap: high transparency, as four tiles will overlap on a line 0441 // // Slider controlling transparency provides [5%,50%], which is scaled to 0-200 alpha. 0442 0443 // if (1 < ui->jobCountSpin->value()) 0444 // ui->transparencySlider->setValue(40 - ui->overlapSpin->value() / 2); 0445 // else 0446 // ui->transparencySlider->setValue(40); 0447 0448 // ui->transparencySlider->update(); 0449 // } 0450 0451 resizeEvent(nullptr); 0452 m_MosaicTilesManager->show(); 0453 0454 //ui->mosaicView->update(); 0455 } 0456 0457 QList <FramingAssistant::Job> FramingAssistant::getJobs() const 0458 { 0459 qCDebug(KSTARS_EKOS_SCHEDULER) << "Mosaic Tile W:" << m_MosaicTilesManager->boundingRect().width() << "H:" << 0460 m_MosaicTilesManager->boundingRect().height(); 0461 0462 QList <FramingAssistant::Job> result; 0463 0464 // We have two items: 0465 // 1. SkyMapItem is the pixmap we fetch from KStars that shows the sky field. 0466 // 2. MosaicItem is the constructed mosaic boxes. 0467 // We already know the center (RA0,DE0) of the SkyMapItem. 0468 // We Map the coordinate of each tile to the SkyMapItem to find out where the tile center is located 0469 // on the SkyMapItem pixmap. 0470 // We calculate the difference between the tile center and the SkyMapItem center and then find the tile coordinates 0471 // in J2000 coords. 0472 for (int i = 0; i < m_MosaicTilesManager->getHeight(); i++) 0473 { 0474 for (int j = 0; j < m_MosaicTilesManager->getWidth(); j++) 0475 { 0476 MosaicTilesManager::OneTile * const tile = m_MosaicTilesManager->getTile(i, j); 0477 qCDebug(KSTARS_EKOS_SCHEDULER) << "Tile #" << i * m_MosaicTilesManager->getWidth() + j << "Center:" << tile->center; 0478 0479 Job ts; 0480 ts.center.setRA0(tile->skyCenter.ra0().Hours()); 0481 ts.center.setDec0(tile->skyCenter.dec0().Degrees()); 0482 ts.rotation = -m_MosaicTilesManager->getPA(); 0483 0484 ts.doAlign = 0485 (0 < ui->alignEvery->value()) && 0486 (0 == ((j + i * m_MosaicTilesManager->getHeight()) % ui->alignEvery->value())); 0487 0488 ts.doFocus = 0489 (0 < ui->focusEvery->value()) && 0490 (0 == ((j + i * m_MosaicTilesManager->getHeight()) % ui->focusEvery->value())); 0491 0492 qCDebug(KSTARS_EKOS_SCHEDULER) << "Tile RA0:" << tile->skyCenter.ra0().toHMSString() << "DE0:" << 0493 tile->skyCenter.dec0().toDMSString(); 0494 result.append(ts); 0495 } 0496 } 0497 0498 return result; 0499 } 0500 0501 void FramingAssistant::fetchINDIInformation() 0502 { 0503 QDBusInterface alignInterface("org.kde.kstars", 0504 "/KStars/Ekos/Align", 0505 "org.kde.kstars.Ekos.Align", 0506 QDBusConnection::sessionBus()); 0507 0508 QDBusReply<QList<double>> cameraReply = alignInterface.call("cameraInfo"); 0509 if (cameraReply.isValid()) 0510 { 0511 QList<double> const values = cameraReply.value(); 0512 0513 m_CameraSize = QSize(values[0], values[1]); 0514 m_PixelSize = QSizeF(values[2], values[3]); 0515 } 0516 0517 QDBusReply<QList<double>> telescopeReply = alignInterface.call("telescopeInfo"); 0518 if (telescopeReply.isValid()) 0519 { 0520 QList<double> const values = telescopeReply.value(); 0521 m_FocalLength = values[0]; 0522 } 0523 0524 QDBusReply<QList<double>> solutionReply = alignInterface.call("getSolutionResult"); 0525 if (solutionReply.isValid()) 0526 { 0527 QList<double> const values = solutionReply.value(); 0528 if (values[0] > INVALID_VALUE) 0529 m_Rotation = values[0]; 0530 } 0531 0532 calculateFOV(); 0533 } 0534 0535 void FramingAssistant::rewordStepEvery(int v) 0536 { 0537 QSpinBox * sp = dynamic_cast<QSpinBox *>(sender()); 0538 if (0 < v) 0539 sp->setSuffix(i18np(" Scheduler job", " Scheduler jobs", v)); 0540 else 0541 sp->setSuffix(i18n(" (first only)")); 0542 } 0543 0544 }