• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Stellarium / stellarium / 12904061178

22 Jan 2025 08:11AM UTC coverage: 12.141% (-0.04%) from 12.184%
12904061178

push

github

web-flow
Translate stellarium-scripts.pot in lt

100% translated source file: 'stellarium-scripts.pot'
on 'lt'.

14599 of 120244 relevant lines covered (12.14%)

19025.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/plugins/Oculars/src/Oculars.cpp
1
/*
2
 * Copyright (C) 2009 Timothy Reaves
3
 * Copyright (C) 2011 Bogdan Marinov
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18
 */
19

20
#include "Oculars.hpp"
21
#include "OcularsGuiPanel.hpp"
22

23
#include "LabelMgr.hpp"
24
#include "SkyGui.hpp"
25
#include "StelActionMgr.hpp"
26
#include "StelApp.hpp"
27
#include "StelCore.hpp"
28
#include "StelFileMgr.hpp"
29
#include "StelGui.hpp"
30
#include "StelGuiItems.hpp"
31
#include "StelMainView.hpp"
32
#include "StelModuleMgr.hpp"
33
#include "StelMovementMgr.hpp"
34
#include "StelObjectMgr.hpp"
35
#include "StelPainter.hpp"
36
#include "StelProjector.hpp"
37
#include "StelTextureMgr.hpp"
38
#include "StelTranslator.hpp"
39
#include "SolarSystem.hpp"
40
#include "NebulaMgr.hpp"
41
#include "StelUtils.hpp"
42
#include "StelPropertyMgr.hpp"
43

44
#include <QAction>
45
#include <QDebug>
46
#include <QDir>
47
#include <QGraphicsWidget>
48
#include <QKeyEvent>
49
#include <QMenu>
50
#include <QMouseEvent>
51
#include <QPixmap>
52
#include <QMessageBox>
53

54
#include <cmath>
55
#include <stdexcept>
56

57
// When DEFAULT_FONT_SIZE is 13, GUI panel's font size was designed to be 12.
58
// This factor preserves the ratio when the fonts are scaled.
59
constexpr double GUI_PANEL_FONT_SIZE_FACTOR = 12.0 / 13.0;
60
// Design font size is 14, based on default app fontsize 13.
61
constexpr double FONT_SIZE_FACTOR = 14.0 / 13.0;
62

63
extern void qt_set_sequence_auto_mnemonic(bool b);
64

65
static QSettings *settings; //!< The settings as read in from the ini file.
66

67
//! This method is the one called automatically by the StelModuleMgr just
68
//! after loading the dynamic library
69
StelModule* OcularsStelPluginInterface::getStelModule() const
×
70
{
71
        return new Oculars();
×
72
}
73

74
StelPluginInfo OcularsStelPluginInterface::getPluginInfo() const
×
75
{
76
        // Allow to load the resources when used as a static plugin
77
        Q_INIT_RESOURCE(Oculars);
×
78

79
        StelPluginInfo info;
×
80
        info.id = "Oculars";
×
81
        info.displayedName = N_("Oculars");
×
82
        info.authors = "Timothy Reaves";
×
83
        info.contact = STELLARIUM_DEV_URL;
×
84
        info.description = N_("Shows the sky as if looking through a telescope eyepiece. (Only magnification and field of view are simulated.) It can also show a sensor frame and a Telrad sight.");
×
85
        info.version = OCULARS_PLUGIN_VERSION;
×
86
        info.license = OCULARS_PLUGIN_LICENSE;
×
87
        return info;
×
88
}
×
89

90
Oculars::Oculars()
×
91
        : selectedCCDIndex(-1)
×
92
        , selectedOcularIndex(-1)
×
93
        , selectedTelescopeIndex(-1)
×
94
        , selectedLensIndex(-1)
×
95
        , selectedCCDRotationAngle(0.0)
×
96
        , selectedCCDPrismPositionAngle(0.0)
×
97
        , arrowButtonScale(150)
×
98
        , flagShowCCD(false)
×
99
        , flagShowOculars(false)
×
100
        , flagShowCrosshairs(false)
×
101
        , flagShowTelrad(false)
×
102
        , usageMessageLabelID(-1)
×
103
        , flagCardinalPointsMain(false)
×
104
        , flagAdaptationMain(false)
×
105
        , flagLimitStarsMain(false)
×
106
        , magLimitStarsMain(0.0)
×
107
        , flagLimitStarsOculars(false)
×
108
        , magLimitStarsOculars(0.0)
×
109
        , flagAutoLimitMagnitude(false)
×
110
        , flagLimitDSOsMain(false)
×
111
        , magLimitDSOsMain(0.0)
×
112
        , flagLimitPlanetsMain(false)
×
113
        , magLimitPlanetsMain(0.0)
×
114
        , relativeStarScaleMain(1.0)
×
115
        , absoluteStarScaleMain(1.0)
×
116
        , relativeStarScaleOculars(1.0)
×
117
        , absoluteStarScaleOculars(1.0)
×
118
        , relativeStarScaleCCD(1.0)
×
119
        , absoluteStarScaleCCD(1.0)
×
120
        , flagMoonScaleMain(false)
×
121
        , flagMinorBodiesScaleMain(false)
×
122
        , flagSunScaleMain(false)
×
123
        , flagPlanetsScaleMain(false)
×
124
        , flagDSOPropHintMain(false)
×
125
        , milkyWaySaturation(1.0)
×
126
        , maxEyepieceAngle(0.0)
×
127
        , flagRequireSelection(true)
×
128
        , flagScaleImageCircle(true)
×
129
        , flagGuiPanelEnabled(false)
×
130
        , flagDMSDegrees(false)
×
131
        , flagHorizontalCoordinates(false)
×
132
        , flagSemiTransparency(false)
×
133
        , transparencyMask(85)
×
134
        , flagHideGridsLines(false)
×
135
        , flagGridLinesDisplayedMain(true)
×
136
        , flagConstellationLinesMain(true)
×
137
        , flagConstellationBoundariesMain(true)
×
138
        , flagAsterismLinesMain(true)
×
139
        , flagRayHelpersLinesMain(true)
×
140
        , flipVertMain(false)
×
141
        , flipHorzMain(false)
×
142
        , pxmapGlow(Q_NULLPTR)
×
143
        , pxmapOnIcon(Q_NULLPTR)
×
144
        , pxmapOffIcon(Q_NULLPTR)
×
145
        , toolbarButton(Q_NULLPTR)
×
146
        , flagShowOcularsButton(false)
×
147
        , ocularDialog(Q_NULLPTR)
×
148
        , ready(false)
×
149
        , actionShowOcular(Q_NULLPTR)
×
150
        , actionShowCrosshairs(Q_NULLPTR)
×
151
        , actionShowSensor(Q_NULLPTR)
×
152
        , actionShowTelrad(Q_NULLPTR)
×
153
        , actionConfiguration(Q_NULLPTR)
×
154
        , actionMenu(Q_NULLPTR)
×
155
        , actionTelescopeIncrement(Q_NULLPTR)
×
156
        , actionTelescopeDecrement(Q_NULLPTR)
×
157
        , actionOcularIncrement(Q_NULLPTR)
×
158
        , actionOcularDecrement(Q_NULLPTR)
×
159
        , guiPanel(Q_NULLPTR)
×
160
        , guiPanelFontSize(StelApp::getInstance().getScreenFontSize() * GUI_PANEL_FONT_SIZE_FACTOR)
×
161
        , textColor(0.)
×
162
        , lineColor(0.)
×
163
        , focuserColor(0.)
×
164
        , selectedSSO(Q_NULLPTR)
×
165
        , actualFOV(0.)
×
166
        , initialFOV(0.)
×
167
        , flagInitFOVUsage(false)
×
168
        , flagInitDirectionUsage(false)
×
169
        , flagAutosetMountForCCD(false)
×
170
        , flagScalingFOVForTelrad(false)
×
171
        , flagScalingFOVForCCD(true)
×
172
        , flagMaxExposureTimeForCCD(false)
×
173
        , flagShowResolutionCriteria(false)
×
174
        , equatorialMountEnabledMain(false)
×
175
        , reticleRotation(0.)
×
176
        , flagShowCcdCropOverlay(false)
×
177
        , flagShowCcdCropOverlayPixelGrid(false)
×
178
        , ccdCropOverlayHSize(DEFAULT_CCD_CROP_OVERLAY_SIZE)
×
179
        , ccdCropOverlayVSize(DEFAULT_CCD_CROP_OVERLAY_SIZE)
×
180
        , flagShowContour(false)
×
181
        , flagShowCardinals(false)
×
182
        , flagAlignCrosshair(false)
×
183
        , telradFOV(0.5f,2.f,4.f)
×
184
        , flagShowFocuserOverlay(false)
×
185
        , flagUseSmallFocuserOverlay(false)
×
186
        , flagUseMediumFocuserOverlay(true)
×
187
        , flagUseLargeFocuserOverlay(true)
×
188
{
189
        setObjectName("Oculars");
×
190
        setFontSizeFromApp(StelApp::getInstance().getScreenFontSize());
×
191
        connect(&StelApp::getInstance(), SIGNAL(screenFontSizeChanged(int)), this, SLOT(setFontSizeFromApp(int)));
×
192

193
        ccds = QList<CCD *>();
×
194
        oculars = QList<Ocular *>();
×
195
        telescopes = QList<Telescope *>();
×
196
        lenses = QList<Lens *> ();
×
197

198
#ifdef Q_OS_MACOS
199
        qt_set_sequence_auto_mnemonic(true);
200
#endif
201
}
×
202

203
Oculars::~Oculars()
×
204
{
205
        delete ocularDialog;
×
206
        ocularDialog = Q_NULLPTR;
×
207
        if (guiPanel)
×
208
                delete guiPanel;
×
209
        if (pxmapGlow)
×
210
                delete pxmapGlow;
×
211
        if (pxmapOnIcon)
×
212
                delete pxmapOnIcon;
×
213
        if (pxmapOffIcon)
×
214
                delete pxmapOffIcon;
×
215
        
216
        qDeleteAll(ccds);
×
217
        ccds.clear();
×
218
        qDeleteAll(telescopes);
×
219
        telescopes.clear();
×
220
        qDeleteAll(oculars);
×
221
        oculars.clear();
×
222
        qDeleteAll(lenses);
×
223
        lenses.clear();
×
224
}
×
225

226
QSettings* Oculars::getSettings()
×
227
{
228
        return settings;
×
229
}
230

231
bool Oculars::configureGui(bool show)
×
232
{
233
        if (show)
×
234
        {
235
                ocularDialog->setVisible(true);
×
236
        }
237

238
        return ready;
×
239
}
240

241
void Oculars::deinit()
×
242
{
243
        // update the ini file.
244
        settings->remove("ccd");
×
245
        settings->remove("ocular");
×
246
        settings->remove("telescope");
×
247
        settings->remove("lens");
×
248
        int index = 0;
×
249
        for (auto* ccd : std::as_const(ccds))
×
250
        {
251
                ccd->writeToSettings(settings, index);
×
252
                index++;
×
253
        }
254
        index = 0;
×
255
        for (auto* ocular : std::as_const(oculars))
×
256
        {
257
                ocular->writeToSettings(settings, index);
×
258
                index++;
×
259
        }
260
        index = 0;
×
261
        for (auto* telescope : std::as_const(telescopes))
×
262
        {
263
                telescope->writeToSettings(settings, index);
×
264
                index++;
×
265
        }
266
        index = 0;
×
267
        for (auto* lens : std::as_const(lenses))
×
268
        {
269
                lens->writeToSettings(settings, index);
×
270
                index++;
×
271
        }
272

273
        settings->setValue("ocular_count", oculars.count());
×
274
        settings->setValue("telescope_count", telescopes.count());
×
275
        settings->setValue("ccd_count", ccds.count());
×
276
        settings->setValue("lens_count", lenses.count());
×
277
        settings->setValue("ocular_index", qMax(0, selectedOcularIndex));
×
278
        settings->setValue("telescope_index", qMax(0, selectedTelescopeIndex));
×
279
        settings->setValue("ccd_index", qMax(0, selectedCCDIndex));
×
280
        settings->setValue("lens_index", selectedLensIndex);
×
281

282
        StelCore *core = StelApp::getInstance().getCore();
×
283
        StelSkyDrawer *skyDrawer = core->getSkyDrawer();
×
284
        disconnect(skyDrawer, SIGNAL(customStarMagLimitChanged(double)), this, SLOT(setMagLimitStarsOcularsManual(double)));
×
285
        disconnect(skyDrawer, SIGNAL(flagStarMagnitudeLimitChanged(bool)), this, SLOT(handleStarMagLimitToggle(bool)));
×
286
        if (flagShowCCD)
×
287
        {
288
                // Retrieve and restore star scales
289
                relativeStarScaleCCD=skyDrawer->getRelativeStarScale();
×
290
                absoluteStarScaleCCD=skyDrawer->getAbsoluteStarScale();
×
291
                skyDrawer->setRelativeStarScale(relativeStarScaleMain);
×
292
                skyDrawer->setAbsoluteStarScale(absoluteStarScaleMain);
×
293
        }
294
        else if (flagShowOculars)
×
295
        {
296
                qDebug() << "Oculars::deinit() .. restoring skyDrawer values while ocular view is active";
×
297

298
                if (!getFlagAutoLimitMagnitude())
×
299
                {
300
                        flagLimitStarsOculars=skyDrawer->getFlagStarMagnitudeLimit();
×
301
                        magLimitStarsOculars=skyDrawer->getCustomStarMagnitudeLimit();
×
302
                }
303
                skyDrawer->setCustomStarMagnitudeLimit(magLimitStarsMain);
×
304
                skyDrawer->setFlagStarMagnitudeLimit(flagLimitStarsMain);
×
305
                // Retrieve and restore star scales
306
                relativeStarScaleOculars=skyDrawer->getRelativeStarScale();
×
307
                absoluteStarScaleOculars=skyDrawer->getAbsoluteStarScale();
×
308
                skyDrawer->setRelativeStarScale(relativeStarScaleMain);
×
309
                skyDrawer->setAbsoluteStarScale(absoluteStarScaleMain);
×
310
        }
311

312
        settings->setValue("stars_scale_relative", QString::number(relativeStarScaleOculars, 'f', 2));
×
313
        settings->setValue("stars_scale_absolute", QString::number(absoluteStarScaleOculars, 'f', 2));
×
314
        settings->setValue("stars_scale_relative_ccd", QString::number(relativeStarScaleCCD, 'f', 2));
×
315
        settings->setValue("stars_scale_absolute_ccd", QString::number(absoluteStarScaleCCD, 'f', 2));
×
316
        settings->setValue("limit_stellar_magnitude_oculars_val", QString::number(magLimitStarsOculars, 'f', 2));
×
317
        settings->setValue("limit_stellar_magnitude_oculars", flagLimitStarsOculars);
×
318
        settings->setValue("text_color", textColor.toStr());
×
319
        settings->setValue("line_color", lineColor.toStr());
×
320
        settings->setValue("focuser_color", focuserColor.toStr());
×
321
        settings->sync();
×
322

323
        disconnect(this, SIGNAL(selectedOcularChanged(int)), this, SLOT(updateOcularReticle()));
×
324
        //disconnect(&StelApp::getInstance(), SIGNAL(colorSchemeChanged(const QString&)), this, SLOT(setStelStyle(const QString&)));
325
        disconnect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(retranslateGui()));
×
326

327
        protractorTexture.clear();
×
328
        protractorFlipVTexture.clear();
×
329
        protractorFlipHTexture.clear();
×
330
        protractorFlipHVTexture.clear();
×
331
}
×
332

333
void Oculars::setFontSize(const int fontSize, const int guiPanelFontSize)
×
334
{
335
        font.setPixelSize(fontSize);
×
336

337
        this->guiPanelFontSize = guiPanelFontSize;
×
338
        if (guiPanel)
×
339
                guiPanel->setFontSize(guiPanelFontSize);
×
340
}
×
341

342
void Oculars::setFontSizeFromApp(const int size)
×
343
{
344
        setFontSize(size * FONT_SIZE_FACTOR,
×
345
                    size * GUI_PANEL_FONT_SIZE_FACTOR);
×
346
}
×
347

348
//! Draw any parts on the screen which are for our module
349
void Oculars::draw(StelCore* core)
×
350
{
351
        if (flagShowTelrad)
×
352
        {
353
                paintTelrad();
×
354
        }
355
        else if (flagShowOculars)
×
356
        {
357
                if (selectedOcularIndex >= 0)
×
358
                {
359
                        paintOcularMask(core);
×
360
                        if (flagShowCrosshairs)
×
361
                                paintCrosshairs();
×
362

363
                        if (!flagGuiPanelEnabled)
×
364
                        {
365
                                // Paint the information in the upper-right hand corner
366
                                paintText(core);
×
367
                        }
368
                }
369
                else
370
                {
371
                        qWarning() << "Oculars: the selected ocular index of "
×
372
                                   << selectedOcularIndex << " is greater than the ocular count of "
×
373
                                   << oculars.count() << ". Module disabled!";
×
374
                }
375
        }
376
        else if (flagShowCCD)
×
377
        {
378
                paintCCDBounds();
×
379
                if (!flagGuiPanelEnabled)
×
380
                {
381
                        // Paint the information in the upper-right hand corner
382
                        paintText(core);
×
383
                }
384
        }
385
}
×
386

387
//! Determine which "layer" the plugin's drawing will happen on.
388
double Oculars::getCallOrder(StelModuleActionName actionName) const
×
389
{
390
        double order = 1000.0; // Very low priority, unless we interact.
×
391

392
        if (actionName==StelModule::ActionHandleMouseMoves ||
×
393
            actionName==StelModule::ActionHandleMouseClicks)
394
        {
395
                // Make sure we are called before MovementMgr (we need to even call it once!)
396
                order = StelApp::getInstance().getModuleMgr().getModule("StelMovementMgr")->getCallOrder(actionName) - 1.0;
×
397
        }
398
        else if (actionName==StelModule::ActionDraw)
×
399
        {
400
                order = GETSTELMODULE(LabelMgr)->getCallOrder(actionName) + 100.0;
×
401
        }
402
        return order;
×
403
}
404

405
void Oculars::handleMouseClicks(class QMouseEvent* event)
×
406
{
407
        StelCore *core = StelApp::getInstance().getCore();
×
408
        const StelProjectorP prj = core->getProjection(StelCore::FrameJ2000, StelCore::RefractionAuto);
×
409
        StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
×
410
        qreal ppx = params.devicePixelsPerPixel;
×
411
        
412
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
413
        const auto eventPosX = event->position().x();
×
414
        const auto eventPosY = event->position().y();
×
415
#else
416
        const auto eventPosX = event->x();
417
        const auto eventPosY = event->y();
418
#endif
419

420
        if (guiPanel)
×
421
        {
422
                const auto ratio = core->getCurrentStelProjectorParams().devicePixelsPerPixel;
×
423
                // Remove all events on the sky within Ocular GUI Panel.
424
                if (eventPosX > guiPanel->pos().x()*ratio && eventPosY > prj->getViewportHeight() - ratio*guiPanel->size().height())
×
425
                {
426
                        event->setAccepted(true);
×
427
                        return;
×
428
                }
429
        }
430

431
        // In case we show oculars with black circle, ignore mouse presses outside image circle:
432
        // https://sourceforge.net/p/stellarium/discussion/278769/thread/57893bb3/?limit=25#75c0
433
        if ((flagShowOculars) ) //&& !getFlagUseSemiTransparency()) // Not sure: ignore or allow selection of semi-hidden stars?
×
434
        {
435
                float wh = prj->getViewportWidth()*0.5f; // get half of width of the screen
×
436
                float hh = prj->getViewportHeight()*0.5f; // get half of height of the screen
×
437
                float mx = eventPosX-wh; // point 0 in center of the screen, axis X directed to right
×
438
                float my = eventPosY-hh; // point 0 in center of the screen, axis Y directed to bottom
×
439

440
                double inner = 0.5 * params.viewportFovDiameter * ppx;
×
441
                // See if we need to scale the mask
442
                if (flagScaleImageCircle && oculars[selectedOcularIndex]->apparentFOV() > 0.0 && !oculars[selectedOcularIndex]->isBinoculars())
×
443
                {
444
                        inner = oculars[selectedOcularIndex]->apparentFOV() * inner / maxEyepieceAngle;
×
445
                }
446

447
                if (mx*mx+my*my>static_cast<float>(inner*inner)) // click outside ocular circle? Gobble event.
×
448
                {
449
                        event->setAccepted(true);
×
450
                        return;
×
451
                }
452
        }
453

454
        StelMovementMgr *movementManager = core->getMovementMgr();
×
455

456
        if (flagShowOculars)
×
457
                movementManager->handleMouseClicks(event); // force it here for selection!
×
458

459
        if (StelApp::getInstance().getStelObjectMgr().getWasSelected())
×
460
        {
461
                if (flagShowOculars)
×
462
                {
463
                        // center the selected object in the ocular, and track.
464
                        movementManager->setFlagTracking(true);
×
465
                }
466
                else
467
                {
468
                        // remove the usage label if it is being displayed.
469
                        hideUsageMessageIfDisplayed();
×
470
                }
471
        }
472
        else if(flagShowOculars)
×
473
        {
474
                // The ocular is displayed, but no object is selected.  So don't track the stars.  We may have locked
475
                // the position of the screen if the movement keys were used.  so call this to be on the safe side.
476
                movementManager->setFlagLockEquPos(false);                
×
477
        }
478
        event->setAccepted(false);
×
479
}
×
480

481
void Oculars::updateLatestSelectedSSO()
×
482
{
483
        QList<StelObjectP> selectedObjects = GETSTELMODULE(StelObjectMgr)->getSelectedObject();
×
484
        if (!selectedObjects.isEmpty())
×
485
        {
486
                selectedSSO = (selectedObjects[0]->getType()=="Planet") ? dynamic_cast<Planet*>(selectedObjects[0].data()) : Q_NULLPTR;
×
487
        }
488
}
×
489

490
void Oculars::init()
×
491
{
492
        // Load settings from ocular.ini
493
        try {
494
                validateAndLoadIniFile();
×
495
                // assume all is well
496
                ready = true;
×
497

498
                setFlagRequireSelection(settings->value("require_selection_to_zoom", true).toBool());
×
499
                flagScaleImageCircle = settings->value("use_max_exit_circle", false).toBool();
×
500
                int ocularCount = settings->value("ocular_count", 0).toInt();
×
501
                int actualOcularCount = ocularCount;
×
502
                for (int index = 0; index < ocularCount; index++)
×
503
                {
504
                        Ocular *newOcular = Ocular::ocularFromSettings(settings, index);
×
505
                        if (newOcular != Q_NULLPTR)
×
506
                        {
507
                                oculars.append(newOcular);
×
508
                        }
509
                        else
510
                        {
511
                                actualOcularCount--;
×
512
                        }
513
                }
514
                if (actualOcularCount < 1)
×
515
                {
516
                        if (actualOcularCount < ocularCount)
×
517
                        {
518
                                qWarning() << "The Oculars ini file appears to be corrupt; delete it.";
×
519
                        }
520
                        else
521
                        {
522
                                qWarning() << "There are no oculars defined for the Oculars plugin; plugin will be disabled.";
×
523
                        }
524
                        ready = false;
×
525
                }
526
                else
527
                {
528
                        selectedOcularIndex = qMax(0, settings->value("ocular_index", 0).toInt());
×
529
                }
530

531
                int ccdCount = settings->value("ccd_count", 0).toInt();
×
532
                int actualCcdCount = ccdCount;
×
533
                for (int index = 0; index < ccdCount; index++)
×
534
                {
535
                        CCD *newCCD = CCD::ccdFromSettings(settings, index);
×
536
                        if (newCCD != Q_NULLPTR)
×
537
                        {
538
                                ccds.append(newCCD);
×
539
                        }
540
                        else
541
                        {
542
                                actualCcdCount--;
×
543
                        }
544
                }
545
                if (actualCcdCount < ccdCount)
×
546
                {
547
                        qWarning() << "The Oculars ini file appears to be corrupt; delete it.";
×
548
                        ready = false;
×
549
                }
550
                selectedCCDIndex = qMax(0, settings->value("ccd_index", 0).toInt());
×
551

552
                int telescopeCount = qMax(0, settings->value("telescope_count", 0).toInt());
×
553
                int actualTelescopeCount = telescopeCount;
×
554
                for (int index = 0; index < telescopeCount; index++)
×
555
                {
556
                        Telescope *newTelescope = Telescope::telescopeFromSettings(settings, index);
×
557
                        if (newTelescope != Q_NULLPTR)
×
558
                        {
559
                                telescopes.append(newTelescope);
×
560
                        }
561
                        else
562
                        {
563
                                actualTelescopeCount--;
×
564
                        }
565
                }
566
                if (actualTelescopeCount < 1)
×
567
                {
568
                        if (actualTelescopeCount < telescopeCount)
×
569
                        {
570
                                qWarning() << "The Oculars ini file appears to be corrupt; delete it.";
×
571
                        }
572
                        else
573
                        {
574
                                qWarning() << "There are no telescopes defined for the Oculars plugin; plugin will be disabled.";
×
575
                        }
576
                        ready = false;
×
577
                }
578
                else
579
                {
580
                        selectedTelescopeIndex = settings->value("telescope_index", 0).toInt();
×
581
                }
582

583
                int lensCount = settings->value("lens_count", 0).toInt();
×
584
                int actualLensCount = lensCount;
×
585
                for (int index = 0; index<lensCount; index++)
×
586
                {
587
                        Lens *newLens = Lens::lensFromSettings(settings, index);
×
588
                        if (newLens != Q_NULLPTR)
×
589
                        {
590
                                lenses.append(newLens);
×
591
                        }
592
                        else
593
                        {
594
                                actualLensCount--;
×
595
                        }
596
                }
597
                if (lensCount > 0 && actualLensCount < lensCount)
×
598
                {
599
                        qWarning() << "The Oculars ini file appears to be corrupt; delete it.";
×
600
                }
601
                selectedLensIndex=settings->value("lens_index", -1).toInt(); // Lens is not selected by default!
×
602

603
                pxmapGlow = new QPixmap(":/graphicGui/miscGlow32x32.png");
×
604
                pxmapOnIcon = new QPixmap(":/ocular/bt_ocular_on.png");
×
605
                pxmapOffIcon = new QPixmap(":/ocular/bt_ocular_off.png");
×
606

607
                ocularDialog = new OcularDialog(this, &ccds, &oculars, &telescopes, &lenses);
×
608
                initializeActivationActions();
×
609
                determineMaxEyepieceAngle();
×
610

611
                const int defaultGuiPanelFontSize = StelApp::getInstance().getScreenFontSize() * GUI_PANEL_FONT_SIZE_FACTOR;
×
612
                guiPanelFontSize=settings->value("gui_panel_fontsize", defaultGuiPanelFontSize).toInt();
×
613
                enableGuiPanel(settings->value("enable_control_panel", true).toBool());
×
614
                textColor=Vec3f(settings->value("text_color", "0.8,0.48,0.0").toString());
×
615
                lineColor=Vec3f(settings->value("line_color", "0.77,0.14,0.16").toString());
×
616
                telradFOV=Vec4f(settings->value("telrad_fov", "0.5,2.0,4.0,0.0").toString());
×
617
                focuserColor=Vec3f(settings->value("focuser_color", "0.0,0.67,1.0").toString());
×
618

619
                // This must come ahead of setFlagAutosetMountForCCD (GH #505)
620
                StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
×
621
                equatorialMountEnabledMain = propMgr->getStelPropertyValue("StelMovementMgr.equatorialMount").toBool();
×
622

623
                // For historical reasons, name of .ini entry and description of checkbox (and therefore flag name) are reversed.
624
                setFlagDMSDegrees( ! settings->value("use_decimal_degrees", false).toBool());
×
625
                setFlagHorizontalCoordinates(settings->value("use_horizontal_coordinates", false).toBool());
×
626
                setFlagAutoLimitMagnitude(settings->value("autolimit_stellar_magnitude", true).toBool());
×
627
                flagLimitStarsOculars=settings->value("limit_stellar_magnitude_oculars", false).toBool();
×
628
                magLimitStarsOculars=settings->value("limit_stellar_magnitude_oculars_val", 12.).toDouble();
×
629
                connect(this, SIGNAL(flagAutoLimitMagnitudeChanged(bool)), this, SLOT(handleAutoLimitToggle(bool))); // only after first initialisation!
×
630
                setFlagInitFovUsage(settings->value("use_initial_fov", false).toBool());
×
631
                setFlagInitDirectionUsage(settings->value("use_initial_direction", false).toBool());
×
632
                setFlagUseSemiTransparency(settings->value("use_semi_transparency", false).toBool());
×
633
                setTransparencyMask(settings->value("transparency_mask", 85).toInt());
×
634
                setFlagHideGridsLines(settings->value("hide_grids_and_lines", true).toBool());
×
635
                setFlagAutosetMountForCCD(settings->value("use_mount_autoset", false).toBool());
×
636
                setFlagScalingFOVForTelrad(settings->value("use_telrad_fov_scaling", true).toBool());
×
637
                setFlagScalingFOVForCCD(settings->value("use_ccd_fov_scaling", true).toBool());
×
638
                setFlagMaxExposureTimeForCCD(settings->value("show_ccd_exposure_time", false).toBool());
×
639
                setFlagShowResolutionCriteria(settings->value("show_resolution_criteria", false).toBool());
×
640
                setArrowButtonScale(settings->value("arrow_scale", 150).toInt());
×
641
                setFlagShowOcularsButton(settings->value("show_toolbar_button", false).toBool());
×
642
                relativeStarScaleOculars=settings->value("stars_scale_relative", 1.0).toDouble();
×
643
                absoluteStarScaleOculars=settings->value("stars_scale_absolute", 1.0).toDouble();
×
644
                relativeStarScaleCCD=settings->value("stars_scale_relative_ccd", 1.0).toDouble();
×
645
                absoluteStarScaleCCD=settings->value("stars_scale_absolute_ccd", 1.0).toDouble();
×
646
                setFlagShowCcdCropOverlay(settings->value("show_ccd_crop_overlay", false).toBool());
×
647
                setFlagShowCcdCropOverlayPixelGrid(settings-> value("ccd_crop_overlay_pixel_grid",false).toBool());
×
648
                setCcdCropOverlayHSize(settings->value("ccd_crop_overlay_hsize", DEFAULT_CCD_CROP_OVERLAY_SIZE).toInt());
×
649
                setCcdCropOverlayVSize(settings->value("ccd_crop_overlay_vsize", DEFAULT_CCD_CROP_OVERLAY_SIZE).toInt());
×
650
                setFlagShowContour(settings->value("show_ocular_contour", false).toBool());
×
651
                setFlagShowCardinals(settings->value("show_ocular_cardinals", false).toBool());
×
652
                setFlagAlignCrosshair(settings->value("align_crosshair", false).toBool());
×
653
                setFlagShowFocuserOverlay(settings->value("show_focuser_overlay", false).toBool());
×
654
                setFlagUseSmallFocuserOverlay(settings->value("use_small_focuser_overlay", false).toBool());
×
655
                setFlagUseMediumFocuserOverlay(settings->value("use_medium_focuser_overlay", true).toBool());
×
656
                setFlagUseLargeFocuserOverlay(settings->value("use_large_focuser_overlay", false).toBool());
×
657
        }
658
        catch (std::runtime_error& e)
×
659
        {
660
                qWarning() << "WARNING: unable to locate ocular.ini file or create a default one for Ocular plugin: " << e.what();
×
661
                ready = false;
×
662
        }
×
663

664
        protractorTexture = StelApp::getInstance().getTextureManager().createTexture(":/ocular/Protractor.png");
×
665
        protractorFlipHTexture = StelApp::getInstance().getTextureManager().createTexture(":/ocular/ProtractorFlipH.png");
×
666
        protractorFlipVTexture = StelApp::getInstance().getTextureManager().createTexture(":/ocular/ProtractorFlipV.png");
×
667
        protractorFlipHVTexture = StelApp::getInstance().getTextureManager().createTexture(":/ocular/ProtractorFlipHV.png");
×
668
        // enforce check existence of reticle for the current eyepiece
669
        updateOcularReticle();
×
670

671
        connect(&StelApp::getInstance(), SIGNAL(languageChanged()), this, SLOT(retranslateGui()));
×
672
        connect(this, SIGNAL(selectedOcularChanged(int)), this, SLOT(updateOcularReticle()));
×
673
        StelCore *core = StelApp::getInstance().getCore();
×
674
        StelSkyDrawer *skyDrawer = core->getSkyDrawer();
×
675
        connect(skyDrawer, SIGNAL(flagStarMagnitudeLimitChanged(bool)), this, SLOT(handleStarMagLimitToggle(bool)));
×
676
        StelObjectMgr* objectMgr = GETSTELMODULE(StelObjectMgr);
×
677
        connect(objectMgr, SIGNAL(selectedObjectChanged(StelModule::StelModuleSelectAction)), this, SLOT(updateLatestSelectedSSO()));
×
678
}
×
679

680
void Oculars::determineMaxEyepieceAngle()
×
681
{
682
        if (ready)
×
683
        {
684
                for (const auto* ocular : std::as_const(oculars))
×
685
                {
686
                        if (ocular->apparentFOV() > maxEyepieceAngle)
×
687
                        {
688
                                maxEyepieceAngle = ocular->apparentFOV();
×
689
                        }
690
                }
691
        }
692
        // ensure it is not zero
693
        if (maxEyepieceAngle == 0.0)
×
694
        {
695
                maxEyepieceAngle = 1.0;
×
696
        }
697
}
×
698

699
void Oculars::instrumentChanged()
×
700
{
701
        // We only zoom if in ocular mode.
702
        if (flagShowOculars)
×
703
        {
704
                // If we are already in Ocular mode, we must reset scalings because zoom() also resets.
705
                StelSkyDrawer *skyDrawer = StelApp::getInstance().getCore()->getSkyDrawer();
×
706
                skyDrawer->setRelativeStarScale(relativeStarScaleMain);
×
707
                skyDrawer->setAbsoluteStarScale(absoluteStarScaleMain);
×
708
                zoom(true);
×
709
        }
710
        else if (flagShowCCD)
×
711
                setScreenFOVForCCD();
×
712
}
×
713

714
void Oculars::setFlagScaleImageCircle(bool state)
×
715
{
716
        if (state)
×
717
        {
718
                determineMaxEyepieceAngle();
×
719
        }
720
        flagScaleImageCircle = state;
×
721
        settings->setValue("use_max_exit_circle", state);
×
722
        settings->sync();
×
723
        emit flagScaleImageCircleChanged(state);
×
724
}
×
725

726
void Oculars::setScreenFOVForCCD()
×
727
{
728
        // CCD is not shown and FOV scaling is disabled, but telescope is changed - do not change FOV!
729
        if (!(getFlagScalingFOVForCCD() && flagShowCCD))
×
730
                return;
×
731

732
        Lens * lens = selectedLensIndex >=0  ? lenses[selectedLensIndex] : Q_NULLPTR;
×
733
        if (selectedCCDIndex > -1 && selectedTelescopeIndex > -1)
×
734
        {
735
                StelCore *core = StelApp::getInstance().getCore();
×
736
                StelMovementMgr *movementManager = core->getMovementMgr();
×
737
                double actualFOVx = ccds[selectedCCDIndex]->getActualFOVx(telescopes[selectedTelescopeIndex], lens);
×
738
                double actualFOVy = ccds[selectedCCDIndex]->getActualFOVy(telescopes[selectedTelescopeIndex], lens);
×
739
                if (actualFOVx < actualFOVy)
×
740
                {
741
                        actualFOVx = actualFOVy;
×
742
                }
743
                double factor = 1.75;
×
744
                if (ccds[selectedCCDIndex]->hasOAG()) factor *= 2;
×
745
                movementManager->setFlagTracking(true);
×
746
                movementManager->zoomTo(actualFOVx * factor, 0.f);
×
747
        }
748
}
749

750
void Oculars::enableGuiPanel(bool enable)
×
751
{
752
        if (enable)
×
753
        {
754
                if (!guiPanel)
×
755
                {
756
                        StelGui* gui= dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
757
                        if (gui)
×
758
                        {
759
                                guiPanel = new OcularsGuiPanel(this, gui->getSkyGui());
×
760
                                if (flagShowOculars)
×
761
                                        guiPanel->showOcularGui();
×
762
                                else if (flagShowCCD)
×
763
                                        guiPanel->showCcdGui();
×
764
                        }
765
                }
766
        }
767
        else
768
        {
769
                if (guiPanel)
×
770
                {
771
                        guiPanel->hide();
×
772
                        delete guiPanel;
×
773
                        guiPanel = Q_NULLPTR;
×
774
                }
775
        }
776
        flagGuiPanelEnabled = enable;
×
777
        settings->setValue("enable_control_panel", enable);
×
778
        settings->sync();
×
779
        emit flagGuiPanelEnabledChanged(enable);
×
780
}
×
781

782
void Oculars::retranslateGui()
×
783
{
784
        if (guiPanel)
×
785
        {
786
                // TODO: Fix this hack!
787
                
788
                // Delete and re-create the panel to retranslate its strings
789
                guiPanel->hide();
×
790
                delete guiPanel;
×
791
                guiPanel = Q_NULLPTR;
×
792
                
793
                StelGui* gui= dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
794
                if (gui)
×
795
                {
796
                        guiPanel = new OcularsGuiPanel(this, gui->getSkyGui());
×
797
                        if (flagShowOculars)
×
798
                                guiPanel->showOcularGui();
×
799
                        else if (flagShowCCD)
×
800
                                guiPanel->showCcdGui();
×
801
                }
802
        }
803
}
×
804

805
void Oculars::updateOcularReticle(void)
×
806
{
807
        reticleRotation = 0.0;
×
808
        QString reticleTexturePath=oculars[selectedOcularIndex]->reticlePath();
×
809
        if (reticleTexturePath.length()==0)
×
810
                reticleTexture=StelTextureSP();
×
811
        else
812
        {
813
                StelTextureMgr& manager = StelApp::getInstance().getTextureManager();
×
814
                //Load OpenGL textures
815
                StelTexture::StelTextureParams params;
×
816
                params.generateMipmaps = true;
×
817
                reticleTexture = manager.createTexture(reticleTexturePath, params);
×
818
        }
819
}
×
820

821
void Oculars::updateLists()
×
822
{
823
        if (oculars.isEmpty())
×
824
        {
825
                selectedOcularIndex = -1;
×
826
                enableOcular(false);
×
827
        }
828
        else
829
        {
830
                if (selectedOcularIndex >= oculars.count())
×
831
                        selectedOcularIndex = oculars.count() - 1;
×
832

833
                if (flagShowOculars)
×
834
                        emit selectedOcularChanged(selectedOcularIndex);
×
835
        }
836

837
        if (telescopes.isEmpty())
×
838
        {
839
                selectedTelescopeIndex = -1;
×
840
                enableOcular(false);
×
841
                toggleCCD(false);
×
842
        }
843
        else
844
        {
845
                if (selectedTelescopeIndex >= telescopes.count())
×
846
                        selectedTelescopeIndex = telescopes.count() - 1;
×
847

848
                if (flagShowOculars || flagShowCCD)
×
849
                        emit selectedTelescopeChanged(selectedTelescopeIndex);
×
850
        }
851

852
        if (ccds.isEmpty())
×
853
        {
854
                selectedCCDIndex = -1;
×
855
                toggleCCD(false);
×
856
        }
857
        else
858
        {
859
                if (selectedCCDIndex >= ccds.count())
×
860
                        selectedCCDIndex = ccds.count() - 1;
×
861

862
                if (flagShowCCD)
×
863
                        emit selectedCCDChanged(selectedCCDIndex);
×
864
        }
865

866
        if (lenses.isEmpty())
×
867
                selectedLensIndex = -1;
×
868
        else
869
        {
870
                if (selectedLensIndex >= lenses.count())
×
871
                        selectedLensIndex = lenses.count() - 1;
×
872
        }
873
}
×
874

875
void Oculars::ccdRotationReset()
×
876
{
877
        if (selectedCCDIndex<0)
×
878
                return;
×
879
        CCD *ccd = ccds[selectedCCDIndex];
×
880
        if (ccd)
×
881
        {
882
                ccd->setChipRotAngle(0.0);
×
883
                emit selectedCCDChanged(selectedCCDIndex);
×
884
                emit selectedCCDRotationAngleChanged(0.0);
×
885
        }
886
}
887

888
void Oculars::prismPositionAngleReset()
×
889
{
890
        if (selectedCCDIndex<0)
×
891
                return;
×
892
        CCD *ccd = ccds[selectedCCDIndex];
×
893
        if (ccd)
×
894
        {
895
                ccd->setPrismPosAngle(0.0);
×
896
                emit selectedCCDChanged(selectedCCDIndex);
×
897
                emit selectedCCDPrismPositionAngleChanged(0.0);
×
898
        }
899
}
900

901
void Oculars::setSelectedCCDRotationAngle(double angle)
×
902
{
903
        if (selectedCCDIndex<0)
×
904
                return;
×
905

906
        CCD *ccd = ccds[selectedCCDIndex];
×
907
        if (ccd)
×
908
        {
909
                ccd->setChipRotAngle(angle);
×
910
                emit selectedCCDRotationAngleChanged(angle);
×
911
        }
912
}
913

914
double Oculars::getSelectedCCDRotationAngle() const
×
915
{
916
        if (selectedCCDIndex<0)
×
917
                return 0.0;
×
918
        CCD *ccd = ccds[selectedCCDIndex];
×
919
        if (ccd) return ccd->chipRotAngle();
×
920
        else return 0.0;
×
921
}
922

923
void Oculars::setSelectedCCDPrismPositionAngle(double angle)
×
924
{
925
        if (selectedCCDIndex<0)
×
926
                return;
×
927

928
        CCD *ccd = ccds[selectedCCDIndex];
×
929
        if (ccd)
×
930
        {
931
                ccd->setPrismPosAngle(angle);
×
932
                emit selectedCCDPrismPositionAngleChanged(angle);
×
933
        }
934
}
935

936
double Oculars::getSelectedCCDPrismPositionAngle() const
×
937
{
938
        if (selectedCCDIndex<0)
×
939
                return 0.0;
×
940
        CCD *ccd = ccds[selectedCCDIndex];
×
941
        if (ccd) return ccd->prismPosAngle();
×
942
        else return 0.0;
×
943
}
944

945
void Oculars::enableOcular(bool enableOcularMode)
×
946
{
947
        if (enableOcularMode)
×
948
        {
949
                // Close the sensor view if it's displayed
950
                if (flagShowCCD)
×
951
                {
952
                        toggleCCD(false);
×
953
                        flagShowCCD = false;
×
954
                        selectedCCDIndex = -1;
×
955
                }
956

957
                // Close the Telrad sight if it's displayed
958
                if (flagShowTelrad)
×
959
                {
960
                        toggleTelrad(false);
×
961
                }
962

963
                // Check to ensure that we have enough oculars & telescopes, as they may have been edited in the config dialog
964
                if (oculars.count() == 0)
×
965
                {
966
                        selectedOcularIndex = -1;
×
967
                        qWarning() << "No oculars found";
×
968
                }
969
                else if (oculars.count() > 0 && selectedOcularIndex == -1)
×
970
                {
971
                        selectedOcularIndex = 0;
×
972
                }
973
                if (telescopes.count() == 0)
×
974
                {
975
                        selectedTelescopeIndex = -1;
×
976
                        qWarning() << "No telescopes found";
×
977
                }
978
                else if (telescopes.count() > 0 && selectedTelescopeIndex == -1)
×
979
                {
980
                        selectedTelescopeIndex = 0;
×
981
                }
982
        }
983

984
        if (!ready  || selectedOcularIndex == -1 ||  (selectedTelescopeIndex == -1 && !isBinocularDefined()))
×
985
        {
986
                qWarning() << "The Oculars module has been disabled.";
×
987
                return;
×
988
        }
989

990
        StelCore *core = StelApp::getInstance().getCore();
×
991
        LabelMgr* labelManager = GETSTELMODULE(LabelMgr);
×
992

993
        // Toggle the ocular view on & off. To toggle on, we want to ensure there is a selected object.
994
        if (!flagShowOculars && !flagShowTelrad && flagRequireSelection && !StelApp::getInstance().getStelObjectMgr().getWasSelected() )
×
995
        {
996
                if (usageMessageLabelID == -1)
×
997
                {
998
                        QFontMetrics metrics(font);
×
999
                        QString labelText = q_("Please select an object before switching to ocular view.");
×
1000
                        StelProjector::StelProjectorParams projectorParams = core->getCurrentStelProjectorParams();
×
1001
                        int yPositionOffset = qRound(projectorParams.viewportXywh[3]*projectorParams.viewportCenterOffset[1]);
×
1002
                        int xPosition = qRound(projectorParams.viewportCenter[0] - 0.5 * metrics.boundingRect(labelText).width());
×
1003
                        int yPosition = qRound(projectorParams.viewportCenter[1] - yPositionOffset - 0.5 * metrics.height());
×
1004
                        const char *tcolor = "#99FF99";
×
1005
                        usageMessageLabelID = labelManager->labelScreen(labelText, xPosition, yPosition,
×
1006
                                                                        true, font.pixelSize(), tcolor);
×
1007
                }
×
1008
        }
1009
        else
1010
        {
1011
                if (selectedOcularIndex != -1)
×
1012
                {
1013
                        // remove the usage label if it is being displayed.
1014
                        hideUsageMessageIfDisplayed();
×
1015
                        flagShowOculars = enableOcularMode;
×
1016
                        zoom(false);
×
1017
                        //BM: I hope this is the right place...
1018
                        if (guiPanel)
×
1019
                                guiPanel->showOcularGui();
×
1020
                }
1021
        }
1022

1023
        emit enableOcularChanged(flagShowOculars);
×
1024
}
1025

1026
void Oculars::decrementCCDIndex()
×
1027
{
1028
        selectedCCDIndex--;
×
1029
        if (selectedCCDIndex == -1)
×
1030
        {
1031
                selectedCCDIndex = ccds.count() - 1;
×
1032
        }
1033
        emit selectedCCDChanged(selectedCCDIndex);
×
1034
}
×
1035

1036
void Oculars::decrementOcularIndex()
×
1037
{
1038
        selectedOcularIndex--;
×
1039
        if (selectedOcularIndex == -1)
×
1040
        {
1041
                selectedOcularIndex = oculars.count() - 1;
×
1042
        }
1043
        // validate the new selection
1044
        if (selectedOcularIndex > -1 && !oculars[selectedOcularIndex]->isBinoculars())
×
1045
        {
1046
                if ( selectedTelescopeIndex == -1 && telescopes.count() == 0)
×
1047
                {
1048
                        // reject the change
1049
                        selectedOcularIndex++;
×
1050
                }
1051

1052
                if (selectedTelescopeIndex == -1)
×
1053
                        selectedTelescopeIndex = 0;
×
1054
        }
1055
        emit selectedOcularChanged(selectedOcularIndex);
×
1056
}
×
1057

1058
void Oculars::decrementTelescopeIndex()
×
1059
{
1060
        selectedTelescopeIndex--;
×
1061
        if (selectedTelescopeIndex == -1)
×
1062
        {
1063
                selectedTelescopeIndex = telescopes.count() - 1;
×
1064
        }
1065
        emit selectedTelescopeChanged(selectedTelescopeIndex);
×
1066
}
×
1067

1068
void Oculars::decrementLensIndex()
×
1069
{
1070
        selectedLensIndex--;
×
1071
        if (selectedLensIndex == lenses.count())
×
1072
        {
1073
                selectedLensIndex = -1;
×
1074
        }
1075
        if (selectedLensIndex == -2)
×
1076
        {
1077
                selectedLensIndex = lenses.count() - 1;
×
1078
        }
1079
        emit selectedLensChanged(selectedLensIndex);
×
1080
}
×
1081

1082
void Oculars::rotateReticleClockwise()
×
1083
{
1084
        // Step: 5 degrees
1085
        reticleRotation -= 5.0;
×
1086
}
×
1087

1088
void Oculars::rotateReticleCounterclockwise()
×
1089
{
1090
        // Step: 5 degrees
1091
        reticleRotation += 5.0;
×
1092
}
×
1093

1094
void Oculars::displayPopupMenu()
×
1095
{
1096
        QMenu * popup = new QMenu(&StelMainView::getInstance());
×
1097

1098
        if (flagShowOculars)
×
1099
        {
1100
                // We are in Oculars mode
1101
                // We want to show all of the Oculars, and if the current ocular is not a binocular,
1102
                // we will also show the telescopes.
1103
                if (!oculars.isEmpty())
×
1104
                {
1105
                        popup->addAction(q_("&Previous ocular"), this, SLOT(decrementOcularIndex()));
×
1106
                        popup->addAction(q_("&Next ocular"), this, SLOT(incrementOcularIndex()));
×
1107
                        QMenu* submenu = new QMenu(q_("Select &ocular"), popup);
×
1108
                        int availableOcularCount = 0;
×
1109
                        for (int index = 0; index < oculars.count(); ++index)
×
1110
                        {
1111
                                QString label;
×
1112
                                if (availableOcularCount < 10)
×
1113
                                {
1114
                                        label = QString("&%1: %2").arg(availableOcularCount).arg(oculars[index]->name());
×
1115
                                }
1116
                                else
1117
                                {
1118
                                        label = oculars[index]->name();
×
1119
                                }
1120
                                //BM: Does this happen at all any more?
1121
                                QAction* action = Q_NULLPTR;
×
1122
                                if (selectedTelescopeIndex != -1 || oculars[index]->isBinoculars())
×
1123
                                {
1124
                                        action = submenu->addAction(label, submenu, [=](){selectOcularAtIndex(index);});
×
1125
                                        availableOcularCount++;
×
1126
                                }
1127

1128
                                if (action && index == selectedOcularIndex)
×
1129
                                {
1130
                                        action->setCheckable(true);
×
1131
                                        action->setChecked(true);
×
1132
                                }
1133
                        }
×
1134
                        popup->addMenu(submenu);
×
1135
                        popup->addSeparator();
×
1136
                }
1137

1138
                // If there is more than one telescope, show the prev/next/list complex.
1139
                // If the selected ocular is a binoculars, show nothing.
1140
                if (telescopes.count() > 1 && (selectedOcularIndex > -1 && !oculars[selectedOcularIndex]->isBinoculars()))
×
1141
                {
1142
                        QMenu* submenu = addTelescopeSubmenu(popup);
×
1143
                        popup->addMenu(submenu);
×
1144
                        submenu = addLensSubmenu(popup);
×
1145
                        popup->addMenu(submenu);
×
1146
                        popup->addSeparator();
×
1147
                }
1148

1149
                QAction* action = popup->addAction(q_("Toggle &crosshair"));
×
1150
                action->setCheckable(true);
×
1151
                action->setChecked(flagShowCrosshairs);
×
1152
                connect(action, SIGNAL(toggled(bool)), actionShowCrosshairs, SLOT(setChecked(bool)));
×
1153
        }
1154
        else
1155
        {
1156
                // We are not in ocular mode
1157
                // We want to show the CCD's, and if a CCD is selected, the telescopes
1158
                //(as a CCD requires a telescope) and the general menu items.
1159
                QAction* action = new QAction(q_("Configure &Oculars"), popup);
×
1160
                action->setCheckable(true);
×
1161
                action->setChecked(ocularDialog->visible());
×
1162
                connect(action, SIGNAL(triggered(bool)), ocularDialog, SLOT(setVisible(bool)));
×
1163
                popup->addAction(action);
×
1164
                popup->addSeparator();
×
1165

1166
                if (!flagShowTelrad)
×
1167
                {
1168
                        QAction* action = popup->addAction(q_("Toggle &CCD"));
×
1169
                        action->setCheckable(true);
×
1170
                        action->setChecked(flagShowCCD);
×
1171
                        connect(action, SIGNAL(toggled(bool)), actionShowSensor, SLOT(setChecked(bool)));
×
1172
                }
1173
                
1174
                if (!flagShowCCD)
×
1175
                {
1176
                        QAction* action = popup->addAction(q_("Toggle &Telrad"));
×
1177
                        action->setCheckable(true);
×
1178
                        action->setChecked(flagShowTelrad);
×
1179
                        connect(action, SIGNAL(toggled(bool)), actionShowTelrad, SLOT(setChecked(bool)));
×
1180
                }
1181
                
1182
                popup->addSeparator();
×
1183
                if (flagShowCCD && selectedCCDIndex > -1 && selectedTelescopeIndex > -1)
×
1184
                {
1185
                        popup->addAction(q_("&Previous CCD"), this, SLOT(decrementCCDIndex()));
×
1186
                        popup->addAction(q_("&Next CCD"), this, SLOT(incrementCCDIndex()));
×
1187
                        QMenu* submenu = new QMenu(q_("&Select CCD"), popup);
×
1188
                        for (int index = 0; index < ccds.count(); ++index)
×
1189
                        {
1190
                                QString label;
×
1191
                                if (index < 10)
×
1192
                                {
1193
                                        label = QString("&%1: %2").arg(index).arg(ccds[index]->name());
×
1194
                                }
1195
                                else
1196
                                {
1197
                                        label = ccds[index]->name();
×
1198
                                }
1199
                                QAction* action = submenu->addAction(label, submenu, [=](){selectCCDAtIndex(index);});
×
1200
                                if (index == selectedCCDIndex)
×
1201
                                {
1202
                                        action->setCheckable(true);
×
1203
                                        action->setChecked(true);
×
1204
                                }
1205
                        }
×
1206
                        popup->addMenu(submenu);
×
1207
                        
1208
                        submenu = new QMenu(q_("&Rotate CCD"), popup);
×
1209
                        submenu->addAction(QString("&1: -90") + QChar(0x00B0), submenu, [=](){rotateCCD(-90);});
×
1210
                        submenu->addAction(QString("&2: -45") + QChar(0x00B0), submenu, [=](){rotateCCD(-45);});
×
1211
                        submenu->addAction(QString("&3: -15") + QChar(0x00B0), submenu, [=](){rotateCCD(-15);});
×
1212
                        submenu->addAction(QString("&4: -5") + QChar(0x00B0),  submenu, [=](){rotateCCD(-5);});
×
1213
                        submenu->addAction(QString("&5: -1") + QChar(0x00B0),  submenu, [=](){rotateCCD(-1);});
×
1214
                        submenu->addAction(QString("&6: +1") + QChar(0x00B0),  submenu, [=](){rotateCCD(1);});
×
1215
                        submenu->addAction(QString("&7: +5") + QChar(0x00B0),  submenu, [=](){rotateCCD(5);});
×
1216
                        submenu->addAction(QString("&8: +15") + QChar(0x00B0), submenu, [=](){rotateCCD(15);});
×
1217
                        submenu->addAction(QString("&9: +45") + QChar(0x00B0), submenu, [=](){rotateCCD(45);});
×
1218
                        submenu->addAction(QString("&0: +90") + QChar(0x00B0), submenu, [=](){rotateCCD(90);});
×
1219

1220
                        submenu->addAction(q_("&Reset rotation"), this, SLOT(ccdRotationReset()));
×
1221
                        popup->addMenu(submenu);                        
×
1222
                        popup->addSeparator();
×
1223
                }
1224
                if (flagShowCCD && selectedCCDIndex > -1 && telescopes.count() > 1)
×
1225
                {
1226
                        QMenu* submenu = addTelescopeSubmenu(popup);
×
1227
                        popup->addMenu(submenu);
×
1228
                        submenu = addLensSubmenu(popup);
×
1229
                        popup->addMenu(submenu);
×
1230
                        popup->addSeparator();
×
1231
                }
1232
        }
1233

1234
#ifdef Q_OS_WIN
1235
        popup->showTearOffMenu(QCursor::pos());
1236
#endif
1237
        popup->exec(QCursor::pos());
×
1238
        delete popup;
×
1239
}
×
1240

1241
void Oculars::incrementCCDIndex()
×
1242
{
1243
        selectedCCDIndex++;
×
1244
        if (selectedCCDIndex == ccds.count())
×
1245
        {
1246
                selectedCCDIndex = 0;
×
1247
        }
1248
        emit selectedCCDChanged(selectedCCDIndex);
×
1249
}
×
1250

1251
void Oculars::incrementOcularIndex()
×
1252
{
1253
        selectedOcularIndex++;
×
1254
        if (selectedOcularIndex == oculars.count())
×
1255
        {
1256
                selectedOcularIndex = 0;
×
1257
        }
1258
        // validate the new selection
1259
        if (selectedOcularIndex > -1 && !oculars[selectedOcularIndex]->isBinoculars())
×
1260
        {
1261
                if ( selectedTelescopeIndex == -1 && telescopes.count() == 0)
×
1262
                {
1263
                        // reject the change
1264
                        selectedOcularIndex++;
×
1265
                }
1266

1267
                if (selectedTelescopeIndex == -1)
×
1268
                        selectTelescopeAtIndex(0);
×
1269
        }
1270
        emit selectedOcularChanged(selectedOcularIndex);
×
1271
}
×
1272

1273
void Oculars::incrementTelescopeIndex()
×
1274
{
1275
        selectedTelescopeIndex++;
×
1276
        if (selectedTelescopeIndex == telescopes.count())
×
1277
        {
1278
                selectedTelescopeIndex = 0;
×
1279
        }
1280
        emit selectedTelescopeChanged(selectedTelescopeIndex);
×
1281
}
×
1282

1283
void Oculars::incrementLensIndex()
×
1284
{
1285
        selectedLensIndex++;
×
1286
        if (selectedLensIndex == lenses.count())
×
1287
        {
1288
                selectedLensIndex = -1;
×
1289
        }
1290
        emit selectedLensChanged(selectedLensIndex);
×
1291
}
×
1292

1293
void Oculars::disableLens()
×
1294
{
1295
        selectedLensIndex = -1;
×
1296
        emit selectedLensChanged(selectedLensIndex);
×
1297
}
×
1298

1299
void Oculars::rotateCCD(int amount)
×
1300
{
1301
        CCD *ccd = ccds[selectedCCDIndex];
×
1302
        if (!ccd) return;
×
1303
        double angle = ccd->chipRotAngle();
×
1304
        angle += amount;
×
1305
        if (angle >= 360)
×
1306
        {
1307
                angle -= 360;
×
1308
        }
1309
        else if (angle <= -360)
×
1310
        {
1311
                angle += 360;
×
1312
        }
1313
        ccd->setChipRotAngle(angle);
×
1314
        emit selectedCCDRotationAngleChanged(angle);
×
1315
}
1316

1317
void Oculars::rotatePrism(int amount)
×
1318
{
1319
        CCD *ccd = ccds[selectedCCDIndex];
×
1320
        if (!ccd) return;
×
1321
        double angle = ccd->prismPosAngle();
×
1322
        angle += amount;
×
1323
        if (angle >= 360)
×
1324
        {
1325
                angle -= 360;
×
1326
        }
1327
        else if (angle <= -360)
×
1328
        {
1329
                angle += 360;
×
1330
        }
1331
        ccd->setPrismPosAngle(angle);
×
1332
        emit selectedCCDPrismPositionAngleChanged(angle);
×
1333
}
1334

1335
void Oculars::selectCCDAtIndex(int index)
×
1336
{
1337
        if (index > -1 && index < ccds.count())
×
1338
        {
1339
                selectedCCDIndex = index;
×
1340
                emit selectedCCDChanged(index);
×
1341
        }
1342
}
×
1343

1344
void Oculars::selectOcularAtIndex(int index)
×
1345
{
1346
        if (selectedTelescopeIndex == -1)
×
1347
                selectTelescopeAtIndex(0);
×
1348

1349
        if (index > -1 && index < oculars.count() && (telescopes.count() >= 0 || oculars[index]->isBinoculars()))
×
1350
        {
1351
                selectedOcularIndex = index;
×
1352
                emit selectedOcularChanged(index);
×
1353
        }
1354
}
×
1355

1356
void Oculars::selectTelescopeAtIndex(int index)
×
1357
{
1358
        if (index > -1 && index < telescopes.count())
×
1359
        {
1360
                selectedTelescopeIndex = index;
×
1361
                emit selectedTelescopeChanged(index);
×
1362
        }
1363
}
×
1364

1365
void Oculars::selectLensAtIndex(int index)
×
1366
{
1367
        if (index > -2 && index < lenses.count())
×
1368
        {
1369
                selectedLensIndex = index;
×
1370
                emit selectedLensChanged(index);
×
1371
        }
1372
}
×
1373

1374
void Oculars::toggleCCD(bool show)
×
1375
{
1376
        //If there are no sensors...
1377
        if (ccds.isEmpty() || telescopes.isEmpty())
×
1378
        {
1379
                //TODO: BM: Make this an on-screen message and/or disable the button
1380
                //if there are no sensors.
1381
                if (show)
×
1382
                {
1383
                        qWarning() << "Oculars plugin: Unable to display a sensor boundary: No sensors or telescopes are defined.";
×
1384
                        QMessageBox::warning(&StelMainView::getInstance(), q_("Warning!"), q_("Unable to display a sensor boundary: No sensors or telescopes are defined."), QMessageBox::Ok);
×
1385
                }
1386
                flagShowCCD = false;
×
1387
                selectedCCDIndex = -1;
×
1388
                show = false;
×
1389
        }
1390

1391
        StelCore *core = StelApp::getInstance().getCore();
×
1392
        StelMovementMgr *movementManager = core->getMovementMgr();
×
1393
        StelSkyDrawer *skyDrawer = core->getSkyDrawer();
×
1394
        if (show)
×
1395
        {
1396
                initialFOV = movementManager->getCurrentFov();
×
1397
                //Mutually exclusive with the ocular mode
1398
                hideUsageMessageIfDisplayed();
×
1399
                if (flagShowOculars)
×
1400
                        enableOcular(false);
×
1401

1402
                if (flagShowTelrad) {
×
1403
                        toggleTelrad(false);
×
1404
                }
1405

1406
                if (selectedTelescopeIndex < 0)
×
1407
                {
1408
                        selectedTelescopeIndex = 0;
×
1409
                }
1410
                if (selectedCCDIndex < 0)
×
1411
                {
1412
                        selectedCCDIndex = 0;
×
1413
                }
1414
                flagShowCCD = true;
×
1415
                setScreenFOVForCCD();
×
1416

1417
                // Change scales for stars. (Even restoring from ocular view has restored main program's values at this point.)
1418
                relativeStarScaleMain=skyDrawer->getRelativeStarScale();
×
1419
                absoluteStarScaleMain=skyDrawer->getAbsoluteStarScale();
×
1420
                skyDrawer->setRelativeStarScale(relativeStarScaleCCD);
×
1421
                skyDrawer->setAbsoluteStarScale(absoluteStarScaleCCD);
×
1422

1423
                if (guiPanel)
×
1424
                {
1425
                        guiPanel->showCcdGui();
×
1426
                }
1427
        }
1428
        else
1429
        {
1430
                flagShowCCD = false;
×
1431

1432
                // Restore star scales
1433
                relativeStarScaleCCD=skyDrawer->getRelativeStarScale();
×
1434
                absoluteStarScaleCCD=skyDrawer->getAbsoluteStarScale();
×
1435
                skyDrawer->setRelativeStarScale(relativeStarScaleMain);
×
1436
                skyDrawer->setAbsoluteStarScale(absoluteStarScaleMain);
×
1437
                //Zoom out
1438
                if (getFlagInitFovUsage())
×
1439
                        movementManager->zoomTo(movementManager->getInitFov());
×
1440
                else if (!flagShowTelrad)
×
1441
                        movementManager->zoomTo(initialFOV);
×
1442

1443
                if (getFlagInitDirectionUsage())
×
1444
                        movementManager->setViewDirectionJ2000(core->altAzToJ2000(movementManager->getInitViewingDirection(), StelCore::RefractionOff));
×
1445

1446
                if (getFlagAutosetMountForCCD())
×
1447
                {
1448
                        StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
×
1449
                        propMgr->setStelPropertyValue("StelMovementMgr.equatorialMount", equatorialMountEnabledMain);
×
1450
                }
1451

1452
                if (guiPanel)
×
1453
                {
1454
                        guiPanel->foldGui();
×
1455
                }
1456
        }
1457

1458
        emit enableCCDChanged(flagShowCCD);
×
1459
}
×
1460

1461
void Oculars::toggleCCD()
×
1462
{
1463
        toggleCCD(!flagShowCCD);
×
1464
}
×
1465

1466
void Oculars::toggleCrosshairs(bool show)
×
1467
{
1468
        if(show != flagShowCrosshairs)
×
1469
        {
1470
                flagShowCrosshairs = show;
×
1471
                emit enableCrosshairsChanged(show);
×
1472
        }
1473
}
×
1474

1475
void Oculars::toggleTelrad(bool show)
×
1476
{
1477
        if(show!=flagShowTelrad)
×
1478
        {
1479
                flagShowTelrad = show;
×
1480

1481
                StelMovementMgr* movementMgr = StelApp::getInstance().getCore()->getMovementMgr();
×
1482
                if (show)
×
1483
                {
1484
                        hideUsageMessageIfDisplayed();
×
1485
                        enableOcular(false);
×
1486
                        toggleCCD(false);
×
1487
                        // NOTE: Added special zoom level for Telrad
1488
                        if (flagScalingFOVForTelrad)
×
1489
                        {
1490
                                float fov = qMax(qMax(telradFOV[0], telradFOV[1]), qMax(telradFOV[2], telradFOV[3]));
×
1491
                                movementMgr->zoomTo(static_cast<double>(fov)*2.);
×
1492
                        }
1493
                }
1494
                else if (getFlagInitFovUsage()) // Restoration of FOV is needed?
×
1495
                        movementMgr->zoomTo(movementMgr->getInitFov());
×
1496

1497
                if (getFlagInitDirectionUsage())
×
1498
                        movementMgr->setViewDirectionJ2000(StelApp::getInstance().getCore()->altAzToJ2000(movementMgr->getInitViewingDirection(), StelCore::RefractionOff));
×
1499

1500
                emit enableTelradChanged(flagShowTelrad);
×
1501
        }
1502
}
×
1503

1504
void Oculars::toggleTelrad()
×
1505
{
1506
        toggleTelrad(!flagShowTelrad);
×
1507
}
×
1508

1509
void Oculars::initializeActivationActions()
×
1510
{
1511
        QString ocularsGroup = N_("Oculars");
×
1512
        actionShowOcular = addAction("actionShow_Oculars", ocularsGroup, N_("Ocular view"), "enableOcular", "Ctrl+O");
×
1513
        actionMenu = addAction("actionShow_Ocular_Menu", ocularsGroup, N_("Oculars popup menu"), "displayPopupMenu()", "Alt+O");
×
1514
        actionShowCrosshairs = addAction("actionShow_Ocular_Crosshairs", ocularsGroup, N_("Show crosshairs"), "enableCrosshairs", "Alt+C");
×
1515
        actionShowSensor = addAction("actionShow_Sensor", ocularsGroup, N_("Image sensor frame"), "enableCCD");
×
1516
        actionShowTelrad = addAction("actionShow_Telrad", ocularsGroup, N_("Telrad sight"), "enableTelrad", "Ctrl+B");
×
1517
        actionConfiguration = addAction("actionShow_Oculars_dialog", ocularsGroup, N_("Show settings dialog"), ocularDialog, "visible", ""); // Allow assign shortkey
×
1518
        addAction("actionShow_Oculars_GUI", ocularsGroup, N_("Toggle Oculars button bar"), "flagGuiPanelEnabled"); // Allow assign shortkey
×
1519
        // Select next telescope via keyboard
1520
        addAction("actionShow_Telescope_Increment", ocularsGroup, N_("Select next telescope"), "incrementTelescopeIndex()");
×
1521
        // Select previous telescope via keyboard
1522
        addAction("actionShow_Telescope_Decrement", ocularsGroup, N_("Select previous telescope"), "decrementTelescopeIndex()");
×
1523
        // Select next eyepiece via keyboard
1524
        addAction("actionShow_Ocular_Increment", ocularsGroup, N_("Select next eyepiece"), "incrementOcularIndex()");
×
1525
        // Select previous eyepiece via keyboard
1526
        addAction("actionShow_Ocular_Decrement", ocularsGroup, N_("Select previous eyepiece"), "decrementOcularIndex()");
×
1527
        // Select next lens via keyboard
1528
        addAction("actionShow_Lens_Increment", ocularsGroup, N_("Select next lens"), "incrementLensIndex()");
×
1529
        // Select previous lens via keyboard
1530
        addAction("actionShow_Lens_Decrement", ocularsGroup, N_("Select previous lens"), "decrementLensIndex()");
×
1531
        // Select next CCD via keyboard
1532
        addAction("actionShow_CCD_Increment", ocularsGroup, N_("Select next CCD frame"), "incrementCCDIndex()");
×
1533
        // Select previous CCD via keyboard
1534
        addAction("actionShow_CCD_Decrement", ocularsGroup, N_("Select previous CCD frame"), "decrementCCDIndex()");
×
1535
        addAction("actionShow_Ocular_Rotate_Reticle_Clockwise", ocularsGroup, N_("Rotate reticle pattern of the eyepiece clockwise"), "rotateReticleClockwise()", "Alt+M");
×
1536
        addAction("actionShow_Ocular_Rotate_Reticle_Counterclockwise", ocularsGroup, N_("Rotate reticle pattern of the eyepiece counterclockwise"), "rotateReticleCounterclockwise()", "Shift+Alt+M");
×
1537
        addAction("actionShow_Sensor_Crop_Overlay", ocularsGroup, N_("Toggle sensor crop overlay"), "toggleCropOverlay()");
×
1538
        addAction("actionShow_Sensor_Pixel_Grid", ocularsGroup, N_("Toggle sensor pixel grid"), "togglePixelGrid()");
×
1539
        addAction("actionShow_Sensor_Focuser_Overlay", ocularsGroup, N_("Toggle focuser overlay"), "toggleFocuserOverlay()");
×
1540

1541
        // NOTE: GUI elements in OcularsGuiPanel
1542
        addAction("actionToggle_Oculars_Rotate_Frame_Reset", ocularsGroup, N_("Reset the sensor frame rotation"), this, "ccdRotationReset()", "", "");
×
1543
        addAction("actionToggle_Oculars_Rotate_Prism_Reset", ocularsGroup, N_("Reset the prism rotation"), this, "prismPositionAngleReset()", "", "");
×
1544
        QList<int> angles = { 1, 5, 15, 90 };
×
1545
        for (int i = 0; i < angles.size(); ++i)
×
1546
        {
1547
                QString angle = QString::number(angles.at(i));
×
1548
                QString degree = (angles.at(i)==1 ? "degree" : "degrees");
×
1549

1550
                QString actionCounterclockwiseCCDName = QString("actionToggle_Oculars_Rotate_Frame_%1_Counterclockwise").arg(angle);
×
1551
                QString actionCounterclockwiseCCDDescription = QString("Rotate the sensor frame %1 %2 counterclockwise").arg(angle, degree);
×
1552
                addAction(actionCounterclockwiseCCDName, ocularsGroup, actionCounterclockwiseCCDDescription, this, [=](){rotateCCD(-1*angles.at(i));}, "");
×
1553

1554
                QString actionClockwiseCCDName = QString("actionToggle_Oculars_Rotate_Frame_%1_Clockwise").arg(angle);
×
1555
                QString actionClockwiseCCDDescription = QString("Rotate the sensor frame %1 %2 clockwise").arg(angle, degree);
×
1556
                addAction(actionClockwiseCCDName, ocularsGroup, actionClockwiseCCDDescription, this, [=](){rotateCCD(angles.at(i));}, "");
×
1557

1558
                QString actionCounterclockwisePrismName = QString("actionToggle_Oculars_Rotate_Prism_%1_Counterclockwise").arg(angle);
×
1559
                QString actionCounterclockwisePrismDescription = QString("Rotate the prism %1 %2 counterclockwise").arg(angle, degree);
×
1560
                addAction(actionCounterclockwisePrismName, ocularsGroup, actionCounterclockwisePrismDescription, this, [=](){rotatePrism(-1*angles.at(i));}, "");
×
1561

1562
                QString actionClockwisePrismName = QString("actionToggle_Oculars_Rotate_Prism_%1_Clockwise").arg(angle);
×
1563
                QString actionClockwisePrismDescription = QString("Rotate the prism %1 %2 clockwise").arg(angle, degree);
×
1564
                addAction(actionClockwisePrismName, ocularsGroup, actionClockwisePrismDescription, this, [=](){rotatePrism(angles.at(i));}, "");
×
1565
        }
×
1566

1567
        connect(this, SIGNAL(selectedCCDChanged(int)),       this, SLOT(instrumentChanged()));        
×
1568
        connect(this, SIGNAL(selectedOcularChanged(int)),    this, SLOT(instrumentChanged()));
×
1569
        connect(this, SIGNAL(selectedTelescopeChanged(int)), this, SLOT(instrumentChanged()));        
×
1570
        connect(this, SIGNAL(selectedLensChanged(int)),      this, SLOT(instrumentChanged()));
×
1571
}
×
1572

1573
bool Oculars::isBinocularDefined()
×
1574
{
1575
        bool binocularFound = false;
×
1576
        for (auto* ocular : oculars)
×
1577
        {
1578
                if (ocular->isBinoculars())
×
1579
                {
1580
                        binocularFound = true;
×
1581
                        break;
×
1582
                }
1583
        }
1584
        return binocularFound;
×
1585
}
1586

1587
QRect Oculars::drawSensorFrameAndOverlay(const StelProjectorP& projector, const Mat4f& derotate,
×
1588
                                         const Vec2f& frameUpDir, const Vec2f& frameRightDir,
1589
                                         const Vec2f& frameCenter, const CCD& ccd, const Lens* lens,
1590
                                         const QSize& overlaySize)
1591
{
1592
        StelPainter sPainter(projector);
×
1593
        sPainter.setLineSmooth(true);
×
1594
        sPainter.setColor(lineColor);
×
1595
        Telescope *telescope = telescopes[selectedTelescopeIndex];
×
1596

1597
        const double fovX = ccd.getActualFOVx(telescope, lens) * (M_PI/180);
×
1598
        const double fovY = ccd.getActualFOVy(telescope, lens) * (M_PI/180);
×
1599

1600
        const float tanFovX = std::tan(fovX/2);
×
1601
        const float tanFovY = std::tan(fovY/2);
×
1602

1603
        const float cropFactorX = float(overlaySize.width())  / ccd.resolutionX();
×
1604
        const float cropFactorY = float(overlaySize.height()) / ccd.resolutionY();
×
1605

1606
        std::vector<std::pair<float,float>> cropFactors{{1.f,1.f}};
×
1607
        if (flagShowCcdCropOverlay)
×
1608
                cropFactors.emplace_back(cropFactorX, cropFactorY);
×
1609

1610
        const int numPointsPerLine = 30;
×
1611

1612
        int minX = INT_MAX, maxX = INT_MIN, minY = INT_MAX, maxY = INT_MIN;
×
1613
        sPainter.enableClientStates(true);
×
1614
        for(const auto& [cropFactorX, cropFactorY] : cropFactors)
×
1615
        {
1616
                const float cropTanFovX = cropFactorX * tanFovX;
×
1617
                const float cropTanFovY = cropFactorY * tanFovY;
×
1618
                std::vector<Vec2f> lineLoopPoints;
×
1619
                lineLoopPoints.reserve(numPointsPerLine * 4);
×
1620
                // Left line
1621
                for(int n = 0; n < numPointsPerLine; ++n)
×
1622
                {
1623
                        const auto x = 1;
×
1624
                        const auto y = cropTanFovX;
×
1625
                        const auto z = cropTanFovY * (2.f / (numPointsPerLine - 1) * n - 1);
×
1626
                        Vec3f win;
×
1627
                        projector->project(derotate * Vec3f(x,y,z), win);
×
1628
                        lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1629
                }
1630
                // Top line
1631
                for(int n = 1; n < numPointsPerLine; ++n)
×
1632
                {
1633
                        const auto x = 1;
×
1634
                        const auto y = -cropTanFovX * (2.f / (numPointsPerLine - 1) * n - 1);
×
1635
                        const auto z = cropTanFovY;
×
1636
                        Vec3f win;
×
1637
                        projector->project(derotate * Vec3f(x,y,z), win);
×
1638
                        lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1639
                }
1640
                // Right line
1641
                for(int n = 1; n < numPointsPerLine; ++n)
×
1642
                {
1643
                        const auto x = 1;
×
1644
                        const auto y = -cropTanFovX;
×
1645
                        const auto z = cropTanFovY * (1 - 2.f / (numPointsPerLine - 1) * n);
×
1646
                        Vec3f win;
×
1647
                        projector->project(derotate * Vec3f(x,y,z), win);
×
1648
                        lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1649
                }
1650
                // Bottom line
1651
                for(int n = 1; n < numPointsPerLine-1; ++n)
×
1652
                {
1653
                        const auto x = 1;
×
1654
                        const auto y = -cropTanFovX * (1 - 2.f / (numPointsPerLine - 1) * n);
×
1655
                        const auto z = -cropTanFovY;
×
1656
                        Vec3f win;
×
1657
                        projector->project(derotate * Vec3f(x,y,z), win);
×
1658
                        lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1659
                }
1660
                for(const auto& p : lineLoopPoints)
×
1661
                {
1662
                        const float x = (p-frameCenter).dot(frameRightDir);
×
1663
                        const float y = (p-frameCenter).dot(frameUpDir);
×
1664
                        if(x > maxX) maxX = x;
×
1665
                        if(x < minX) minX = x;
×
1666
                        if(y > maxY) maxY = y;
×
1667
                        if(y < minY) minY = y;
×
1668
                }
1669
                sPainter.setVertexPointer(2, GL_FLOAT, lineLoopPoints.data());
×
1670
                sPainter.drawFromArray(StelPainter::LineLoop, lineLoopPoints.size(), 0, false);
×
1671
        }
×
1672

1673
        const QRect boundingRect(QPoint(minX, minY), QSize(maxX-minX, maxY-minY));
×
1674

1675
        if (!(flagShowCcdCropOverlay && flagShowCcdCropOverlayPixelGrid))
×
1676
                return boundingRect;
×
1677

1678
        std::vector<Vec2f> lineStripPoints;
×
1679
        const float cropTanFovX = cropFactorX * tanFovX;
×
1680
        const float cropTanFovY = cropFactorY * tanFovY;
×
1681
        lineStripPoints.reserve(numPointsPerLine);
×
1682
        const int numOverlayPixelsX = overlaySize.width()  / ccd.binningX();
×
1683
        const int numOverlayPixelsY = overlaySize.height() / ccd.binningY();
×
1684

1685
        // Vertical lines of the pixel grid
1686
        for(float line = 1; line < numOverlayPixelsX; ++line)
×
1687
        {
1688
                for(float p = 0; p < numPointsPerLine; ++p)
×
1689
                {
1690
                        const auto x = 1;
×
1691
                        const auto y = cropTanFovX * (1 - 2 * line / numOverlayPixelsX);
×
1692
                        const auto z = cropTanFovY * (2.f / (numPointsPerLine - 1) * p - 1);
×
1693
                        Vec3f win;
×
1694
                        projector->project(derotate * Vec3f(x,y,z), win);
×
1695
                        lineStripPoints.push_back(Vec2f(win[0], win[1]));
×
1696
                }
1697
                sPainter.setVertexPointer(2, GL_FLOAT, lineStripPoints.data());
×
1698
                sPainter.drawFromArray(StelPainter::LineStrip, lineStripPoints.size(), 0, false);
×
1699
                lineStripPoints.clear();
×
1700
        }
1701

1702
        // Horizontal lines of the pixel grid
1703
        for(float line = 1; line < numOverlayPixelsY; ++line)
×
1704
        {
1705
                for(float p = 0; p < numPointsPerLine; ++p)
×
1706
                {
1707
                        const auto x = 1;
×
1708
                        const auto y = -cropTanFovX * (2.f / (numPointsPerLine - 1) * p - 1);
×
1709
                        const auto z = cropTanFovY * (1 - 2 * line / numOverlayPixelsX);
×
1710
                        Vec3f win;
×
1711
                        projector->project(derotate * Vec3f(x,y,z), win);
×
1712
                        lineStripPoints.push_back(Vec2f(win[0], win[1]));
×
1713
                }
1714
                sPainter.setVertexPointer(2, GL_FLOAT, lineStripPoints.data());
×
1715
                sPainter.drawFromArray(StelPainter::LineStrip, lineStripPoints.size(), 0, false);
×
1716
                lineStripPoints.clear();
×
1717
        }
1718

1719
        return boundingRect;
×
1720
}
×
1721

1722
void Oculars::drawCirclesOfConstantAngularRadii(StelPainter& sPainter, const Mat4f& derotate, const std::vector<float>& angularRadii)
×
1723
{
1724
        sPainter.enableClientStates(true);
×
1725

1726
        constexpr int numPointsPerCircle = 150;
×
1727
        const float*const cossin = StelUtils::ComputeCosSinTheta(numPointsPerCircle);
×
1728
        std::vector<Vec2f> lineLoopPoints;
×
1729
        lineLoopPoints.reserve(numPointsPerCircle);
×
1730
        for(const auto radius : angularRadii)
×
1731
        {
1732
                const auto tanAngRadius = std::tan(radius);
×
1733
                for(int n = 0; n < numPointsPerCircle; ++n)
×
1734
                {
1735
                        const float cosb = cossin[2*n], sinb = cossin[2*n+1];
×
1736
                        const float x = 1;
×
1737
                        const float y = tanAngRadius*sinb;
×
1738
                        const float z = tanAngRadius*cosb;
×
1739
                        Vec3f win;
×
1740
                        sPainter.getProjector()->project(derotate * Vec3f(x,y,z), win);
×
1741
                        lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1742
                }
1743
                sPainter.setVertexPointer(2, GL_FLOAT, lineLoopPoints.data());
×
1744
                sPainter.drawFromArray(StelPainter::LineLoop, lineLoopPoints.size(), 0, false);
×
1745
                lineLoopPoints.clear();
×
1746
        }
1747

1748
        sPainter.enableClientStates(false);
×
1749
}
×
1750

1751
void Oculars::drawOAG(const StelProjectorP& projector, const Mat4f& derotate,
×
1752
                      const CCD& ccd, const Lens* lens)
1753
{
1754
        StelPainter sPainter(projector);
×
1755
        sPainter.setLineSmooth(true);
×
1756
        sPainter.setColor(lineColor);
×
1757

1758
        Telescope *telescope = telescopes[selectedTelescopeIndex];
×
1759
        const float innerRadius = ccd.getInnerOAGRadius(telescope, lens) * (M_PI/180);
×
1760
        const float outerRadius = ccd.getOuterOAGRadius(telescope, lens) * (M_PI/180);
×
1761

1762
        drawCirclesOfConstantAngularRadii(sPainter, derotate, {innerRadius,outerRadius});
×
1763

1764
        const int numPointsPerLine = 30;
×
1765

1766
        const float prismFovX = ccd.getOAGActualFOVx(telescope, lens) * (M_PI/180);
×
1767
        const float tanFovX = std::tan(prismFovX/2);
×
1768

1769
        const auto tanInnerRadius = std::tan(innerRadius);
×
1770
        const auto tanOuterRadius = std::tan(outerRadius);
×
1771
        std::vector<Vec2f> lineLoopPoints;
×
1772
        lineLoopPoints.reserve(numPointsPerLine * 4);
×
1773
        // Left line
1774
        for(int n = 0; n < numPointsPerLine; ++n)
×
1775
        {
1776
                const auto x = 1;
×
1777
                const auto y = tanFovX;
×
1778
                const auto z = (tanOuterRadius-tanInnerRadius) * n / (numPointsPerLine-1) + tanInnerRadius;
×
1779
                Vec3f win;
×
1780
                projector->project(derotate * Vec3f(x,y,z), win);
×
1781
                lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1782
        }
1783
        // Top line
1784
        for(int n = 1; n < numPointsPerLine; ++n)
×
1785
        {
1786
                const auto x = 1;
×
1787
                const auto y = -tanFovX * (2.f / (numPointsPerLine - 1) * n - 1);
×
1788
                const auto z = tanOuterRadius;
×
1789
                Vec3f win;
×
1790
                projector->project(derotate * Vec3f(x,y,z), win);
×
1791
                lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1792
        }
1793
        // Right line
1794
        for(int n = 1; n < numPointsPerLine; ++n)
×
1795
        {
1796
                const auto x = 1;
×
1797
                const auto y = -tanFovX;
×
1798
                const auto z = (tanInnerRadius-tanOuterRadius) * n / (numPointsPerLine-1) + tanOuterRadius;
×
1799
                Vec3f win;
×
1800
                projector->project(derotate * Vec3f(x,y,z), win);
×
1801
                lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1802
        }
1803
        // Bottom line
1804
        for(int n = 1; n < numPointsPerLine-1; ++n)
×
1805
        {
1806
                const auto x = 1;
×
1807
                const auto y = -tanFovX * (1 - 2.f / (numPointsPerLine - 1) * n);
×
1808
                const auto z = tanInnerRadius;
×
1809
                Vec3f win;
×
1810
                projector->project(derotate * Vec3f(x,y,z), win);
×
1811
                lineLoopPoints.push_back(Vec2f(win[0], win[1]));
×
1812
        }
1813
        sPainter.enableClientStates(true);
×
1814
        sPainter.setVertexPointer(2, GL_FLOAT, lineLoopPoints.data());
×
1815
        sPainter.drawFromArray(StelPainter::LineLoop, lineLoopPoints.size(), 0, false);
×
1816
}
×
1817

1818
void Oculars::paintCCDBounds()
×
1819
{
1820
        int fontSize = StelApp::getInstance().getScreenFontSize();
×
1821
        StelCore *core = StelApp::getInstance().getCore();
×
1822
        StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
×
1823
        Lens *lens = selectedLensIndex >=0  ? lenses[selectedLensIndex] : Q_NULLPTR;
×
1824

1825
        const auto equatProj = core->getProjection(StelCore::FrameEquinoxEqu, StelCore::RefractionMode::RefractionOff);
×
1826
        const auto altAzProj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionMode::RefractionOff);
×
1827
        if (selectedCCDIndex < 0 || selectedTelescopeIndex < 0)
×
1828
                return;
×
1829

1830
        CCD *ccd = ccds[selectedCCDIndex];
×
1831
        if (!ccd) return;
×
1832

1833
        Telescope *telescope = telescopes[selectedTelescopeIndex];
×
1834
        const auto projector = telescope->isEquatorial() ? equatProj : altAzProj;
×
1835

1836
        double screenFOV = static_cast<double>(params.fov);
×
1837
        Vec2i centerScreen(projector->getViewportPosX() + projector->getViewportWidth() / 2,
×
1838
                           projector->getViewportPosY() + projector->getViewportHeight() / 2);
×
1839

1840
        const double ccdXRatio = ccd->getActualFOVx(telescope, lens) / screenFOV;
×
1841
        const double ccdYRatio = ccd->getActualFOVy(telescope, lens) / screenFOV;
×
1842

1843
        const double fovX = ccd->getActualFOVx(telescope, lens);
×
1844
        const double fovY = ccd->getActualFOVy(telescope, lens);
×
1845

1846
        // As the FOV is based on the narrow aspect of the screen, we need to calculate
1847
        // height & width based solely off of that dimension.
1848
        int aspectIndex = 2;
×
1849
        if (params.viewportXywh[2] > params.viewportXywh[3])
×
1850
        {
1851
                aspectIndex = 3;
×
1852
        }
1853
        const float width = params.viewportXywh[aspectIndex] * static_cast<float>(ccdXRatio * params.devicePixelsPerPixel);
×
1854
        const float height = params.viewportXywh[aspectIndex] * static_cast<float>(ccdYRatio * params.devicePixelsPerPixel);
×
1855

1856
        // Get Crop size taking into account the binning rounded to the lower limit and limiting it to sensor size
1857
        const float actualCropOverlayX = (std::min(ccd->resolutionX(), ccdCropOverlayHSize) / ccd->binningX()) * ccd->binningX();
×
1858
        const float actualCropOverlayY = (std::min(ccd->resolutionY(), ccdCropOverlayVSize)  / ccd->binningY()) * ccd->binningY();
×
1859

1860
        // Calculate the size of the CCD crop overlay
1861
        const float overlayWidth = width * actualCropOverlayX / ccd->resolutionX();
×
1862
        const float overlayHeight = height * actualCropOverlayY / ccd->resolutionY();
×
1863

1864
        Vec3d centerPos3d;
×
1865
        projector->unProject(centerScreen[0], centerScreen[1], centerPos3d);
×
1866
        double azimuth, elevation;
1867
        StelUtils::rectToSphe(&azimuth, &elevation, centerPos3d);
×
1868
        const auto derotate = Mat4f::rotation(Vec3f(0,0,1), azimuth) *
×
1869
                              Mat4f::rotation(Vec3f(0,1,0), -elevation) *
×
1870
                              Mat4f::rotation(Vec3f(1,0,0), ccd->chipRotAngle() * (M_PI/180));
×
1871

1872
        if (getFlagAutosetMountForCCD())
×
1873
        {
1874
                StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
×
1875
                propMgr->setStelPropertyValue("actionSwitch_Equatorial_Mount", telescope->isEquatorial());
×
1876
        }
1877

1878
        const QSize overlaySize(actualCropOverlayX, actualCropOverlayY);
×
1879

1880
        // Compute vectors corresponding to up and right direction of the frame, they will be used to find its bounding rect
1881
        Vec3f frameUpWin, frameCenterWin, frameRightWin;
×
1882
        projector->project(derotate * Vec3f(1,0,1), frameUpWin);
×
1883
        projector->project(derotate * Vec3f(1,0,0), frameCenterWin);
×
1884
        projector->project(derotate * Vec3f(1,-1,0), frameRightWin);
×
1885
        const auto frameUpWinDir = normalize(Vec2f(frameUpWin[0] - frameCenterWin[0],
×
1886
                                                   frameUpWin[1] - frameCenterWin[1]));
×
1887
        const auto frameRightWinDir = normalize(Vec2f(frameRightWin[0] - frameCenterWin[0],
×
1888
                                                      frameRightWin[1] - frameCenterWin[1]));
×
1889
        const auto frameCenterWin2d = Vec2f(frameCenterWin[0], frameCenterWin[1]);
×
1890

1891
        const auto boundingRect = drawSensorFrameAndOverlay(projector, derotate, frameUpWinDir, frameRightWinDir,
×
1892
                                                            frameCenterWin2d, *ccd, lens, overlaySize);
1893
        StelPainter painter(projector);
×
1894
        painter.setLineSmooth(true);
×
1895
        painter.setColor(lineColor);
×
1896
        painter.setFont(font);
×
1897

1898
        if(ccd->hasOAG())
×
1899
        {
1900
                const auto derotateOAG = Mat4f::rotation(Vec3f(0,0,1), azimuth) *
×
1901
                                         Mat4f::rotation(Vec3f(0,1,0), -elevation) *
×
1902
                                         Mat4f::rotation(Vec3f(1,0,0), (ccd->prismPosAngle() + ccd->chipRotAngle()) * (M_PI/180));
×
1903
                drawOAG(projector, derotateOAG, *ccd, lens);
×
1904
        }
1905

1906
        // Tool for planning a mosaic astrophotography: shows a small cross at center of CCD's
1907
        // frame and equatorial coordinates for epoch J2000.0 of that center.
1908
        // Details: https://bugs.launchpad.net/stellarium/+bug/1404695
1909

1910
        const double ratioLimit = 0.375;
×
1911
        const double ratioLimitCrop = 0.75;
×
1912
        if (ccdXRatio>=ratioLimit || ccdYRatio>=ratioLimit)
×
1913
        {
1914
                const double textRotationAngle = 180/M_PI * std::atan2(frameRightWinDir[1], frameRightWinDir[0]);
×
1915
                QTransform transform = QTransform().translate(centerScreen[0], centerScreen[1]).rotate(textRotationAngle);
×
1916
                QPoint a, b;
×
1917
                // draw cross at center
1918
                const int cross = qRound(10 * params.devicePixelsPerPixel); // use permanent size of cross (10px)
×
1919
                a = transform.map(QPoint(-cross, -cross));
×
1920
                b = transform.map(QPoint(cross, cross));
×
1921
                painter.drawLine2d(a.x(), a.y(), b.x(), b.y());
×
1922
                a = transform.map(QPoint(-cross, cross));
×
1923
                b = transform.map(QPoint(cross, -cross));
×
1924
                painter.drawLine2d(a.x(), a.y(), b.x(), b.y());
×
1925
                // calculate coordinates of the center and show it
1926
                Vec3d centerPosition;
×
1927
                equatProj->unProject(centerScreen[0], centerScreen[1], centerPosition);
×
1928
                double cx, cy;
1929
                QString cxt, cyt, coords;
×
1930
                bool withDecimalDegree = StelApp::getInstance().getFlagShowDecimalDegrees();
×
1931
                if (getFlagHorizontalCoordinates())
×
1932
                {
1933
                        bool useSouthAzimuth = StelApp::getInstance().getFlagSouthAzimuthUsage();
×
1934
                        coords = QString("%1:").arg(qc_("Az/Alt of cross", "abbreviated in the plugin"));
×
1935
                        StelUtils::rectToSphe(&cy,&cx,core->equinoxEquToAltAz(centerPosition, StelCore::RefractionAuto));
×
1936
                        const double direction = (useSouthAzimuth ? 2. : 3.); // N is zero, E is 90 degrees
×
1937
                        cy = direction*M_PI - cy;
×
1938
                        if (cy > M_PI*2)
×
1939
                                cy -= M_PI*2;
×
1940

1941
                        if (withDecimalDegree)
×
1942
                        {
1943
                                cxt = StelUtils::radToDecDegStr(cy);
×
1944
                                cyt = StelUtils::radToDecDegStr(cx);
×
1945
                        }
1946
                        else
1947
                        {
1948
                                cxt = StelUtils::radToDmsStr(cy);
×
1949
                                cyt = StelUtils::radToDmsStr(cx);
×
1950
                        }
1951
                }
1952
                else
1953
                {
1954
                        coords = QString("%1:").arg(qc_("RA/Dec (J2000.0) of cross", "abbreviated in the plugin"));
×
1955
                        StelUtils::rectToSphe(&cx,&cy,core->equinoxEquToJ2000(centerPosition, StelCore::RefractionOff)); // Calculate RA/DE (J2000.0) and show it...
×
1956
                        if (withDecimalDegree)
×
1957
                        {
1958
                                cxt = StelUtils::radToDecDegStr(cx, 5, false, true);
×
1959
                                cyt = StelUtils::radToDecDegStr(cy);
×
1960
                        }
1961
                        else
1962
                        {
1963
                                cxt = StelUtils::radToHmsStr(cx, true);
×
1964
                                cyt = StelUtils::radToDmsStr(cy, true);
×
1965
                        }
1966
                }
1967

1968
                const auto fm = painter.getFontMetrics();
×
1969
                float scaleFactor = static_cast<float>(1.2 * params.devicePixelsPerPixel);
×
1970

1971
                const auto topY = boundingRect.bottom();
×
1972
                const auto leftX = boundingRect.left();
×
1973
                const auto bottomY = boundingRect.top();
×
1974
                const auto rightX = boundingRect.right();
×
1975

1976
                // FIXME: this is a workaround for a strange behavior of QFontMetrics.
1977
                // Without this rounding we get wrong results for fractional scaling
1978
                // factors: the labels on the right are shifted too far from the right
1979
                // border, and the interval between the lines is too large.
1980
                const auto fmPixelRatio = std::floor(params.devicePixelsPerPixel);
×
1981

1982
                // Coordinates of center of visible field of view for CCD (red rectangle); above top-left corner
1983
                const auto coordsHeight = fm.boundingRect(coords).height() * fmPixelRatio;
×
1984
                a = transform.map(QPoint(leftX, topY + std::lround(1.5*coordsHeight)));
×
1985
                painter.drawText(a.x(), a.y(), coords, textRotationAngle);
×
1986
                coords = QString("%1/%2").arg(cxt.simplified(), cyt);
×
1987
                a = transform.map(QPoint(leftX, topY + std::lround(0.5*coordsHeight)));
×
1988
                painter.drawText(a.x(), a.y(), coords, textRotationAngle);
×
1989

1990
                // Dimensions of visible field of view for CCD (red rectangle); below bottom-left corner
1991
                const auto dims = getDimensionsString(fovX, fovY);
×
1992
                const auto dimsHeight = fm.boundingRect(dims).height() * fmPixelRatio;
×
1993
                a = transform.map(QPoint(leftX, bottomY - std::lround(dimsHeight)));
×
1994
                painter.drawText(a.x(), a.y(), dims, textRotationAngle);
×
1995

1996
                // Horizontal and vertical scales of visible field of view for CCD (red rectangle); below bottom-right corner
1997
                //TRANSLATORS: Unit of measure for scale - arc-seconds per pixel
1998
                QString unit = q_("\"/px");
×
1999
                QString scales = QString("%1%3 %4 %2%3").arg(QString::number(3600*ccd->getCentralAngularResolutionX(telescope, lens), 'f', 4),
×
2000
                                                             QString::number(3600*ccd->getCentralAngularResolutionY(telescope, lens), 'f', 4),
×
2001
                                                             unit, QChar(0x00D7));
×
2002
                const auto scalesBR = fm.boundingRect(scales);
×
2003
                a = transform.map(QPoint(rightX - std::lround(scalesBR.width() * fmPixelRatio),
×
2004
                                                                 bottomY - std::lround(scalesBR.height() * fmPixelRatio)));
×
2005
                painter.drawText(a.x(), a.y(), scales, textRotationAngle);
×
2006

2007
                // Rotation angle of visible field of view for CCD (red rectangle); above top-right corner
2008
                QString angle = QString("%1%2").arg(QString::number(ccd->chipRotAngle(), 'f', 1)).arg(QChar(0x00B0));
×
2009
                const auto angleBR = fm.boundingRect(angle);
×
2010
                a = transform.map(QPoint(rightX - std::lround(angleBR.width() * fmPixelRatio),
×
2011
                                                                 topY + std::lround(0.5*angleBR.height() * fmPixelRatio)));
×
2012
                painter.drawText(a.x(), a.y(), angle, textRotationAngle);
×
2013

2014
                if(flagShowCcdCropOverlay && (ccdXRatio>=ratioLimitCrop || ccdYRatio>=ratioLimitCrop))
×
2015
                {
2016
                        // show the CCD crop overlay text
2017
                        QString resolutionOverlayText = QString("%1%3 %4 %2%3").arg(QString::number(actualCropOverlayX, 'd', 0), QString::number(actualCropOverlayY, 'd', 0), qc_("px", "pixels"), QChar(0x00D7));
×
2018
                        if(actualCropOverlayX!=ccdCropOverlayHSize || actualCropOverlayY!=ccdCropOverlayVSize)
×
2019
                                resolutionOverlayText.append(" [*]");
×
2020
                        a = transform.map(QPoint(qRound(overlayWidth*0.5f - painter.getFontMetrics().boundingRect(resolutionOverlayText).width()), qRound(-overlayHeight*0.5f - fontSize*scaleFactor)));
×
2021
                        painter.drawText(a.x(), a.y(), resolutionOverlayText, textRotationAngle);
×
2022
                }
×
2023

2024
                if (getFlagMaxExposureTimeForCCD() && selectedSSO!=Q_NULLPTR)
×
2025
                {
2026
                        double properMotion = StelUtils::fmodpos(selectedSSO->getHourlyProperMotion(core)[0], 2.0*M_PI) * M_180_PI;
×
2027
                        if (properMotion>0.)
×
2028
                        {
2029
                                const double sqf = qMin(3600*ccd->getCentralAngularResolutionX(telescope, lens),
×
2030
                                                                                3600*ccd->getCentralAngularResolutionY(telescope, lens));
×
2031
                                double exposure = 3600.*sqf/qRound(3600.*properMotion);
×
2032
                                if (exposure>0.)
×
2033
                                {
2034
                                        // TRANSLATORS: "Max exposure" is short version of phrase "Max time of exposure"
2035
                                        QString exposureTime = QString("%1: %2 %3").arg(q_("Max exposure"), QString::number(qRound(exposure*10.)/10., 'd', 1), qc_("s", "time"));
×
2036
                                        const auto expoBR = fm.boundingRect(exposureTime);
×
2037
                                        a = transform.map(QPoint(rightX - std::lround(expoBR.width() * fmPixelRatio),
×
2038
                                                                                         topY + std::lround(1.5*expoBR.height() * fmPixelRatio)));
×
2039
                                        painter.drawText(a.x(), a.y(), exposureTime, textRotationAngle);
×
2040
                                }
×
2041
                        }
2042
                }
2043
        }
×
2044

2045
        if (getFlagShowFocuserOverlay())
×
2046
        {
2047
                painter.setProjector(projector);
×
2048
                painter.setColor(focuserColor);
×
2049

2050
                std::vector<float> radii;
×
2051
                if (getFlagUseSmallFocuserOverlay())
×
2052
                        radii.push_back(0.5*M_PI/180*ccd->getFocuserFOV(telescope, lens, 1.25));
×
2053
                if (getFlagUseMediumFocuserOverlay())
×
2054
                        radii.push_back(0.5*M_PI/180*ccd->getFocuserFOV(telescope, lens, 2.));
×
2055
                if (getFlagUseLargeFocuserOverlay())
×
2056
                        radii.push_back(0.5*M_PI/180*ccd->getFocuserFOV(telescope, lens, 3.3));
×
2057

2058
                if (!radii.empty())
×
2059
                        drawCirclesOfConstantAngularRadii(painter, derotate, radii);
×
2060
        }
×
2061
}
×
2062

2063
void Oculars::paintCrosshairs()
×
2064
{
2065
        StelCore *core = StelApp::getInstance().getCore();
×
2066
        const StelProjectorP projector = core->getProjection(StelCore::FrameEquinoxEqu);
×
2067
        StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
×
2068
        // Center of screen
2069
        Vec2i centerScreen(projector->getViewportPosX()+projector->getViewportWidth()/2,
×
2070
                           projector->getViewportPosY()+projector->getViewportHeight()/2);
×
2071
        float length = 0.5f * static_cast<float>(params.viewportFovDiameter);
×
2072
        // See if we need to scale the length
2073
        if (flagScaleImageCircle && oculars[selectedOcularIndex]->apparentFOV() > 0.0 && !oculars[selectedOcularIndex]->isBinoculars())
×
2074
        {
2075
                length *= static_cast<float>(oculars[selectedOcularIndex]->apparentFOV() / maxEyepieceAngle);
×
2076
        }
2077
        length *= static_cast<float>(params.devicePixelsPerPixel);
×
2078
        double polarAngle = 0.;
×
2079
        if (getFlagAlignCrosshair())
×
2080
        {
2081
                Vec3d CPos;
×
2082
                Vector2<qreal> cpos = projector->getViewportCenter();
×
2083
                projector->unProject(cpos[0], cpos[1], CPos);
×
2084
                Vec3d CPrel(CPos);
×
2085
                CPrel[2]*=0.2;
×
2086
                Vec3d crel;
×
2087
                projector->project(CPrel, crel);
×
2088
                polarAngle = atan2(cpos[1] - crel[1], cpos[0] - crel[0]) * (-180.0)/M_PI; // convert to degrees
×
2089
                if (CPos[2] > 0) polarAngle += 90.0;
×
2090
                else polarAngle -= 90.0;
×
2091
        }
2092
        // Draw the lines
2093
        StelPainter painter(projector);
×
2094
        painter.setColor(lineColor);
×
2095
        QPoint a, b;
×
2096
        int hw = qRound(length);
×
2097
        QTransform ch_transform = QTransform().translate(centerScreen[0], centerScreen[1]).rotate(-polarAngle);
×
2098
        a = ch_transform.map(QPoint(0, -hw));
×
2099
        b = ch_transform.map(QPoint(0, hw));
×
2100
        painter.drawLine2d(a.x(), a.y(), b.x(), b.y());
×
2101
        a = ch_transform.map(QPoint(-hw, 0));
×
2102
        b = ch_transform.map(QPoint(hw, 0));
×
2103
        painter.drawLine2d(a.x(), a.y(), b.x(), b.y());
×
2104
}
×
2105

2106
void Oculars::paintTelrad()
×
2107
{
2108
        if (!flagShowOculars)
×
2109
        {
2110
                StelCore *core = StelApp::getInstance().getCore();
×
2111
                const StelProjectorP projector = core->getProjection(StelCore::FrameEquinoxEqu);                
×
2112
                // StelPainter drawing
2113
                StelPainter painter(projector);                
×
2114
                painter.setColor(lineColor);
×
2115
                Vec2i centerScreen(projector->getViewportPosX()+projector->getViewportWidth()/2,
×
2116
                                   projector->getViewportPosY()+projector->getViewportHeight()/2);
×
2117
                const float pixelsPerRad = projector->getPixelPerRadAtCenter(); // * params.devicePixelsPerPixel;
×
2118
                if (telradFOV[0]>0.f) painter.drawCircle(centerScreen[0], centerScreen[1], 0.5f * pixelsPerRad * static_cast<float>(M_PI/180) * (telradFOV[0]));
×
2119
                if (telradFOV[1]>0.f) painter.drawCircle(centerScreen[0], centerScreen[1], 0.5f * pixelsPerRad * static_cast<float>(M_PI/180) * (telradFOV[1]));
×
2120
                if (telradFOV[2]>0.f) painter.drawCircle(centerScreen[0], centerScreen[1], 0.5f * pixelsPerRad * static_cast<float>(M_PI/180) * (telradFOV[2]));
×
2121
                if (telradFOV[3]>0.f) painter.drawCircle(centerScreen[0], centerScreen[1], 0.5f * pixelsPerRad * static_cast<float>(M_PI/180) * (telradFOV[3]));
×
2122
        }
×
2123
}
×
2124

2125
void Oculars::paintOcularMask(const StelCore *core)
×
2126
{
2127
        if (oculars[selectedOcularIndex]->hasPermanentCrosshair())
×
2128
                paintCrosshairs();
×
2129

2130
        const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz);
×
2131
        StelPainter painter(prj);
×
2132
        StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
×
2133

2134
        double inner = 0.5 * params.viewportFovDiameter * params.devicePixelsPerPixel;
×
2135
        // See if we need to scale the mask
2136
        if (flagScaleImageCircle && oculars[selectedOcularIndex]->apparentFOV() > 0.0 && !oculars[selectedOcularIndex]->isBinoculars())
×
2137
        {
2138
                inner = oculars[selectedOcularIndex]->apparentFOV() * inner / maxEyepieceAngle;
×
2139
        }
2140
        Vec2i centerScreen(prj->getViewportPosX()+prj->getViewportWidth()/2, prj->getViewportPosY()+prj->getViewportHeight()/2);
×
2141

2142
        painter.setBlending(true);
×
2143
        // Paint the reticale, if needed
2144
        if (!reticleTexture.isNull())
×
2145
        {
2146
                painter.setColor(lineColor);
×
2147
                reticleTexture->bind();
×
2148
                /* Why it need?
2149
                int textureHeight;
2150
                int textureWidth;
2151
                reticleTexture->getDimensions(textureWidth, textureHeight);
2152
                */
2153
                painter.drawSprite2dMode(centerScreen[0], centerScreen[1], static_cast<float>(inner / params.devicePixelsPerPixel), static_cast<float>(reticleRotation));
×
2154
        }
2155

2156
        const float alpha = getFlagUseSemiTransparency() ? getTransparencyMask()*0.01f : 1.f;
×
2157
        painter.setColor(0.f,0.f,0.f,alpha);
×
2158

2159
        GLfloat outerRadius = static_cast<GLfloat>(params.viewportXywh[2] * params.devicePixelsPerPixel + params.viewportXywh[3] * params.devicePixelsPerPixel);
×
2160
        GLint slices = 239;
×
2161

2162
        GLfloat sinCache[240];
2163
        GLfloat cosCache[240];
2164
        GLfloat vertices[(240+1)*2][3];
2165
        GLfloat deltaRadius;
2166
        GLfloat radiusHigh;
2167

2168
        /* Compute length (needed for normal calculations) */
2169
        deltaRadius=outerRadius-static_cast<GLfloat>(inner);
×
2170

2171
        /* Cache is the vertex locations cache */
2172
        for (int i=0; i<=slices; i++)
×
2173
        {
2174
                GLfloat angle=static_cast<GLfloat>(M_PI*2.0)*i/slices;
×
2175
                sinCache[i]=static_cast<GLfloat>(sinf(angle));
×
2176
                cosCache[i]=static_cast<GLfloat>(cosf(angle));
×
2177
        }
2178

2179
        sinCache[slices]=sinCache[0];
×
2180
        cosCache[slices]=cosCache[0];
×
2181

2182
        /* Enable arrays */
2183
        painter.enableClientStates(true);
×
2184
        painter.setVertexPointer(3, GL_FLOAT, vertices);
×
2185

2186
        radiusHigh=outerRadius-deltaRadius;
×
2187
        for (int i=0; i<=slices; i++)
×
2188
        {
2189
                vertices[i*2][0]= centerScreen[0] + outerRadius*sinCache[i];
×
2190
                vertices[i*2][1]= centerScreen[1] + outerRadius*cosCache[i];
×
2191
                vertices[i*2][2] = 0.0;
×
2192
                vertices[i*2+1][0]= centerScreen[0] + radiusHigh*sinCache[i];
×
2193
                vertices[i*2+1][1]= centerScreen[1] + radiusHigh*cosCache[i];
×
2194
                vertices[i*2+1][2] = 0.0;
×
2195
        }
2196
        painter.drawFromArray(StelPainter::TriangleStrip, (slices+1)*2, 0, false);
×
2197
        painter.enableClientStates(false);
×
2198

2199
        if (getFlagShowContour())
×
2200
        {
2201
                painter.setColor(lineColor);
×
2202
                painter.drawCircle(centerScreen[0], centerScreen[1], static_cast<float>(inner));
×
2203
        }
2204

2205
        if (getFlagShowCardinals())
×
2206
        {
2207
                // Compute polar angle for cardinals and show it
2208
                const StelProjectorP projector = core->getProjection(StelCore::FrameEquinoxEqu);
×
2209
                Vec3d CPos;
×
2210
                Vector2<qreal> cpos = projector->getViewportCenter();
×
2211
                projector->unProject(cpos[0], cpos[1], CPos);
×
2212
                Vec3d CPrel(CPos);
×
2213
                CPrel[2]*=0.2;
×
2214
                Vec3d crel;
×
2215
                projector->project(CPrel, crel);
×
2216
                double polarAngle = atan2(cpos[1] - crel[1], cpos[0] - crel[0]) * (-180.0)/M_PI; // convert to degrees
×
2217
                if (CPos[2] > 0)
×
2218
                        polarAngle += 90.0;
×
2219
                else
2220
                        polarAngle -= 90.0;
×
2221

2222
                painter.setColor(lineColor);
×
2223
                bool flipH = core->getFlipHorz();
×
2224
                bool flipV = core->getFlipVert();
×
2225
                if (flipH && flipV)
×
2226
                        protractorFlipHVTexture->bind();
×
2227
                else if (flipH && !flipV)
×
2228
                        protractorFlipHTexture->bind();
×
2229
                else if (!flipH && flipV)
×
2230
                        protractorFlipVTexture->bind();
×
2231
                else
2232
                        protractorTexture->bind();
×
2233
                painter.drawSprite2dMode(centerScreen[0], centerScreen[1], static_cast<float>(inner / params.devicePixelsPerPixel), static_cast<float>(-polarAngle));                
×
2234
        }
×
2235
}
×
2236

2237
void Oculars::paintText(const StelCore* core)
×
2238
{
2239
        const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz);
×
2240
        StelPainter painter(prj);
×
2241

2242
        // Get the current instruments
2243
        CCD *ccd = Q_NULLPTR;
×
2244
        if(selectedCCDIndex != -1)
×
2245
        {
2246
                ccd = ccds[selectedCCDIndex];
×
2247
        }
2248
        Ocular *ocular = Q_NULLPTR;
×
2249
        if(selectedOcularIndex !=-1)
×
2250
        {
2251
                ocular = oculars[selectedOcularIndex];
×
2252
        }
2253
        Telescope *telescope = Q_NULLPTR;
×
2254
        if(selectedTelescopeIndex != -1)
×
2255
        {
2256
                telescope = telescopes[selectedTelescopeIndex];
×
2257
        }
2258
        Lens *lens = selectedLens();
×
2259

2260
        // set up the color and the GL state
2261
        painter.setColor(textColor);
×
2262
        painter.setBlending(true);
×
2263

2264
        // Get the X & Y positions, and the line height
2265
        painter.setFont(font);
×
2266
        QString widthString = "MMMMMMMMMMMMMMMMMMMMMM";
×
2267
        const double insetFromRHS = painter.getFontMetrics().boundingRect(widthString).width();
×
2268
        StelProjector::StelProjectorParams projectorParams = core->getCurrentStelProjectorParams();
×
2269
        int yPositionOffset = qRound(projectorParams.viewportXywh[3]*projectorParams.viewportCenterOffset[1]);
×
2270
        const double ppx = projectorParams.devicePixelsPerPixel;
×
2271
        int xPosition = qRound(ppx*(projectorParams.viewportXywh[2] - insetFromRHS));
×
2272
        int yPosition = qRound(ppx*(projectorParams.viewportXywh[3] - 20) - yPositionOffset);
×
2273
        const int lineHeight = qRound(ppx*painter.getFontMetrics().height());
×
2274

2275
        // The Ocular
2276
        if (flagShowOculars && ocular!=Q_NULLPTR)
×
2277
        {
2278
                QString ocularNumberLabel;
×
2279
                QString name = ocular->name();
×
2280
                QString ocularI18n = ocular->isBinoculars() ? q_("Binocular") : q_("Ocular");
×
2281
                if (name.isEmpty())
×
2282
                {
2283
                        ocularNumberLabel = QString("%1 #%2").arg(ocularI18n).arg(selectedOcularIndex);
×
2284
                }
2285
                else
2286
                {
2287
                        ocularNumberLabel = QString("%1 #%2: %3").arg(ocularI18n).arg(selectedOcularIndex).arg(name);
×
2288
                }
2289
                // The name of the ocular could be really long.
2290
                if (name.length() > widthString.length())
×
2291
                {
2292
                        xPosition -= qRound(insetFromRHS*0.5);
×
2293
                }
2294
                painter.drawText(xPosition, yPosition, ocularNumberLabel);
×
2295
                yPosition-=lineHeight;
×
2296
                
2297
                if (!ocular->isBinoculars())
×
2298
                {
2299
                        // TRANSLATORS: FL = Focal length
2300
                        QString eFocalLengthLabel = QString(q_("Ocular FL: %1 mm")).arg(QString::number(ocular->effectiveFocalLength(), 'f', 1));
×
2301
                        painter.drawText(xPosition, yPosition, eFocalLengthLabel);
×
2302
                        yPosition-=lineHeight;
×
2303
                        
2304
                        QString ocularFov = QString::number(ocular->apparentFOV(), 'f', 2);
×
2305
                        ocularFov.append(QChar(0x00B0));//Degree sign
×
2306
                        // TRANSLATORS: aFOV = apparent field of view
2307
                        QString ocularFOVLabel = QString(q_("Ocular aFOV: %1")).arg(ocularFov);
×
2308
                        painter.drawText(xPosition, yPosition, ocularFOVLabel);
×
2309
                        yPosition-=lineHeight;
×
2310

2311
                        QString lensNumberLabel;
×
2312
                        // Barlow and Shapley lens
2313
                        if (lens != Q_NULLPTR) // it's null if lens is not selected (lens index = -1)
×
2314
                        {
2315
                                QString lensName = lens->getName();
×
2316
                                if (lensName.isEmpty())
×
2317
                                {
2318
                                        lensNumberLabel = QString(q_("Lens #%1")).arg(selectedLensIndex);
×
2319
                                }
2320
                                else
2321
                                {
2322
                                        lensNumberLabel = QString (q_("Lens #%1: %2")).arg(selectedLensIndex).arg(lensName);
×
2323
                                }
2324
                        }
×
2325
                        else
2326
                        {
2327
                                lensNumberLabel = QString (q_("Lens: none"));
×
2328
                        }
2329
                        painter.drawText(xPosition, yPosition, lensNumberLabel);
×
2330
                        yPosition-=lineHeight;
×
2331

2332
                        if (telescope!=Q_NULLPTR)
×
2333
                        {
2334
                                QString telescopeName = telescope->name();
×
2335
                                QString telescopeString = "";
×
2336

2337
                                if (telescopeName.isEmpty())
×
2338
                                        telescopeString = QString("%1").arg(selectedTelescopeIndex);
×
2339
                                else
2340
                                        telescopeString = QString("%1: %2").arg(selectedTelescopeIndex).arg(telescopeName);
×
2341

2342
                                painter.drawText(xPosition, yPosition, QString(q_("Telescope #%1")).arg(telescopeString));
×
2343
                                yPosition-=lineHeight;
×
2344

2345
                                // General info
2346
                                double mag = ocular->magnification(telescope, lens);
×
2347
                                QString magString = QString::number(mag, 'f', 1);
×
2348
                                magString.append(QChar(0x02E3)); // Was 0x00D7
×
2349
                                magString.append(QString(" (%1D)").arg(QString::number(mag/telescope->diameter(), 'f', 2)));
×
2350

2351
                                painter.drawText(xPosition, yPosition, QString(q_("Magnification: %1")).arg(magString));
×
2352
                                yPosition-=lineHeight;
×
2353

2354
                                if (mag>0)
×
2355
                                {
2356
                                        QString exitPupil = QString::number(telescope->diameter()/mag, 'f', 2);
×
2357

2358
                                        painter.drawText(xPosition, yPosition, QString(q_("Exit pupil: %1 mm")).arg(exitPupil));
×
2359
                                        yPosition-=lineHeight;
×
2360
                                }
×
2361

2362
                                QString fovString = QString::number(ocular->actualFOV(telescope, lens), 'f', 5);
×
2363
                                fovString.append(QChar(0x00B0));//Degree sign
×
2364

2365
                                painter.drawText(xPosition, yPosition, QString(q_("FOV: %1")).arg(fovString));
×
2366
                        }
×
2367
                }
×
2368
        }
×
2369

2370
        // The CCD
2371
        if (flagShowCCD && ccd!=Q_NULLPTR)
×
2372
        {
2373
                QString ccdSensorLabel, ccdInfoLabel, ccdBinningInfo;
×
2374
                QString name = "";
×
2375
                QString telescopeName = "";
×
2376
                double fovX = 0.0;
×
2377
                double fovY = 0.0;
×
2378
                if (telescope!=Q_NULLPTR)
×
2379
                {
2380
                        fovX = ccd->getActualFOVx(telescope, lens);
×
2381
                        fovY = ccd->getActualFOVy(telescope, lens);
×
2382
                        name = ccd->name();
×
2383
                        telescopeName = telescope->name();
×
2384
                }
2385

2386
                ccdInfoLabel = QString(q_("Dimensions: %1")).arg(getDimensionsString(fovX, fovY));
×
2387
                ccdBinningInfo = QString("%1: %2 %4 %3").arg(q_("Binning")).arg(ccd->binningX()).arg(ccd->binningY()).arg(QChar(0x00D7));
×
2388
                
2389
                if (name.isEmpty())
×
2390
                {
2391
                        ccdSensorLabel = QString(q_("Sensor #%1")).arg(selectedCCDIndex);
×
2392
                }
2393
                else
2394
                {
2395
                        ccdSensorLabel = QString(q_("Sensor #%1: %2"))
×
2396
                                        .arg(selectedCCDIndex)
×
2397
                                        .arg(name);
×
2398
                }
2399
                // The telescope
2400
                QString telescopeNumberLabel;
×
2401
                if (telescopeName.isEmpty())
×
2402
                {
2403
                        telescopeNumberLabel = QString(q_("Telescope #%1"))
×
2404
                                        .arg(selectedTelescopeIndex);
×
2405
                }
2406
                else
2407
                {
2408
                        telescopeNumberLabel = QString(q_("Telescope #%1: %2"))
×
2409
                                        .arg(selectedTelescopeIndex)
×
2410
                                        .arg(telescopeName);
×
2411
                }
2412
                painter.drawText(xPosition, yPosition, ccdSensorLabel);
×
2413
                yPosition-=lineHeight;
×
2414
                painter.drawText(xPosition, yPosition, ccdInfoLabel);
×
2415
                yPosition-=lineHeight;
×
2416
                painter.drawText(xPosition, yPosition, ccdBinningInfo);
×
2417
                yPosition-=lineHeight;
×
2418
                painter.drawText(xPosition, yPosition, telescopeNumberLabel);
×
2419
        }
×
2420
}
×
2421

2422
void Oculars::validateAndLoadIniFile()
×
2423
{
2424
        // Ensure the module directory exists
2425
        StelFileMgr::makeSureDirExistsAndIsWritable(StelFileMgr::getUserDir()+"/modules/Oculars");
×
2426
        StelFileMgr::Flags flags = static_cast<StelFileMgr::Flags>(StelFileMgr::Directory|StelFileMgr::Writable);
×
2427
        QString ocularIniPath = StelFileMgr::findFile("modules/Oculars/", flags) + "ocular.ini";
×
2428
        if (ocularIniPath.isEmpty())
×
2429
                return;
×
2430

2431
        // If the ini file does not already exist, create it from the resource in the QT resource
2432
        if(!QFileInfo::exists(ocularIniPath))
×
2433
        {
2434
                QFile src(":/ocular/default_ocular.ini");
×
2435
                if (!src.copy(ocularIniPath))
×
2436
                {
2437
                        qWarning() << "Oculars::validateIniFile cannot copy default_ocular.ini resource to [non-existing] "
×
2438
                                      + ocularIniPath;
×
2439
                }
2440
                else
2441
                {
2442
                        qDebug() << "Oculars::validateAndLoadIniFile() copied default_ocular.ini to " << QDir::toNativeSeparators(ocularIniPath);
×
2443
                        // The resource is read only, and the new file inherits this, so set write-able.
2444
                        QFile dest(ocularIniPath);
×
2445
                        dest.setPermissions(dest.permissions() | QFile::WriteOwner);
×
2446
                }
×
2447
        }
×
2448
        else
2449
        {
2450
                qDebug().noquote() << "Oculars::validateAndLoadIniFile() ocular.ini exists at:" << QDir::toNativeSeparators(ocularIniPath) << ". Checking version...";
×
2451
                QSettings mySettings(ocularIniPath, QSettings::IniFormat);
×
2452
                const float ocularsVersion = mySettings.value("oculars_version", 0.0).toFloat();
×
2453
                qWarning() << "Oculars::validateAndLoadIniFile() found existing ini file version" << ocularsVersion;
×
2454

2455
                if (ocularsVersion < MIN_OCULARS_INI_VERSION)
×
2456
                {
2457
                        qWarning() << "Oculars::validateAndLoadIniFile() existing ini file version" << ocularsVersion
×
2458
                                   << "too old to use; required version is" << MIN_OCULARS_INI_VERSION << ". Copying over new one.";
×
2459
                        // delete last "old" file, if it exists
2460
                        QFile deleteFile(ocularIniPath + ".old");
×
2461
                        deleteFile.remove();
×
2462

2463
                        // Rename the old one, and copy over a new one
2464
                        QFile oldFile(ocularIniPath);
×
2465
                        if (!oldFile.rename(ocularIniPath + ".old"))
×
2466
                        {
2467
                                qWarning() << "Oculars::validateAndLoadIniFile() cannot move ocular.ini resource to ocular.ini.old at path" + QDir::toNativeSeparators(ocularIniPath);
×
2468
                        }
2469
                        else
2470
                        {
2471
                                qWarning() << "Oculars::validateAndLoadIniFile() ocular.ini resource renamed to ocular.ini.old at path" + QDir::toNativeSeparators(ocularIniPath);
×
2472
                                QFile src(":/ocular/default_ocular.ini");
×
2473
                                if (!src.copy(ocularIniPath))
×
2474
                                {
2475
                                        qWarning() << "Oculars::validateIniFile cannot copy default_ocular.ini resource to [non-existing]" + QDir::toNativeSeparators(ocularIniPath);
×
2476
                                }
2477
                                else
2478
                                {
2479
                                        qDebug() << "Oculars::validateAndLoadIniFile() copied default_ocular.ini to" << QDir::toNativeSeparators(ocularIniPath);
×
2480
                                        // The resource is read only, and the new file inherits this...  make sure the new file
2481
                                        // is writable by the Stellarium process so that updates can be done.
2482
                                        QFile dest(ocularIniPath);
×
2483
                                        dest.setPermissions(dest.permissions() | QFile::WriteOwner);
×
2484
                                }
×
2485
                        }
×
2486
                }
×
2487
        }
×
2488
        settings = new QSettings(ocularIniPath, QSettings::IniFormat, this);
×
2489
}
×
2490

2491
void Oculars::unzoomOcular()
×
2492
{
2493
        Q_ASSERT(flagShowOculars == false);
×
2494
        StelCore *core = StelApp::getInstance().getCore();
×
2495
        StelMovementMgr *movementManager = core->getMovementMgr();        
×
2496
        StelSkyDrawer *skyDrawer = core->getSkyDrawer();
×
2497

2498
        if (flagHideGridsLines)
×
2499
                toggleLines(true);
×
2500

2501
        StelApp::getInstance().getStelPropertyManager()->setStelPropertyValue("MilkyWay.saturation", milkyWaySaturation);
×
2502
        disconnect(skyDrawer, SIGNAL(customStarMagLimitChanged(double)), this, SLOT(setMagLimitStarsOcularsManual(double)));
×
2503
        // restore values, but keep current to enable toggling.
2504
        if (!getFlagAutoLimitMagnitude())
×
2505
        {
2506
                flagLimitStarsOculars=skyDrawer->getFlagStarMagnitudeLimit();
×
2507
                magLimitStarsOculars=skyDrawer->getCustomStarMagnitudeLimit();
×
2508
        }
2509
        skyDrawer->setCustomStarMagnitudeLimit(magLimitStarsMain);
×
2510
        skyDrawer->setFlagStarMagnitudeLimit(flagLimitStarsMain);
×
2511
        relativeStarScaleOculars=skyDrawer->getRelativeStarScale();
×
2512
        absoluteStarScaleOculars=skyDrawer->getAbsoluteStarScale();
×
2513
        skyDrawer->setRelativeStarScale(relativeStarScaleMain);
×
2514
        skyDrawer->setAbsoluteStarScale(absoluteStarScaleMain);
×
2515
        skyDrawer->setFlagLuminanceAdaptation(flagAdaptationMain);
×
2516
        skyDrawer->setFlagPlanetMagnitudeLimit(flagLimitPlanetsMain);
×
2517
        skyDrawer->setFlagNebulaMagnitudeLimit(flagLimitDSOsMain);
×
2518
        skyDrawer->setCustomPlanetMagnitudeLimit(magLimitPlanetsMain);
×
2519
        skyDrawer->setCustomNebulaMagnitudeLimit(magLimitDSOsMain);
×
2520
        movementManager->setFlagEnableZoomKeys(true);
×
2521
        movementManager->setFlagEnableMouseZooming(true);
×
2522

2523
        GETSTELMODULE(SolarSystem)->setFlagMoonScale(flagMoonScaleMain);
×
2524
        GETSTELMODULE(SolarSystem)->setFlagMinorBodyScale(flagMinorBodiesScaleMain);
×
2525
        GETSTELMODULE(SolarSystem)->setFlagSunScale(flagSunScaleMain);
×
2526
        GETSTELMODULE(SolarSystem)->setFlagPlanetScale(flagPlanetsScaleMain);
×
2527
        GETSTELMODULE(NebulaMgr)->setHintsProportional(flagDSOPropHintMain);
×
2528

2529
        // Set the screen display
2530
        core->setFlipHorz(flipHorzMain);
×
2531
        core->setFlipVert(flipVertMain);
×
2532

2533
        if (getFlagInitFovUsage())
×
2534
                movementManager->zoomTo(movementManager->getInitFov());
×
2535
        else if (!flagShowTelrad)
×
2536
                movementManager->zoomTo(initialFOV);
×
2537

2538
        if (getFlagInitDirectionUsage())
×
2539
                movementManager->setViewDirectionJ2000(core->altAzToJ2000(movementManager->getInitViewingDirection(), StelCore::RefractionOff));
×
2540
}
×
2541

2542
void Oculars::zoom(bool zoomedIn)
×
2543
{
2544
        if (flagShowOculars && selectedOcularIndex == -1)
×
2545
        {
2546
                // The user cycled out the selected ocular
2547
                flagShowOculars = false;
×
2548
        }
2549

2550
        if (flagShowOculars)
×
2551
        {
2552
                if (!zoomedIn)
×
2553
                {
2554
                        StelCore *core = StelApp::getInstance().getCore();
×
2555
                        StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
×
2556

2557
                        if (flagHideGridsLines)
×
2558
                        {
2559
                                // Store current state for later resetting
2560
                                flagGridLinesDisplayedMain      = propMgr->getStelPropertyValue("GridLinesMgr.gridlinesDisplayed").toBool();
×
2561
                                flagCardinalPointsMain          = propMgr->getStelPropertyValue("LandscapeMgr.cardinalPointsDisplayed").toBool();
×
2562
                                flagConstellationLinesMain      = propMgr->getStelPropertyValue("ConstellationMgr.linesDisplayed").toBool();
×
2563
                                flagConstellationBoundariesMain        = propMgr->getStelPropertyValue("ConstellationMgr.boundariesDisplayed").toBool();
×
2564
                                flagAsterismLinesMain           = propMgr->getStelPropertyValue("AsterismMgr.linesDisplayed").toBool();
×
2565
                                flagRayHelpersLinesMain         = propMgr->getStelPropertyValue("AsterismMgr.rayHelpersDisplayed").toBool();
×
2566
                        }
2567

2568
                        StelSkyDrawer *skyDrawer = core->getSkyDrawer();
×
2569
                        // Current state
2570
                        flagAdaptationMain        = skyDrawer->getFlagLuminanceAdaptation();
×
2571
                        flagLimitStarsMain        = skyDrawer->getFlagStarMagnitudeLimit();
×
2572
                        flagLimitPlanetsMain        = skyDrawer->getFlagPlanetMagnitudeLimit();
×
2573
                        flagLimitDSOsMain        = skyDrawer->getFlagNebulaMagnitudeLimit();
×
2574
                        magLimitStarsMain        = skyDrawer->getCustomStarMagnitudeLimit();
×
2575
                        magLimitPlanetsMain        = skyDrawer->getCustomPlanetMagnitudeLimit();
×
2576
                        magLimitDSOsMain        = skyDrawer->getCustomNebulaMagnitudeLimit();
×
2577
                        relativeStarScaleMain        = skyDrawer->getRelativeStarScale();
×
2578
                        absoluteStarScaleMain        = skyDrawer->getAbsoluteStarScale();
×
2579

2580
                        flagMoonScaleMain        = propMgr->getStelPropertyValue("SolarSystem.flagMoonScale").toBool();
×
2581
                        flagMinorBodiesScaleMain = propMgr->getStelPropertyValue("SolarSystem.flagMinorBodyScale").toBool();
×
2582
                        flagSunScaleMain         = propMgr->getStelPropertyValue("SolarSystem.flagSunScale").toBool();
×
2583
                        flagPlanetsScaleMain     = propMgr->getStelPropertyValue("SolarSystem.flagPlanetScale").toBool();
×
2584

2585
                        flagDSOPropHintMain        = propMgr->getStelPropertyValue("NebulaMgr.hintsProportional").toBool();
×
2586
                        milkyWaySaturation        = propMgr->getStelPropertyValue("MilkyWay.saturation").toDouble();
×
2587

2588
                        flipHorzMain = core->getFlipHorz();
×
2589
                        flipVertMain = core->getFlipVert();
×
2590

2591
                        StelMovementMgr *movementManager = core->getMovementMgr();
×
2592
                        initialFOV = movementManager->getCurrentFov();
×
2593
                }
2594

2595
                // set new state
2596
                zoomOcular();
×
2597
        }
2598
        else
2599
        {
2600
                //reset to original state
2601
                unzoomOcular();
×
2602
        }
2603
}
×
2604

2605
void Oculars::toggleLines(bool visible)
×
2606
{
2607
        if (flagShowTelrad)
×
2608
                return;
×
2609

2610
        StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
×
2611

2612
        if (visible)
×
2613
        {
2614
                propMgr->setStelPropertyValue("GridLinesMgr.gridlinesDisplayed", flagGridLinesDisplayedMain);
×
2615
                propMgr->setStelPropertyValue("LandscapeMgr.cardinalPointsDisplayed", flagCardinalPointsMain);
×
2616
                propMgr->setStelPropertyValue("ConstellationMgr.linesDisplayed", flagConstellationLinesMain);
×
2617
                propMgr->setStelPropertyValue("ConstellationMgr.boundariesDisplayed", flagConstellationBoundariesMain);
×
2618
                propMgr->setStelPropertyValue("AsterismMgr.linesDisplayed", flagAsterismLinesMain);
×
2619
                propMgr->setStelPropertyValue("AsterismMgr.rayHelpersDisplayed", flagRayHelpersLinesMain);
×
2620
        }
2621
        else
2622
        {
2623
                propMgr->setStelPropertyValue("GridLinesMgr.gridlinesDisplayed", false);
×
2624
                propMgr->setStelPropertyValue("LandscapeMgr.cardinalPointsDisplayed", false);
×
2625
                propMgr->setStelPropertyValue("ConstellationMgr.linesDisplayed", false);
×
2626
                propMgr->setStelPropertyValue("ConstellationMgr.boundariesDisplayed", false);
×
2627
                propMgr->setStelPropertyValue("AsterismMgr.linesDisplayed", false);
×
2628
                propMgr->setStelPropertyValue("AsterismMgr.rayHelpersDisplayed", false);
×
2629
        }
2630
}
2631

2632
void Oculars::zoomOcular()
×
2633
{
2634
        Q_ASSERT(flagShowOculars == true);
×
2635
        StelCore *core = StelApp::getInstance().getCore();
×
2636
        StelMovementMgr *movementManager = core->getMovementMgr();
×
2637
        StelSkyDrawer *skyDrawer = core->getSkyDrawer();
×
2638

2639
        if (flagHideGridsLines)
×
2640
                toggleLines(false);
×
2641

2642
        skyDrawer->setFlagLuminanceAdaptation(false);
×
2643
        StelApp::getInstance().getStelPropertyManager()->setStelPropertyValue("MilkyWay.saturation", 0.f);
×
2644

2645
        GETSTELMODULE(SolarSystem)->setFlagMoonScale(false);
×
2646
        GETSTELMODULE(SolarSystem)->setFlagMinorBodyScale(false);
×
2647
        GETSTELMODULE(SolarSystem)->setFlagSunScale(false);
×
2648
        GETSTELMODULE(SolarSystem)->setFlagPlanetScale(false);
×
2649
        GETSTELMODULE(NebulaMgr)->setHintsProportional(false);
×
2650

2651
        movementManager->setFlagTracking(true);
×
2652
        movementManager->setFlagEnableZoomKeys(false);
×
2653
        movementManager->setFlagEnableMouseZooming(false);
×
2654
        
2655
        // We won't always have a selected object
2656
        if (StelApp::getInstance().getStelObjectMgr().getWasSelected())
×
2657
        {
2658
                StelObjectP selectedObject = StelApp::getInstance().getStelObjectMgr().getSelectedObject()[0];
×
2659
                movementManager->moveToJ2000(selectedObject->getEquinoxEquatorialPos(core), movementManager->mountFrameToJ2000(Vec3d(0., 0., 1.)), 0.0, StelMovementMgr::ZoomIn);
×
2660
        }
×
2661

2662
        // Set the screen display
2663
        Ocular * ocular = oculars[selectedOcularIndex];
×
2664
        Telescope * telescope = Q_NULLPTR;
×
2665
        Lens * lens = Q_NULLPTR;
×
2666
        // Only consider flip is we're not binoculars
2667
        if (ocular->isBinoculars())
×
2668
        {
2669
                core->setFlipHorz(false);
×
2670
                core->setFlipVert(false);
×
2671
        }
2672
        else
2673
        {
2674
                if (selectedLensIndex >= 0)
×
2675
                {
2676
                        lens = lenses[selectedLensIndex];
×
2677
                }
2678
                telescope = telescopes[selectedTelescopeIndex];
×
2679
                core->setFlipHorz(telescope->isHFlipped());
×
2680
                core->setFlipVert(telescope->isVFlipped());
×
2681
        }
2682

2683
        // Change relative and absolute scales for stars
2684
        relativeStarScaleMain=skyDrawer->getRelativeStarScale();
×
2685
        skyDrawer->setRelativeStarScale(relativeStarScaleOculars);
×
2686
        absoluteStarScaleMain=skyDrawer->getAbsoluteStarScale();
×
2687
        skyDrawer->setAbsoluteStarScale(absoluteStarScaleOculars);
×
2688

2689
        // Limit stars and DSOs        magnitude. Either compute limiting magnitude for the telescope/ocular,
2690
        // or just use the custom oculars mode value.
2691

2692
        // TODO: set lim. mag without also activating flag it if it should not be activated.
2693

2694
        double limitMag=magLimitStarsOculars;
×
2695
        if (getFlagAutoLimitMagnitude() || flagLimitStarsOculars )
×
2696
        {
2697
                if (getFlagAutoLimitMagnitude())
×
2698
                {
2699
                        disconnect(skyDrawer, SIGNAL(customStarMagLimitChanged(double)), this, SLOT(setMagLimitStarsOcularsManual(double))); // we want to keep the old manual value.
×
2700
                        limitMag = computeLimitMagnitude(ocular, telescope);
×
2701
                        // TODO: Is it really good to apply the star formula to DSO?
2702
                        skyDrawer->setFlagNebulaMagnitudeLimit(true);
×
2703
                        skyDrawer->setCustomNebulaMagnitudeLimit(limitMag);
×
2704
                        skyDrawer->setFlagPlanetMagnitudeLimit(true);
×
2705
                        skyDrawer->setCustomPlanetMagnitudeLimit(limitMag);
×
2706
                }
2707
                else
2708
                {        // It's possible that the user changes the custom magnitude while viewing, and then changes the ocular.
2709
                        // Therefore we need a temporary connection.
2710
                        connect(skyDrawer, SIGNAL(customStarMagLimitChanged(double)), this, SLOT(setMagLimitStarsOcularsManual(double)));
×
2711
                }
2712
                skyDrawer->setFlagStarMagnitudeLimit(true);
×
2713
        }
2714
        skyDrawer->setCustomStarMagnitudeLimit(limitMag);
×
2715

2716
        actualFOV = ocular->actualFOV(telescope, lens);
×
2717
        // See if the mask was scaled; if so, correct the actualFOV.
2718
        if (flagScaleImageCircle && ocular->apparentFOV() > 0.0 && !ocular->isBinoculars())
×
2719
        {
2720
                actualFOV = maxEyepieceAngle * actualFOV / ocular->apparentFOV();
×
2721
        }
2722
        movementManager->zoomTo(actualFOV, 0.f);
×
2723
}
×
2724

2725
void Oculars::hideUsageMessageIfDisplayed()
×
2726
{
2727
        if (usageMessageLabelID > -1)
×
2728
        {
2729
                LabelMgr *labelManager = GETSTELMODULE(LabelMgr);
×
2730
                labelManager->setLabelShow(usageMessageLabelID, false);
×
2731
                labelManager->deleteLabel(usageMessageLabelID);
×
2732
                usageMessageLabelID = -1;
×
2733
        }
2734
}
×
2735

2736
Lens* Oculars::selectedLens()
×
2737
{
2738
        if (selectedLensIndex >= 0 && selectedLensIndex < lenses.count())
×
2739
        {
2740
                return lenses[selectedLensIndex];
×
2741
        }
2742
        return Q_NULLPTR;
×
2743
}
2744

2745
QMenu* Oculars::addLensSubmenu(QMenu* parent)
×
2746
{
2747
        Q_ASSERT(parent);
×
2748

2749
        QMenu *submenu = new QMenu(q_("&Lens"), parent);
×
2750
        submenu->addAction(q_("&Previous lens"), this, SLOT(decrementLensIndex()));
×
2751
        submenu->addAction(q_("&Next lens"), this, SLOT(incrementLensIndex()));
×
2752
        submenu->addSeparator();
×
2753
        submenu->addAction(q_("None"), this, SLOT(disableLens()));
×
2754

2755
        for (int index = 0; index < lenses.count(); ++index)
×
2756
        {
2757
                QString label;
×
2758
                if (index < 10)
×
2759
                {
2760
                        label = QString("&%1: %2").arg(index).arg(lenses[index]->getName());
×
2761
                }
2762
                else
2763
                {
2764
                        label = lenses[index]->getName();
×
2765
                }
2766
                QAction* action = submenu->addAction(label, submenu, [=](){selectLensAtIndex(index);});
×
2767
                if (index == selectedLensIndex)
×
2768
                {
2769
                        action->setCheckable(true);
×
2770
                        action->setChecked(true);
×
2771
                }
2772
        }
×
2773
        return submenu;
×
2774
}
2775

2776
QMenu* Oculars::addTelescopeSubmenu(QMenu *parent)
×
2777
{
2778
        Q_ASSERT(parent);
×
2779

2780
        QMenu* submenu = new QMenu(q_("&Telescope"), parent);
×
2781
        submenu->addAction(q_("&Previous telescope"), this, SLOT(decrementTelescopeIndex()));
×
2782
        submenu->addAction(q_("&Next telescope"), this, SLOT(incrementTelescopeIndex()));
×
2783
        submenu->addSeparator();
×
2784
        for (int index = 0; index < telescopes.count(); ++index)
×
2785
        {
2786
                QString label;
×
2787
                if (index < 10)
×
2788
                {
2789
                        label = QString("&%1: %2").arg(index).arg(telescopes[index]->name());
×
2790
                }
2791
                else
2792
                {
2793
                        label = telescopes[index]->name();
×
2794
                }
2795
                QAction* action = submenu->addAction(label, submenu, [=](){selectTelescopeAtIndex(index);});
×
2796
                if (index == selectedTelescopeIndex)
×
2797
                {
2798
                        action->setCheckable(true);
×
2799
                        action->setChecked(true);
×
2800
                }
2801
        }
×
2802

2803
        return submenu;
×
2804
}
2805

2806
void Oculars::setFlagDMSDegrees(const bool b)
×
2807
{
2808
        flagDMSDegrees = b;
×
2809
        settings->setValue("use_decimal_degrees", !b);
×
2810
        settings->sync();
×
2811
        emit flagDMSDegreesChanged(b);
×
2812
}
×
2813

2814
bool Oculars::getFlagDMSDegrees() const
×
2815
{
2816
        return flagDMSDegrees;
×
2817
}
2818

2819
void Oculars::setFlagHorizontalCoordinates(const bool b)
×
2820
{
2821
        flagHorizontalCoordinates = b;
×
2822
        settings->setValue("use_horizontal_coordinates", b);
×
2823
        settings->sync();
×
2824
        emit flagHorizontalCoordinatesChanged(b);
×
2825
}
×
2826

2827
bool Oculars::getFlagHorizontalCoordinates() const
×
2828
{
2829
        return flagHorizontalCoordinates;
×
2830
}
2831

2832
void Oculars::setFlagRequireSelection(const bool b)
×
2833
{
2834
        flagRequireSelection = b;
×
2835
        settings->setValue("require_selection_to_zoom", b);
×
2836
        settings->sync();
×
2837
        emit flagRequireSelectionChanged(b);
×
2838
}
×
2839

2840
bool Oculars::getFlagRequireSelection() const
×
2841
{
2842
        return flagRequireSelection;
×
2843
}
2844

2845
void Oculars::setFlagAutoLimitMagnitude(const bool b)
×
2846
{
2847
        flagAutoLimitMagnitude = b;
×
2848
        settings->setValue("autolimit_stellar_magnitude", b);
×
2849
        settings->sync();
×
2850
        emit flagAutoLimitMagnitudeChanged(b);
×
2851
}
×
2852

2853
bool Oculars::getFlagAutoLimitMagnitude() const
×
2854
{
2855
        return flagAutoLimitMagnitude;
×
2856
}
2857

2858
void Oculars::setMagLimitStarsOcularsManual(double mag)
×
2859
{
2860
        magLimitStarsOculars = mag;
×
2861
        settings->setValue("limit_stellar_magnitude_oculars_val", mag);
×
2862
        settings->sync();
×
2863
        // This is no property, no need to emit a signal.
2864
}
×
2865

2866
double Oculars::getMagLimitStarsOcularsManual() const
×
2867
{
2868
        return magLimitStarsOculars;
×
2869
}
2870

2871
void Oculars::setFlagInitFovUsage(const bool b)
×
2872
{
2873
        flagInitFOVUsage = b;
×
2874
        settings->setValue("use_initial_fov", b);
×
2875
        settings->sync();
×
2876
        emit flagInitFOVUsageChanged(b);
×
2877
}
×
2878

2879
bool Oculars::getFlagInitFovUsage() const
×
2880
{
2881
        return flagInitFOVUsage;
×
2882
}
2883

2884
void Oculars::setFlagInitDirectionUsage(const bool b)
×
2885
{
2886
        flagInitDirectionUsage = b;
×
2887
        settings->setValue("use_initial_direction", b);
×
2888
        settings->sync();
×
2889
        emit flagInitDirectionUsageChanged(b);
×
2890
}
×
2891

2892
bool Oculars::getFlagInitDirectionUsage() const
×
2893
{
2894
        return flagInitDirectionUsage;
×
2895
}
2896

2897
void Oculars::setFlagAutosetMountForCCD(const bool b)
×
2898
{
2899
        flagAutosetMountForCCD = b;
×
2900
        settings->setValue("use_mount_autoset", b);
×
2901
        settings->sync();
×
2902

2903
        if (!b)
×
2904
        {
2905
                StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
×
2906
                propMgr->setStelPropertyValue("StelMovementMgr.equatorialMount", equatorialMountEnabledMain);
×
2907
        }
2908
        emit flagAutosetMountForCCDChanged(b);
×
2909
}
×
2910

2911
bool Oculars::getFlagAutosetMountForCCD() const
×
2912
{
2913
        return  flagAutosetMountForCCD;
×
2914
}
2915

2916
void Oculars::setFlagScalingFOVForTelrad(const bool b)
×
2917
{
2918
        flagScalingFOVForTelrad = b;
×
2919
        settings->setValue("use_telrad_fov_scaling", b);
×
2920
        settings->sync();
×
2921
        emit flagScalingFOVForTelradChanged(b);
×
2922
}
×
2923

2924
bool Oculars::getFlagScalingFOVForTelrad() const
×
2925
{
2926
        return  flagScalingFOVForTelrad;
×
2927
}
2928

2929
void Oculars::setTelradFOV(const Vec4f &fov)
×
2930
{
2931
        telradFOV = fov;
×
2932
        settings->setValue("telrad_fov", fov.toStr());
×
2933
        settings->sync();
×
2934
        emit telradFOVChanged(fov);
×
2935
}
×
2936

2937
Vec4f Oculars::getTelradFOV() const
×
2938
{
2939
        return  telradFOV;
×
2940
}
2941

2942
void Oculars::setFlagScalingFOVForCCD(const bool b)
×
2943
{
2944
        flagScalingFOVForCCD = b;
×
2945
        settings->setValue("use_ccd_fov_scaling", b);
×
2946
        settings->sync();
×
2947
        emit flagScalingFOVForCCDChanged(b);
×
2948
}
×
2949

2950
bool Oculars::getFlagScalingFOVForCCD() const
×
2951
{
2952
        return  flagScalingFOVForCCD;
×
2953
}
2954

2955
void Oculars::setFlagMaxExposureTimeForCCD(const bool b)
×
2956
{
2957
        flagMaxExposureTimeForCCD = b;
×
2958
        settings->setValue("show_ccd_exposure_time", b);
×
2959
        settings->sync();
×
2960
        emit flagMaxExposureTimeForCCDChanged(b);
×
2961
}
×
2962

2963
bool Oculars::getFlagMaxExposureTimeForCCD() const
×
2964
{
2965
        return  flagMaxExposureTimeForCCD;
×
2966
}
2967

2968
void Oculars::setFlagUseSemiTransparency(const bool b)
×
2969
{
2970
        flagSemiTransparency = b;
×
2971
        settings->setValue("use_semi_transparency", b);
×
2972
        settings->sync();
×
2973
        emit flagUseSemiTransparencyChanged(b);
×
2974
}
×
2975

2976
bool Oculars::getFlagUseSemiTransparency() const
×
2977
{
2978
        return flagSemiTransparency;
×
2979
}
2980

2981
void Oculars::setTransparencyMask(const int v)
×
2982
{
2983
        transparencyMask = v;
×
2984
        settings->setValue("transparency_mask", v);
×
2985
        settings->sync();
×
2986
        emit transparencyMaskChanged(v);
×
2987
}
×
2988

2989
int Oculars::getTransparencyMask() const
×
2990
{
2991
        return transparencyMask;
×
2992
}
2993

2994
void Oculars::setFlagShowResolutionCriteria(const bool b)
×
2995
{
2996
        flagShowResolutionCriteria = b;
×
2997
        settings->setValue("show_resolution_criteria", b);
×
2998
        settings->sync();
×
2999
        emit flagShowResolutionCriteriaChanged(b);
×
3000
}
×
3001

3002
bool Oculars::getFlagShowResolutionCriteria() const
×
3003
{
3004
        return flagShowResolutionCriteria;
×
3005
}
3006

3007
void Oculars::setCcdCropOverlayHSize(int size) {
×
3008
        ccdCropOverlayHSize = size;
×
3009
        settings->setValue("ccd_crop_overlay_hsize", size);
×
3010
        settings->sync();
×
3011
        emit ccdCropOverlayHSizeChanged(size);
×
3012
}
×
3013

3014
void Oculars::setCcdCropOverlayVSize(int size) {
×
3015
        ccdCropOverlayVSize = size;
×
3016
        settings->setValue("ccd_crop_overlay_vsize", size);
×
3017
        settings->sync();
×
3018
        emit ccdCropOverlayVSizeChanged(size);
×
3019
}
×
3020

3021
void Oculars::setFlagShowCcdCropOverlay(const bool b)
×
3022
{
3023
        flagShowCcdCropOverlay = b;
×
3024
        settings->setValue("show_ccd_crop_overlay", b);
×
3025
        settings->sync();
×
3026
        emit flagShowCcdCropOverlayChanged(b);
×
3027
}
×
3028

3029
bool Oculars::getFlagShowCcdCropOverlay(void) const
×
3030
{
3031
        return flagShowCcdCropOverlay;
×
3032
}
3033

3034
void Oculars::setFlagShowCcdCropOverlayPixelGrid(const bool b)
×
3035
{
3036
        flagShowCcdCropOverlayPixelGrid = b;
×
3037
        settings->setValue("ccd_crop_overlay_pixel_grid", b);
×
3038
        settings->sync();
×
3039
        emit flagShowCcdCropOverlayPixelGridChanged(b);
×
3040
}
×
3041

3042
bool Oculars::getFlagShowCcdCropOverlayPixelGrid(void) const
×
3043
{
3044
        return flagShowCcdCropOverlayPixelGrid;
×
3045
}
3046

3047

3048
void Oculars::setFlagShowFocuserOverlay(const bool b)
×
3049
{
3050
        flagShowFocuserOverlay = b;
×
3051
        settings->setValue("show_focuser_overlay", b);
×
3052
        settings->sync();
×
3053
        emit flagShowFocuserOverlayChanged(b);
×
3054
}
×
3055

3056
bool Oculars::getFlagShowFocuserOverlay(void) const
×
3057
{
3058
        return flagShowFocuserOverlay;
×
3059
}
3060

3061
void Oculars::setFlagUseSmallFocuserOverlay(const bool b)
×
3062
{
3063
        flagUseSmallFocuserOverlay = b;
×
3064
        settings->setValue("use_small_focuser_overlay", b);
×
3065
        settings->sync();
×
3066
        emit flagUseSmallFocuserOverlayChanged(b);
×
3067
}
×
3068

3069
bool Oculars::getFlagUseSmallFocuserOverlay(void) const
×
3070
{
3071
        return flagUseSmallFocuserOverlay;
×
3072
}
3073

3074
void Oculars::setFlagUseMediumFocuserOverlay(const bool b)
×
3075
{
3076
        flagUseMediumFocuserOverlay = b;
×
3077
        settings->setValue("use_medium_focuser_overlay", b);
×
3078
        settings->sync();
×
3079
        emit flagUseMediumFocuserOverlayChanged(b);
×
3080
}
×
3081

3082
bool Oculars::getFlagUseMediumFocuserOverlay(void) const
×
3083
{
3084
        return flagUseMediumFocuserOverlay;
×
3085
}
3086

3087
void Oculars::setFlagUseLargeFocuserOverlay(const bool b)
×
3088
{
3089
        flagUseLargeFocuserOverlay = b;
×
3090
        settings->setValue("use_large_focuser_overlay", b);
×
3091
        settings->sync();
×
3092
        emit flagUseLargeFocuserOverlayChanged(b);
×
3093
}
×
3094

3095
bool Oculars::getFlagUseLargeFocuserOverlay(void) const
×
3096
{
3097
        return flagUseLargeFocuserOverlay;
×
3098
}
3099

3100
void Oculars::setFlagShowContour(const bool b)
×
3101
{
3102
        flagShowContour = b;
×
3103
        settings->setValue("show_ocular_contour", b);
×
3104
        settings->sync();
×
3105
        emit flagShowContourChanged(b);
×
3106
}
×
3107

3108
bool Oculars::getFlagShowContour(void) const
×
3109
{
3110
        return flagShowContour;
×
3111
}
3112

3113
void Oculars::setFlagShowCardinals(const bool b)
×
3114
{
3115
        flagShowCardinals = b;
×
3116
        settings->setValue("show_ocular_cardinals", b);
×
3117
        settings->sync();
×
3118
        emit flagShowCardinalsChanged(b);
×
3119
}
×
3120

3121
bool Oculars::getFlagShowCardinals(void) const
×
3122
{
3123
        return flagShowCardinals;
×
3124
}
3125

3126
void Oculars::setFlagAlignCrosshair(const bool b)
×
3127
{
3128
        flagAlignCrosshair = b;
×
3129
        settings->setValue("align_crosshair", b);
×
3130
        settings->sync();
×
3131
        emit flagAlignCrosshairChanged(b);
×
3132
}
×
3133

3134
bool Oculars::getFlagAlignCrosshair(void) const
×
3135
{
3136
        return flagAlignCrosshair;
×
3137
}
3138

3139
void Oculars::setArrowButtonScale(const int val)
×
3140
{
3141
        arrowButtonScale = val;
×
3142
        settings->setValue("arrow_scale", val);
×
3143
        settings->sync();
×
3144
        emit arrowButtonScaleChanged(val);
×
3145
}
×
3146

3147
int Oculars::getArrowButtonScale() const
×
3148
{
3149
        return arrowButtonScale;
×
3150
}
3151

3152
void Oculars::setFlagHideGridsLines(const bool b)
×
3153
{
3154
        if (b != flagHideGridsLines)
×
3155
        {
3156
                flagHideGridsLines = b;
×
3157
                settings->setValue("hide_grids_and_lines", b);
×
3158
                settings->sync();
×
3159
                emit flagHideGridsLinesChanged(b);
×
3160

3161
                if (b && flagShowOculars)
×
3162
                {
3163
                        // Store current state for later resetting
3164
                        StelPropertyMgr* propMgr=StelApp::getInstance().getStelPropertyManager();
×
3165
                        flagGridLinesDisplayedMain        = propMgr->getStelPropertyValue("GridLinesMgr.gridlinesDisplayed").toBool();
×
3166
                        flagCardinalPointsMain                = propMgr->getStelPropertyValue("LandscapeMgr.cardinalPointsDisplayed").toBool();
×
3167
                        flagConstellationLinesMain        = propMgr->getStelPropertyValue("ConstellationMgr.linesDisplayed").toBool();
×
3168
                        flagConstellationBoundariesMain        = propMgr->getStelPropertyValue("ConstellationMgr.boundariesDisplayed").toBool();
×
3169
                        flagAsterismLinesMain                = propMgr->getStelPropertyValue("AsterismMgr.linesDisplayed").toBool();
×
3170
                        flagRayHelpersLinesMain                = propMgr->getStelPropertyValue("AsterismMgr.rayHelpersDisplayed").toBool();
×
3171
                        toggleLines(false);
×
3172
                }
×
3173
                else if (!b && flagShowOculars)
×
3174
                {
3175
                        // Restore main program state
3176
                        toggleLines(true);
×
3177
                }
3178
        }
3179
}
×
3180

3181
bool Oculars::getFlagHideGridsLines() const
×
3182
{
3183
        return flagHideGridsLines;
×
3184
}
3185

3186
QString Oculars::getDimensionsString(double fovX, double fovY) const
×
3187
{
3188
        QString stringFovX, stringFovY;
×
3189
        if (getFlagDMSDegrees())
×
3190
        {
3191
                if (fovX >= 1.0)
×
3192
                {
3193
                        int degrees = static_cast<int>(fovX);
×
3194
                        double minutes = (fovX - degrees) * 60.;
×
3195
                        stringFovX = QString::number(degrees) + QChar(0x00B0) + QString::number(minutes, 'f', 2) + QChar(0x2032);
×
3196
                }
3197
                else
3198
                {
3199
                        double minutes = fovX * 60.;
×
3200
                        stringFovX = QString::number(minutes, 'f', 2) + QChar(0x2032);
×
3201
                }
3202

3203
                if (fovY >= 1.0)
×
3204
                {
3205
                        int degrees = static_cast<int>(fovY);
×
3206
                        double minutes = (fovY - degrees) * 60.;
×
3207
                        stringFovY = QString::number(degrees) + QChar(0x00B0) + QString::number(minutes, 'f', 2) + QChar(0x2032);
×
3208
                }
3209
                else
3210
                {
3211
                        double minutes = fovY * 60;
×
3212
                        stringFovY = QString::number(minutes, 'f', 2) + QChar(0x2032);
×
3213
                }
3214
        }
3215
        else
3216
        {
3217
                stringFovX = QString::number(fovX, 'f', 5) + QChar(0x00B0);
×
3218
                stringFovY = QString::number(fovY, 'f', 5) + QChar(0x00B0);
×
3219
        }
3220

3221
        return stringFovX + QChar(0x00D7) + stringFovY;
×
3222
}
×
3223

3224
// Define whether the button toggling eyepieces should be visible
3225
void Oculars::setFlagShowOcularsButton(bool b)
×
3226
{
3227
        StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
3228
        if (gui)
×
3229
        {
3230
                if (b==true) {
×
3231
                        if (toolbarButton==Q_NULLPTR) {
×
3232
                                // Create the oculars button
3233
                                toolbarButton = new StelButton(Q_NULLPTR, *pxmapOnIcon, *pxmapOffIcon, *pxmapGlow, "actionShow_Oculars", false, "actionShow_Oculars_dialog");
×
3234
                        }
3235
                        gui->getButtonBar()->addButton(toolbarButton, "065-pluginsGroup");
×
3236
                } else {
3237
                        gui->getButtonBar()->hideButton("actionShow_Oculars");
×
3238
                }
3239
        }
3240
        flagShowOcularsButton = b;
×
3241
        settings->setValue("show_toolbar_button", b);
×
3242
        settings->sync();
×
3243

3244
        emit flagShowOcularsButtonChanged(b);
×
3245
}
×
3246

3247

3248
void Oculars::setGuiPanelFontSize(int size)
×
3249
{
3250
        // This forces a redraw of the panel.
3251
        if (size!=guiPanelFontSize)
×
3252
        {
3253
                bool guiPanelVisible=guiPanel;
×
3254
                if (guiPanelVisible)
×
3255
                        enableGuiPanel(false);
×
3256
                guiPanelFontSize=size;
×
3257
                if (guiPanelVisible)
×
3258
                        enableGuiPanel(true);
×
3259

3260
                settings->setValue("gui_panel_fontsize", size);
×
3261
                settings->sync();
×
3262
                emit guiPanelFontSizeChanged(size);
×
3263
        }
3264
}
×
3265

3266
void Oculars::toggleCropOverlay()
×
3267
{
3268
        setFlagShowCcdCropOverlay(!getFlagShowCcdCropOverlay());
×
3269
}
×
3270

3271
void Oculars::togglePixelGrid()
×
3272
{
3273
        setFlagShowCcdCropOverlayPixelGrid(!getFlagShowCcdCropOverlayPixelGrid());
×
3274
}
×
3275

3276
void Oculars::toggleFocuserOverlay()
×
3277
{
3278
        setFlagShowFocuserOverlay(!getFlagShowFocuserOverlay());
×
3279
}
×
3280

3281
double Oculars::computeLimitMagnitude(Ocular *ocular, Telescope *telescope)
×
3282
{
3283
        // Simplified calculation of the penetrating power of the telescope
3284
        if (ocular->isBinoculars())
×
3285
        {
3286
                // Harald Lang's modified version of Carlin's formula (see below)
3287
                // 3 log A + 2 log X + 0.6 + v
3288
                // A = aperture in cm
3289
                // X = magnification
3290
                // 0.6 = constant of exit pupil
3291
                // v = Naked Eye Lim Mag
3292
                // https://www.cloudynights.com/topic/99013-binocular-limiting-magnitude/
3293
                const auto drawer = StelApp::getInstance().getCore()->getSkyDrawer();
×
3294
                const float nelm = StelCore::luminanceToNELM(drawer->getLightPollutionLuminance());
×
3295
                return 3.0*std::log10(ocular->fieldStop()/10) + 2.0*std::log10(ocular->effectiveFocalLength()) + 0.6 + nelm;
×
3296
        }
3297
        else
3298
        {
3299
                // A better formula for telescopic limiting magnitudes?
3300
                // North, G.; Journal of the British Astronomical Association, vol.107, no.2, p.82
3301
                // http://adsabs.harvard.edu/abs/1997JBAA..107...82N
3302
                return 4.5 + 4.4*std::log10((telescope!=Q_NULLPTR) ? telescope->diameter() : 0.1); // Avoid a potential call of null pointer, and a log(0) error.
×
3303
        }
3304
}
3305

3306
void Oculars::handleAutoLimitToggle(bool on)
×
3307
{
3308
        if (!flagShowOculars)
×
3309
                return;
×
3310

3311
        // When we are in Oculars mode, we must toggle between the auto limit and manual limit. Logic taken from zoomOcular()/unzoomOcular()
3312
        StelCore *core = StelApp::getInstance().getCore();
×
3313
        StelSkyDrawer *skyDrawer = core->getSkyDrawer();
×
3314
        if (on)
×
3315
        {
3316
                Ocular * ocular = oculars[selectedOcularIndex];
×
3317
                Telescope * telescope = Q_NULLPTR;
×
3318
                if (!ocular->isBinoculars())
×
3319
                {
3320
                        telescope = telescopes[selectedTelescopeIndex];
×
3321
                }
3322
                disconnect(skyDrawer, SIGNAL(customStarMagLimitChanged(double)), this, SLOT(setMagLimitStarsOcularsManual(double))); // keep the old manual value in config.
×
3323
                double limitMag = computeLimitMagnitude(ocular, telescope);
×
3324
                // TODO: Is it really good to apply the star formula to DSO?
3325
                skyDrawer->setFlagNebulaMagnitudeLimit(true);
×
3326
                skyDrawer->setCustomNebulaMagnitudeLimit(limitMag);
×
3327
                skyDrawer->setFlagStarMagnitudeLimit(true);
×
3328
                skyDrawer->setCustomStarMagnitudeLimit(limitMag);
×
3329
        }
3330
        else
3331
        {
3332
                connect(skyDrawer, SIGNAL(customStarMagLimitChanged(double)), this, SLOT(setMagLimitStarsOcularsManual(double)));
×
3333
                skyDrawer->setCustomStarMagnitudeLimit(magLimitStarsOculars);
×
3334
                skyDrawer->setFlagStarMagnitudeLimit(flagLimitStarsOculars);
×
3335
        }
3336
}
3337

3338
// Handle switching the main program's star limitation flag
3339
void Oculars::handleStarMagLimitToggle(bool on)
×
3340
{
3341
        if (!flagShowOculars)
×
3342
                return;
×
3343

3344
        flagLimitStarsOculars=on;
×
3345
        // It only makes sense to switch off the auto-limit when we switch off the limit.
3346
        if (!on)
×
3347
        {
3348
                setFlagAutoLimitMagnitude(false);
×
3349
        }
3350
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc