Kstars

framingassistant.cpp
1/*
2 SPDX-FileCopyrightText: 2022 Jasem Mutlaq <mutlaqja@ikarustech.com>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "framingassistant.h"
8#include "ui_framingassistant.h"
9#include "mosaictilesmanager.h"
10#include "kstars.h"
11#include "Options.h"
12#include "scheduler.h"
13#include "skymap.h"
14#include "ekos/manager.h"
15#include "projections/projector.h"
16
17#include "ekos_scheduler_debug.h"
18
19namespace Ekos
20{
21
22FramingAssistant* FramingAssistant::Instance()
23{
24 if (_FramingAssistant == nullptr)
25 {
26 _FramingAssistant = new FramingAssistant;
27 }
28
29 return _FramingAssistant;
30}
31
32FramingAssistant::FramingAssistant(): QDialog(KStars::Instance()), ui(new Ui::FramingAssistant())
33{
34 ui->setupUi(this);
35
36 // Initial optics information is taken from Ekos options
37 ui->focalLenSpin->setValue(Options::telescopeFocalLength());
38 ui->pixelWSizeSpin->setValue(Options::cameraPixelWidth());
39 ui->pixelHSizeSpin->setValue(Options::cameraPixelHeight());
40 ui->cameraWSpin->setValue(Options::cameraWidth());
41 ui->cameraHSpin->setValue(Options::cameraHeight());
42 ui->rotationSpin->setValue(Options::cameraRotation());
43
44 // Initial job location is the home path appended with the target name
45 //ui->jobsDir->setText(QDir::cleanPath(QDir::homePath() + QDir::separator() + targetName.replace(' ', '_')));
46 //ui->selectJobsDirB->setIcon(QIcon::fromTheme("document-open-folder"));
47
48 // The update timer avoids stacking updates which crash the sky map renderer
49 updateTimer = new QTimer(this);
50 updateTimer->setSingleShot(true);
51 updateTimer->setInterval(1000);
52 connect(updateTimer, &QTimer::timeout, this, &Ekos::FramingAssistant::constructMosaic);
53
54 // Scope optics information
55 // - Changing the optics configuration changes the FOV, which changes the target field dimensions
56 connect(ui->focalLenSpin, &QDoubleSpinBox::editingFinished, this, &Ekos::FramingAssistant::calculateFOV);
57 connect(ui->cameraWSpin, &QSpinBox::editingFinished, this, &Ekos::FramingAssistant::calculateFOV);
58 connect(ui->cameraHSpin, &QSpinBox::editingFinished, this, &Ekos::FramingAssistant::calculateFOV);
59 connect(ui->pixelWSizeSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
60 &Ekos::FramingAssistant::calculateFOV);
61 connect(ui->pixelHSizeSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
62 &Ekos::FramingAssistant::calculateFOV);
63 connect(ui->rotationSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
64 &Ekos::FramingAssistant::calculateFOV);
65
66 // Mosaic configuration
67 // - Changing the target field dimensions changes the grid dimensions
68 // - Changing the overlap field changes the grid dimensions (more intuitive than changing the field)
69 // - Changing the grid dimensions changes the target field dimensions
70 connect(ui->targetHFOVSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
71 &Ekos::FramingAssistant::updateGridFromTargetFOV);
72 connect(ui->targetWFOVSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
73 &Ekos::FramingAssistant::updateGridFromTargetFOV);
74 connect(ui->overlapSpin, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this,
75 &Ekos::FramingAssistant::updateGridFromTargetFOV);
76 connect(ui->mosaicWSpin, QOverload<int>::of(&QSpinBox::valueChanged), this,
77 &Ekos::FramingAssistant::updateTargetFOVFromGrid);
78 connect(ui->mosaicHSpin, QOverload<int>::of(&QSpinBox::valueChanged), this,
79 &Ekos::FramingAssistant::updateTargetFOVFromGrid);
80
81 // Lazy update for s-shape
82 connect(ui->reverseOddRows, &QCheckBox::toggled, this, [&]()
83 {
84 renderedHFOV = 0;
85 updateTimer->start();
86 });
87
88 // Buttons
89 connect(ui->resetB, &QPushButton::clicked, this, &Ekos::FramingAssistant::updateTargetFOVFromGrid);
90 connect(ui->selectJobsDirB, &QPushButton::clicked, this, &Ekos::FramingAssistant::saveJobsDirectory);
91 connect(ui->fetchB, &QPushButton::clicked, this, &FramingAssistant::fetchINDIInformation);
92
93 // The sky map is a pixmap background, and the mosaic tiles are rendered over it
94 //m_TilesScene = new MosaicTilesScene(this);
95 m_SkyPixmapItem = m_TilesScene.addPixmap(targetPix);
96 m_SkyPixmapItem->setTransformationMode(Qt::TransformationMode::SmoothTransformation);
97 m_MosaicTilesManager = new MosaicTilesManager(this);
98 connect(m_MosaicTilesManager, &MosaicTilesManager::newOffset, this, [this](const QPointF & offset)
99 {
100 // Find out new center
101 QPointF cartesianCenter = SkyMap::Instance()->projector()->toScreen(&m_CenterPoint);
102 QPointF destinationCenter = cartesianCenter + offset;
103 SkyPoint newCenter = SkyMap::Instance()->projector()->fromScreen(destinationCenter,
104 KStarsData::Instance());
105 SkyPoint J2000Center = newCenter.catalogueCoord(KStars::Instance()->data()->ut().djd());
106 setCenter(J2000Center);
107 updateTimer->start();
108 });
109 m_TilesScene.addItem(m_MosaicTilesManager);
110 //ui->mosaicView->setScene(&m_TilesScene);
111
112 // Always use Equatorial Mode in Mosaic mode
113 m_RememberAltAzOption = Options::useAltAz();
114 Options::setUseAltAz(false);
115 m_RememberShowGround = Options::showGround();
116 Options::setShowGround(false);
117
118 // Rendering options
119 // connect(ui->transparencySlider, QOverload<int>::of(&QSlider::valueChanged), this, [&](int v)
120 // {
121 // ui->transparencySlider->setToolTip(QString("%1%").arg(v));
122 // m_MosaicTilesManager->setPainterAlpha(v);
123 // updateTimer->start();
124 // });
125 // connect(ui->transparencyAuto, &QCheckBox::toggled, this, [&](bool v)
126 // {
127 // ui->transparencySlider->setEnabled(!v);
128 // if (v)
129 // updateTimer->start();
130 // });
131
132 // Job options
133 connect(ui->alignEvery, QOverload<int>::of(&QSpinBox::valueChanged), this, &Ekos::FramingAssistant::rewordStepEvery);
134 connect(ui->focusEvery, QOverload<int>::of(&QSpinBox::valueChanged), this, &Ekos::FramingAssistant::rewordStepEvery);
135 emit ui->alignEvery->valueChanged(0);
136 emit ui->focusEvery->valueChanged(0);
137
138 // Center, fetch optics and adjust size
139 //setCenter(center);
140 fetchINDIInformation();
141 adjustSize();
142}
143
144FramingAssistant::~FramingAssistant()
145{
146 delete updateTimer;
147 Options::setUseAltAz(m_RememberAltAzOption);
148 Options::setShowGround(m_RememberShowGround);
149}
150
151QString FramingAssistant::getJobsDir() const
152{
153 return ui->jobsDir->text();
154}
155
156bool FramingAssistant::isScopeInfoValid() const
157{
158 if (0 < ui->focalLenSpin->value())
159 if (0 < ui->cameraWSpin->value() && 0 < ui->cameraWSpin->value())
160 if (0 < ui->pixelWSizeSpin->value() && 0 < ui->pixelHSizeSpin->value())
161 return true;
162 return false;
163}
164
165double FramingAssistant::getTargetWFOV() const
166{
167 double const xFOV = ui->cameraWFOVSpin->value() * (1 - ui->overlapSpin->value() / 100.0);
168 return ui->cameraWFOVSpin->value() + xFOV * (ui->mosaicWSpin->value() - 1);
169}
170
171double FramingAssistant::getTargetHFOV() const
172{
173 double const yFOV = ui->cameraHFOVSpin->value() * (1 - ui->overlapSpin->value() / 100.0);
174 return ui->cameraHFOVSpin->value() + yFOV * (ui->mosaicHSpin->value() - 1);
175}
176
177double FramingAssistant::getTargetMosaicW() const
178{
179 // If FOV is invalid, or target FOV is null, or target FOV is smaller than camera FOV, we get one tile
180 if (!isScopeInfoValid() || !ui->targetWFOVSpin->value() || ui->targetWFOVSpin->value() <= ui->cameraWFOVSpin->value())
181 return 1;
182
183 // Else we get one tile, plus as many overlapping camera FOVs in the remnant of the target FOV
184 double const xFOV = ui->cameraWFOVSpin->value() * (1 - ui->overlapSpin->value() / 100.0);
185 int const tiles = 1 + ceil((ui->targetWFOVSpin->value() - ui->cameraWFOVSpin->value()) / xFOV);
186 //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));
187 return tiles;
188}
189
190double FramingAssistant::getTargetMosaicH() const
191{
192 // If FOV is invalid, or target FOV is null, or target FOV is smaller than camera FOV, we get one tile
193 if (!isScopeInfoValid() || !ui->targetHFOVSpin->value() || ui->targetHFOVSpin->value() <= ui->cameraHFOVSpin->value())
194 return 1;
195
196 // Else we get one tile, plus as many overlapping camera FOVs in the remnant of the target FOV
197 double const yFOV = ui->cameraHFOVSpin->value() * (1 - ui->overlapSpin->value() / 100.0);
198 int const tiles = 1 + ceil((ui->targetHFOVSpin->value() - ui->cameraHFOVSpin->value()) / yFOV);
199 //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));
200 return tiles;
201}
202
203//int FramingAssistant::exec()
204//{
205// premosaicZoomFactor = Options::zoomFactor();
206
207// int const result = QDialog::exec();
208
209// // Revert various options
210// updateTimer->stop();
211// SkyMap *map = SkyMap::Instance();
212// if (map && 0 < premosaicZoomFactor)
213// map->setZoomFactor(premosaicZoomFactor);
214
215// return result;
216//}
217
218void FramingAssistant::saveJobsDirectory()
219{
220 QString dir = QFileDialog::getExistingDirectory(KStars::Instance(), i18nc("@title:window", "FITS Save Directory"),
221 ui->jobsDir->text());
222
223 if (!dir.isEmpty())
224 ui->jobsDir->setText(dir);
225}
226
227void FramingAssistant::setCenter(const SkyPoint &value)
228{
229 m_CenterPoint = value;
230 m_CenterPoint.apparentCoord(static_cast<long double>(J2000), KStars::Instance()->data()->ut().djd());
231}
232
233void FramingAssistant::calculateFOV()
234{
235 if (!isScopeInfoValid())
236 return;
237
238 ui->fovGroup->setEnabled(true);
239
240 ui->targetWFOVSpin->setMinimum(ui->cameraWFOVSpin->value());
241 ui->targetHFOVSpin->setMinimum(ui->cameraHFOVSpin->value());
242
243 Options::setTelescopeFocalLength(ui->focalLenSpin->value());
244 Options::setCameraPixelWidth(ui->pixelWSizeSpin->value());
245 Options::setCameraPixelHeight(ui->pixelHSizeSpin->value());
246 Options::setCameraWidth(ui->cameraWSpin->value());
247 Options::setCameraHeight(ui->cameraHSpin->value());
248
249 // Calculate FOV in arcmins
250 double const fov_x =
251 206264.8062470963552 * ui->cameraWSpin->value() * ui->pixelWSizeSpin->value() / 60000.0 / ui->focalLenSpin->value();
252 double const fov_y =
253 206264.8062470963552 * ui->cameraHSpin->value() * ui->pixelHSizeSpin->value() / 60000.0 / ui->focalLenSpin->value();
254
255 ui->cameraWFOVSpin->setValue(fov_x);
256 ui->cameraHFOVSpin->setValue(fov_y);
257
258 double const target_fov_w = getTargetWFOV();
259 double const target_fov_h = getTargetHFOV();
260
261 if (ui->targetWFOVSpin->value() < target_fov_w)
262 {
263 bool const sig = ui->targetWFOVSpin->blockSignals(true);
264 ui->targetWFOVSpin->setValue(target_fov_w);
265 ui->targetWFOVSpin->blockSignals(sig);
266 }
267
268 if (ui->targetHFOVSpin->value() < target_fov_h)
269 {
270 bool const sig = ui->targetHFOVSpin->blockSignals(true);
271 ui->targetHFOVSpin->setValue(target_fov_h);
272 ui->targetHFOVSpin->blockSignals(sig);
273 }
274
275 updateTimer->start();
276}
277
278void FramingAssistant::updateTargetFOV()
279{
280 KStars *ks = KStars::Instance();
281 SkyMap *map = SkyMap::Instance();
282
283 // Render the required FOV
284 renderedWFOV = ui->targetWFOVSpin->value();// * cos(ui->rotationSpin->value() * dms::DegToRad);
285 renderedHFOV = ui->targetHFOVSpin->value();// * sin(ui->rotationSpin->value() * dms::DegToRad);
286
287 // Pick thrice the largest FOV to obtain a proper zoom
288 double const spacing = ui->mosaicWSpin->value() < ui->mosaicHSpin->value() ? ui->mosaicHSpin->value() :
289 ui->mosaicWSpin->value();
290 double const scale = 1.0 + 2.0 / (1.0 + spacing);
291 double const renderedFOV = scale * (renderedWFOV < renderedHFOV ? renderedHFOV : renderedWFOV);
292
293 // Check the aspect ratio of the sky map, assuming the map zoom considers the width (see KStars::setApproxFOV)
294 double const aspect_ratio = map->width() / map->height();
295
296 // Set the zoom (in degrees) that gives the expected FOV for the map aspect ratio, and center the target
297 ks->setApproxFOV(renderedFOV * aspect_ratio / 60.0);
298 //center.EquatorialToHorizontal(KStarsData::Instance()->lst(), KStarsData::Instance()->geo()->lat());
299 map->setClickedObject(nullptr);
300 map->setClickedPoint(&m_CenterPoint);
301 map->slotCenter();
302
303 // Wait for the map to stop slewing, so that HiPS renders properly
304 while(map->isSlewing())
305 qApp->processEvents();
306 qApp->processEvents();
307
308 // Compute the horizontal and vertical resolutions, deduce the actual FOV of the map in arcminutes
309 pixelsPerArcminRA = pixelsPerArcminDE = Options::zoomFactor() * dms::DegToRad / 60.0;
310
311 // Get the sky map image - don't bother subframing, it causes imprecision sometimes
312 QImage fullSkyChart(QSize(map->width(), map->height()), QImage::Format_RGB32);
313 map->exportSkyImage(&fullSkyChart, false);
314 qApp->processEvents();
315 m_SkyPixmapItem->setPixmap(QPixmap::fromImage(fullSkyChart));
316
317 // Relocate
318 QRectF sceneRect = m_SkyPixmapItem->boundingRect().translated(-m_SkyPixmapItem->boundingRect().center());
319 m_TilesScene.setSceneRect(sceneRect);
320 m_SkyPixmapItem->setOffset(sceneRect.topLeft());
321 m_SkyPixmapItem->setPos(QPointF());
322
323}
324
325void FramingAssistant::resizeEvent(QResizeEvent *)
326{
327 // Adjust scene rect to avoid rounding holes on border
328 QRectF adjustedSceneRect(m_TilesScene.sceneRect());
329 adjustedSceneRect.setTop(adjustedSceneRect.top() + 2);
330 adjustedSceneRect.setLeft(adjustedSceneRect.left() + 2);
331 adjustedSceneRect.setRight(adjustedSceneRect.right() - 2);
332 adjustedSceneRect.setBottom(adjustedSceneRect.bottom() - 2);
333
334 // ui->mosaicView->fitInView(adjustedSceneRect, Qt::KeepAspectRatioByExpanding);
335 // ui->mosaicView->centerOn(QPointF());
336}
337
338void FramingAssistant::showEvent(QShowEvent *)
339{
340 resizeEvent(nullptr);
341}
342
343void FramingAssistant::resetFOV()
344{
345 if (!isScopeInfoValid())
346 return;
347
348 ui->targetWFOVSpin->setValue(getTargetWFOV());
349 ui->targetHFOVSpin->setValue(getTargetHFOV());
350}
351
352void FramingAssistant::updateTargetFOVFromGrid()
353{
354 if (!isScopeInfoValid())
355 return;
356
357 double const targetWFOV = getTargetWFOV();
358 double const targetHFOV = getTargetHFOV();
359
360 if (ui->targetWFOVSpin->value() != targetWFOV)
361 {
362 bool const sig = ui->targetWFOVSpin->blockSignals(true);
363 ui->targetWFOVSpin->setValue(targetWFOV);
364 ui->targetWFOVSpin->blockSignals(sig);
365 updateTimer->start();
366 }
367
368 if (ui->targetHFOVSpin->value() != targetHFOV)
369 {
370 bool const sig = ui->targetHFOVSpin->blockSignals(true);
371 ui->targetHFOVSpin->setValue(targetHFOV);
372 ui->targetHFOVSpin->blockSignals(sig);
373 updateTimer->start();
374 }
375}
376
377void FramingAssistant::updateGridFromTargetFOV()
378{
379 if (!isScopeInfoValid())
380 return;
381
382 double const expectedW = getTargetMosaicW();
383 double const expectedH = getTargetMosaicH();
384
385 if (expectedW != ui->mosaicWSpin->value())
386 {
387 bool const sig = ui->mosaicWSpin->blockSignals(true);
388 ui->mosaicWSpin->setValue(expectedW);
389 ui->mosaicWSpin->blockSignals(sig);
390 }
391
392 if (expectedH != ui->mosaicHSpin->value())
393 {
394 bool const sig = ui->mosaicHSpin->blockSignals(true);
395 ui->mosaicHSpin->setValue(expectedH);
396 ui->mosaicHSpin->blockSignals(sig);
397 }
398
399 // Update unconditionally, as we may be updating the overlap or the target FOV covered by the mosaic
400 updateTimer->start();
401}
402
403void FramingAssistant::constructMosaic()
404{
405 updateTimer->stop();
406
407 if (!isScopeInfoValid())
408 return;
409
410 updateTargetFOV();
411
412 if (m_MosaicTilesManager->getPA() != ui->rotationSpin->value())
413 Options::setCameraRotation(ui->rotationSpin->value());
414
415 qCDebug(KSTARS_EKOS_SCHEDULER) << "Tile FOV in pixels W:" << ui->cameraWFOVSpin->value() * pixelsPerArcminRA << "H:"
416 << ui->cameraHFOVSpin->value() * pixelsPerArcminDE;
417
418 m_MosaicTilesManager->setPos(0, 0);
419 m_MosaicTilesManager->setSkyCenter(m_CenterPoint);
420 m_MosaicTilesManager->setGridDimensions(ui->mosaicWSpin->value(), ui->mosaicHSpin->value());
421 m_MosaicTilesManager->setPositionAngle(ui->rotationSpin->value());
422 m_MosaicTilesManager->setSingleTileFOV(ui->cameraWFOVSpin->value() * pixelsPerArcminRA,
423 ui->cameraHFOVSpin->value() * pixelsPerArcminDE);
424 m_MosaicTilesManager->setMosaicFOV(ui->targetWFOVSpin->value() * pixelsPerArcminRA,
425 ui->targetHFOVSpin->value() * pixelsPerArcminDE);
426 m_MosaicTilesManager->setOverlap(ui->overlapSpin->value() / 100);
427 m_MosaicTilesManager->setPixelScale(QSizeF(pixelsPerArcminRA * 60.0, pixelsPerArcminDE * 60.0));
428 m_MosaicTilesManager->updateTiles(m_MosaicTilesManager->mapToItem(m_SkyPixmapItem,
429 m_SkyPixmapItem->boundingRect().center()),
430 ui->reverseOddRows->checkState() == Qt::CheckState::Checked);
431
432 // ui->jobCountSpin->setValue(m_MosaicTilesManager->getWidth() * m_MosaicTilesManager->getHeight());
433
434 // if (ui->transparencyAuto->isChecked())
435 // {
436 // // Tiles should be more transparent when many are overlapped
437 // // Overlap < 50%: low transparency, as only two tiles will overlap on a line
438 // // 50% < Overlap < 75%: mid transparency, as three tiles will overlap one a line
439 // // 75% < Overlap: high transparency, as four tiles will overlap on a line
440 // // Slider controlling transparency provides [5%,50%], which is scaled to 0-200 alpha.
441
442 // if (1 < ui->jobCountSpin->value())
443 // ui->transparencySlider->setValue(40 - ui->overlapSpin->value() / 2);
444 // else
445 // ui->transparencySlider->setValue(40);
446
447 // ui->transparencySlider->update();
448 // }
449
450 resizeEvent(nullptr);
451 m_MosaicTilesManager->show();
452
453 //ui->mosaicView->update();
454}
455
456QList <FramingAssistant::Job> FramingAssistant::getJobs() const
457{
458 qCDebug(KSTARS_EKOS_SCHEDULER) << "Mosaic Tile W:" << m_MosaicTilesManager->boundingRect().width() << "H:" <<
459 m_MosaicTilesManager->boundingRect().height();
460
461 QList <FramingAssistant::Job> result;
462
463 // We have two items:
464 // 1. SkyMapItem is the pixmap we fetch from KStars that shows the sky field.
465 // 2. MosaicItem is the constructed mosaic boxes.
466 // We already know the center (RA0,DE0) of the SkyMapItem.
467 // We Map the coordinate of each tile to the SkyMapItem to find out where the tile center is located
468 // on the SkyMapItem pixmap.
469 // We calculate the difference between the tile center and the SkyMapItem center and then find the tile coordinates
470 // in J2000 coords.
471 for (int i = 0; i < m_MosaicTilesManager->getHeight(); i++)
472 {
473 for (int j = 0; j < m_MosaicTilesManager->getWidth(); j++)
474 {
475 MosaicTilesManager::OneTile * const tile = m_MosaicTilesManager->getTile(i, j);
476 qCDebug(KSTARS_EKOS_SCHEDULER) << "Tile #" << i * m_MosaicTilesManager->getWidth() + j << "Center:" << tile->center;
477
478 Job ts;
479 ts.center.setRA0(tile->skyCenter.ra0().Hours());
480 ts.center.setDec0(tile->skyCenter.dec0().Degrees());
481 ts.rotation = -m_MosaicTilesManager->getPA();
482
483 ts.doAlign =
484 (0 < ui->alignEvery->value()) &&
485 (0 == ((j + i * m_MosaicTilesManager->getHeight()) % ui->alignEvery->value()));
486
487 ts.doFocus =
488 (0 < ui->focusEvery->value()) &&
489 (0 == ((j + i * m_MosaicTilesManager->getHeight()) % ui->focusEvery->value()));
490
491 qCDebug(KSTARS_EKOS_SCHEDULER) << "Tile RA0:" << tile->skyCenter.ra0().toHMSString() << "DE0:" <<
492 tile->skyCenter.dec0().toDMSString();
493 result.append(ts);
494 }
495 }
496
497 return result;
498}
499
500void FramingAssistant::fetchINDIInformation()
501{
502 QDBusInterface alignInterface("org.kde.kstars",
503 "/KStars/Ekos/Align",
504 "org.kde.kstars.Ekos.Align",
506
507 QDBusReply<QList<double>> cameraReply = alignInterface.call("cameraInfo");
508 if (cameraReply.isValid())
509 {
510 QList<double> const values = cameraReply.value();
511
512 m_CameraSize = QSize(values[0], values[1]);
513 m_PixelSize = QSizeF(values[2], values[3]);
514 }
515
516 QDBusReply<QList<double>> telescopeReply = alignInterface.call("telescopeInfo");
517 if (telescopeReply.isValid())
518 {
519 QList<double> const values = telescopeReply.value();
520 m_FocalLength = values[0];
521 }
522
523 QDBusReply<QList<double>> solutionReply = alignInterface.call("getSolutionResult");
524 if (solutionReply.isValid())
525 {
526 QList<double> const values = solutionReply.value();
527 if (values[0] > INVALID_VALUE)
528 m_Rotation = values[0];
529 }
530
531 calculateFOV();
532}
533
534void FramingAssistant::rewordStepEvery(int v)
535{
536 QSpinBox * sp = dynamic_cast<QSpinBox *>(sender());
537 if (0 < v)
538 sp->setSuffix(i18np(" Scheduler job", " Scheduler jobs", v));
539 else
540 sp->setSuffix(i18n(" (first only)"));
541}
542
543}
This is the main window for KStars.
Definition kstars.h:90
static KStars * Instance()
Definition kstars.h:122
Q_SCRIPTABLE Q_NOREPLY void setApproxFOV(double FOV_Degrees)
DBUS interface function.
This is the canvas on which the sky is painted.
Definition skymap.h:54
The sky coordinates of a point in the sky.
Definition skypoint.h:45
void apparentCoord(long double jd0, long double jdf)
Computes the apparent coordinates for this SkyPoint for any epoch, accounting for the effects of prec...
Definition skypoint.cpp:720
SkyPoint catalogueCoord(long double jdf)
Computes the J2000.0 catalogue coordinates for this SkyPoint using the epoch removing aberration,...
Definition skypoint.cpp:730
static constexpr double DegToRad
DegToRad is a const static member equal to the number of radians in one degree (dms::PI/180....
Definition dms.h:390
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
KIOCORE_EXPORT QString dir(const QString &fileClass)
void clicked(bool checked)
void toggled(bool checked)
void editingFinished()
QDBusConnection sessionBus()
bool isValid() const const
void valueChanged(double d)
QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, Options options)
void append(QList< T > &&value)
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
QPointF topLeft() const const
QRectF translated(const QPointF &offset) const const
void setSuffix(const QString &suffix)
void valueChanged(int i)
bool isEmpty() const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void timeout()
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 31 2025 11:53:47 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.