pulsatingscience.cpp 17.4 KB
Newer Older
Oliver Bock's avatar
Oliver Bock committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/******************************************************************************
 *   Copyright (C) 2008 by Oliver Bock                                        *
 *   oliver.bock[AT]aei.mpg.de                                                *
 *                                                                            *
 *   This file is part of PulsatingScience.                                   *
 *                                                                            *
 *   PulsatingScience is free software: you can redistribute it and/or modify *
 *   it under the terms of the GNU General Public License as published        *
 *   by the Free Software Foundation, version 3 of the License.               *
 *                                                                            *
 *   PulsatingScience is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of           *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             *
 *   GNU General Public License for more details.                             *
 *                                                                            *
 *   You should have received a copy of the GNU General Public License        *
 *   along with PulsatingScience. If not, see <http://www.gnu.org/licenses/>. *
 *                                                                            *
 ******************************************************************************/

#include "pulsatingscience.h"
22
23
#include <QSettings>

Oliver Bock's avatar
Oliver Bock committed
24

25
26
27
28
#ifdef __APPLE__
#include "/System/Library/Frameworks/Carbon.framework/Versions/A/Headers/Carbon.h"
#endif

Oliver Bock's avatar
Oliver Bock committed
29
30
PulsatingScience::PulsatingScience(QWidget *parent) : QMainWindow(parent)
{
31
    ui.setupUi(this);
32

33
34
35
36
    QAction* animControl = ui.dockAnimControl->toggleViewAction();
    animControl->setStatusTip(tr("Toggle the animation control visibility"));
    animControl->setShortcut(QKeySequence(tr("Alt+A")));
    ui.menuView->addAction(animControl);
37

38
39
40
41
#ifdef __APPLE__
    ui.actionMenu_bar->setEnabled(false);
#endif

42
43
44
45
46
47
48
49
    // inital status (based on GUI)
    m_permanentOrbits = ui.actionPermanent_orbits->isChecked();
    m_rotationAxesVisible = ui.actionRotationAxes->isChecked();
    m_menuBarVisible = ui.actionMenu_bar->isChecked();
    m_statusBarVisible = ui.actionStatus_bar->isChecked();
    m_animControlVisible = true;
    m_animControlFloating = ui.dockAnimControl->isFloating();
    m_hiddenDemoModeActivated = false;
50

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    // register alternate shortcuts (will be enabled when menu is hidden)
    m_runShortcut = new QShortcut(ui.actionRun->shortcut(), this);
    m_runShortcut->setEnabled(false);
    m_pauseShortcut = new QShortcut(ui.actionPause->shortcut(), this);
    m_pauseShortcut->setEnabled(false);
    m_stopShortcut = new QShortcut(ui.actionStop->shortcut(), this);
    m_stopShortcut->setEnabled(false);
    m_permanentOrbitsShortcut = new QShortcut(ui.actionPermanent_orbits->shortcut(), this);
    m_permanentOrbitsShortcut->setEnabled(false);
    m_rotationAxesShortcut = new QShortcut(ui.actionRotationAxes->shortcut(), this);
    m_rotationAxesShortcut->setEnabled(false);
    m_menuBarShortcut = new QShortcut(ui.actionMenu_bar->shortcut(), this);
    m_menuBarShortcut->setEnabled(false);
    m_fullscreenShortcut = new QShortcut(ui.actionFullscreen->shortcut(), this);
    m_fullscreenShortcut->setEnabled(false);
66

67
68
    // register "hidden" demo mode shortcut for IYA2009 exhibition
    m_hiddenShortcut = new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::ALT + Qt::Key_D, this);
Oliver Bock's avatar
Oliver Bock committed
69

70
71
72
    // establish object communications
    connect(ui.pushRun, SIGNAL(clicked()),
            ui.pulsarGlWidget, SLOT(runAnimation()));
73

74
75
    connect(ui.actionRun, SIGNAL(triggered()),
            ui.pulsarGlWidget, SLOT(runAnimation()));
76

77
78
    connect(ui.actionRun, SIGNAL(triggered()),
            this, SLOT(on_pushRun_clicked()));
79

80
81
    connect(ui.pushPause, SIGNAL(clicked()),
            ui.pulsarGlWidget, SLOT(pauseAnimation()));
82

83
84
    connect(ui.actionPause, SIGNAL(triggered()),
            ui.pulsarGlWidget, SLOT(pauseAnimation()));
85

86
87
    connect(ui.actionPause, SIGNAL(triggered()),
            this, SLOT(on_pushPause_clicked()));
88

89
90
    connect(ui.pushStop, SIGNAL(clicked()),
            ui.pulsarGlWidget, SLOT(stopAnimation()));
91

92
93
    connect(ui.actionStop, SIGNAL(triggered()),
            ui.pulsarGlWidget, SLOT(stopAnimation()));
94

95
96
    connect(ui.actionStop, SIGNAL(triggered()),
            this, SLOT(on_pushStop_clicked()));
97

98
99
    connect(ui.actionPermanent_orbits, SIGNAL(toggled(bool)),
            ui.pulsarGlWidget, SLOT(showOrbits(bool)));
100

101
102
    connect(ui.actionRotationAxes, SIGNAL(toggled(bool)),
            ui.pulsarGlWidget, SLOT(showRotationAxes(bool)));
Oliver Bock's avatar
Oliver Bock committed
103

104
105
    connect(ui.pulsarGlWidget, SIGNAL(pulsarSemiMajorAxisUpdated(double)),
            this, SLOT(updatePulsarSemiMajorAxisValue(double)));
Oliver Bock's avatar
Oliver Bock committed
106

107
108
    connect(ui.pulsarGlWidget, SIGNAL(pulsarAnimationStep(double)),
            ui.pulseScopeWidget, SLOT(setMarker(double)), Qt::DirectConnection);
Oliver Bock's avatar
Oliver Bock committed
109

110
111
    connect(ui.pulsarGlWidget, SIGNAL(pulseProfileUpdated(const QVector<double>&)),
            ui.pulseScopeWidget, SLOT(drawCurve(const QVector<double>&)), Qt::DirectConnection);
Oliver Bock's avatar
Oliver Bock committed
112

113
114
    connect(m_hiddenShortcut, SIGNAL(activated()),
            this, SLOT(toggleHiddenDemoMode()));
115
116
117
118
119
120
121
122
123
124

    // restore previously saved window and splitter layout
    QCoreApplication::setOrganizationName("Max-Planck-Insitut für Gravitationsphysik");
    QCoreApplication::setOrganizationDomain("aei.mpg.de");
    QCoreApplication::setApplicationName("Pulsating Science");
    QSettings settings;

    restoreGeometry(settings.value("windowGeometry").toByteArray());
    restoreState(settings.value("windowState").toByteArray());
    ui.splitter->restoreState(settings.value("splitterSizes").toByteArray());
Oliver Bock's avatar
Oliver Bock committed
125
126
127
128
}

PulsatingScience::~PulsatingScience()
{
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
    if(m_runShortcut) {
        m_runShortcut->disconnect();
        delete m_runShortcut;
    }

    if(m_pauseShortcut) {
        m_pauseShortcut->disconnect();
        delete m_pauseShortcut;
    }

    if(m_stopShortcut) {
        m_stopShortcut->disconnect();
        delete m_stopShortcut;
    }

    if(m_permanentOrbitsShortcut) {
        m_permanentOrbitsShortcut->disconnect();
        delete m_permanentOrbitsShortcut;
    }

    if(m_rotationAxesShortcut) {
        m_rotationAxesShortcut->disconnect();
        delete m_rotationAxesShortcut;
    }

    if(m_menuBarShortcut) {
        m_menuBarShortcut->disconnect();
        delete m_menuBarShortcut;
    }

    if(m_fullscreenShortcut) {
        m_fullscreenShortcut->disconnect();
        delete m_fullscreenShortcut;
    }

    if(m_hiddenShortcut) {
        m_hiddenShortcut->disconnect();
        delete m_hiddenShortcut;
    }
Oliver Bock's avatar
Oliver Bock committed
168
169
170
171
172
}

void PulsatingScience::closeEvent(QCloseEvent *event)
{
    if(m_hiddenDemoModeActivated) {
173
        event->ignore();
Oliver Bock's avatar
Oliver Bock committed
174
175
    }
    else {
Oliver Bock's avatar
Oliver Bock committed
176
        // save window and splitter layout
177
178
179
180
181
        QSettings settings;
        settings.setValue("windowGeometry", saveGeometry());
        settings.setValue("windowState", saveState());
        settings.setValue("splitterSizes", ui.splitter->saveState());

Oliver Bock's avatar
Oliver Bock committed
182
183
        event->accept();
    }
Oliver Bock's avatar
Oliver Bock committed
184
}
185

Oliver Bock's avatar
Oliver Bock committed
186
187
void PulsatingScience::on_pushRun_clicked()
{
188
189
190
191
192
193
194
195
196
197
    if(ui.pushRun->isEnabled()) {
        ui.pushRun->setEnabled(false);
        ui.pushPause->setEnabled(true);
        ui.pushStop->setEnabled(true);
    }
    else {
        ui.pushRun->setEnabled(true);
        ui.pushPause->setEnabled(false);
        ui.pushStop->setEnabled(false);
    }
Oliver Bock's avatar
Oliver Bock committed
198
199
200
201
}

void PulsatingScience::on_pushPause_clicked()
{
202
203
204
    ui.pushRun->setEnabled(true);
    ui.pushPause->setEnabled(false);
    ui.pushStop->setEnabled(true);
Oliver Bock's avatar
Oliver Bock committed
205
206
207
208
}

void PulsatingScience::on_pushStop_clicked()
{
209
210
211
    ui.pushRun->setEnabled(true);
    ui.pushPause->setEnabled(false);
    ui.pushStop->setEnabled(false);
Oliver Bock's avatar
Oliver Bock committed
212
213
}

Oliver Bock's avatar
Oliver Bock committed
214
215
void PulsatingScience::on_radioCompanionWD_toggled(bool checked)
{
216
217
218
219
    if(checked) {
        ui.pulsarGlWidget->setCompanionMass(0.6);
        ui.lcdCompanionMass->display(QString::number(0.6, 'f', 1));
    }
Oliver Bock's avatar
Oliver Bock committed
220
221
222
223
}

void PulsatingScience::on_radioCompanionSun_toggled(bool checked)
{
224
225
226
227
    if(checked) {
        ui.pulsarGlWidget->setCompanionMass(1.0);
        ui.lcdCompanionMass->display(QString::number(1.0, 'f', 1));
    }
Oliver Bock's avatar
Oliver Bock committed
228
229
230
231
}

void PulsatingScience::on_radioCompanionNS_toggled(bool checked)
{
232
233
234
235
    if(checked) {
        ui.pulsarGlWidget->setCompanionMass(1.4);
        ui.lcdCompanionMass->display(QString::number(1.4, 'f', 1));
    }
Oliver Bock's avatar
Oliver Bock committed
236
237
238
239
}

void PulsatingScience::on_sliderPulsarMass_valueChanged(int value)
{
240
241
    ui.pulsarGlWidget->setPulsarMass(value * 0.1);
    ui.lcdPulsarMass->display(QString::number(value * 0.1, 'f', 1));
Oliver Bock's avatar
Oliver Bock committed
242
243
}

Oliver Bock's avatar
Oliver Bock committed
244
void PulsatingScience::on_sliderPulsarSpinFrequency_valueChanged(int value)
245
{
246
247
    ui.pulsarGlWidget->setPulsarSpinFrequency(value * 0.1);
    ui.lcdPulsarSpinFrequency->display(QString::number(value * 0.1, 'f', 1));
Oliver Bock's avatar
Oliver Bock committed
248
249
}

250
251
void PulsatingScience::on_sliderPulsarSpinAxisInclination_valueChanged(int value)
{
252
253
    ui.pulsarGlWidget->setPulsarSpinAxisInclination(value);
    ui.lcdPulsarSpinAxisInclination->display(QString::number(value));
254
255
}

256
257
void PulsatingScience::on_sliderPulsarMagneticAxisInclination_valueChanged(int value)
{
258
259
    ui.pulsarGlWidget->setPulsarMagneticAxisInclination(value);
    ui.lcdPulsarMagneticAxisInclination->display(QString::number(value));
260
261
}

Oliver Bock's avatar
Oliver Bock committed
262
void PulsatingScience::on_sliderPulsarSemiMajorAxis_valueChanged(int value)
Oliver Bock's avatar
Oliver Bock committed
263
{
264
265
266
    ui.pulsarGlWidget->setPulsarSemiMajorAxis(value * 0.001);
    ui.lcdPulsarSemiMajorAxis->display(QString::number(value * 0.001, 'f', 1));
    ui.lcdPulsarSemiMajorAxis->setStyleSheet("color: black");
267
}
Oliver Bock's avatar
Oliver Bock committed
268

269
void PulsatingScience::permanentOrbitsToggled() {
270
271
272
273
274
275
276
277
    if(m_permanentOrbits) {
        on_actionPermanent_orbits_toggled(false);
        ui.actionPermanent_orbits->setChecked(false);
    }
    else {
        on_actionPermanent_orbits_toggled(true);
        ui.actionPermanent_orbits->setChecked(true);
    }
278
279
280
}

void PulsatingScience::on_actionPermanent_orbits_toggled(bool checked) {
281
    m_permanentOrbits = checked;
282
283
}

284
void PulsatingScience::rotationAxesToggled() {
285
286
287
288
289
290
291
292
    if(m_rotationAxesVisible) {
        on_actionRotationAxes_toggled(false);
        ui.actionRotationAxes->setChecked(false);
    }
    else {
        on_actionRotationAxes_toggled(true);
        ui.actionRotationAxes->setChecked(true);
    }
293
294
295
}

void PulsatingScience::on_actionRotationAxes_toggled(bool checked) {
296
    m_rotationAxesVisible = checked;
297
298
299
300
}

void PulsatingScience::menuBarToggled()
{
301
302
303
304
305
306
307
308
309
    if(ui.menuBar->isVisible()) {
        on_actionMenu_bar_toggled(false);
        ui.actionMenu_bar->setChecked(false);
    }
    else if(!ui.actionFullscreen->isChecked()) {
        // allow menu bar only when NOT in fullscreen mode
        on_actionMenu_bar_toggled(true);
        ui.actionMenu_bar->setChecked(true);
    }
310
311
}

Oliver Bock's avatar
Oliver Bock committed
312
313
void PulsatingScience::on_actionMenu_bar_toggled(bool checked)
{
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
    if(checked) {
        ui.menuBar->show();
        m_menuBarVisible = true;

        // deactivate alternate shortcuts
        m_runShortcut->disconnect();
        m_runShortcut->setEnabled(false);
        m_pauseShortcut->disconnect();
        m_pauseShortcut->setEnabled(false);
        m_stopShortcut->disconnect();
        m_stopShortcut->setEnabled(false);
        m_permanentOrbitsShortcut->disconnect();
        m_permanentOrbitsShortcut->setEnabled(false);
        m_rotationAxesShortcut->disconnect();
        m_rotationAxesShortcut->setEnabled(false);
        m_fullscreenShortcut->disconnect();
        m_fullscreenShortcut->setEnabled(false);
        m_menuBarShortcut->disconnect();
        m_menuBarShortcut->setEnabled(false);
    }
    else {
        ui.menuBar->hide();
        m_menuBarVisible = false;

        // activate alternate shortcuts
        m_runShortcut->setEnabled(true);
        connect(m_runShortcut, SIGNAL(activated()), ui.pulsarGlWidget, SLOT(runAnimation()));
        m_pauseShortcut->setEnabled(true);
        connect(m_pauseShortcut, SIGNAL(activated()), ui.pulsarGlWidget, SLOT(pauseAnimation()));
        m_stopShortcut->setEnabled(true);
        connect(m_stopShortcut, SIGNAL(activated()), ui.pulsarGlWidget, SLOT(stopAnimation()));
        m_permanentOrbitsShortcut->setEnabled(true);
        connect(m_permanentOrbitsShortcut, SIGNAL(activated()), this, SLOT(permanentOrbitsToggled()));
        m_rotationAxesShortcut->setEnabled(true);
        connect(m_rotationAxesShortcut, SIGNAL(activated()), this, SLOT(rotationAxesToggled()));
        m_fullscreenShortcut->setEnabled(true);
        connect(m_fullscreenShortcut, SIGNAL(activated()), this, SLOT(fullscreenToggled()));
        m_menuBarShortcut->setEnabled(true);
        connect(m_menuBarShortcut, SIGNAL(activated()), this, SLOT(menuBarToggled()));
    }
354
355
356
357
}

void PulsatingScience::fullscreenToggled()
{
358
359
360
361
362
363
364
365
    if((windowState() & Qt::WindowFullScreen) > 0) {
        on_actionFullscreen_toggled(false);
        ui.actionFullscreen->setChecked(false);
    }
    else {
        on_actionFullscreen_toggled(true);
        ui.actionFullscreen->setChecked(true);
    }
366
367
368
369
}

void PulsatingScience::on_actionFullscreen_toggled(bool checked)
{
370
371
372
373
    if(checked) {
        window()->setWindowState(windowState() | Qt::WindowFullScreen);
        // assuming text being black
        setBackgroundRole(QPalette::Text);
374
#ifndef __APPLE__
375
376
377
378
379
        if(m_menuBarVisible) {
            on_actionMenu_bar_toggled(false);
            // keep visibility setting
            m_menuBarVisible = true;
        }
380
#endif
381
382
383
384
385
386
387
388
389
390
        if(m_statusBarVisible) ui.statusbar->hide();
        if(m_animControlVisible && !m_animControlFloating) {
            ui.dockAnimControl->hide();
            // keep visibility setting
            m_animControlVisible = true;
        }
    }
    else {
        window()->setWindowState(windowState() & ~Qt::WindowFullScreen);
        setBackgroundRole(QPalette::Window);
391
#ifndef __APPLE__
392
        if(m_menuBarVisible) on_actionMenu_bar_toggled(true);
393
394
#endif
        if(m_statusBarVisible) ui.statusbar->show();
395
396
        if(m_animControlVisible && !m_animControlFloating) ui.dockAnimControl->show();
    }
Oliver Bock's avatar
Oliver Bock committed
397
398
399
400
}

void PulsatingScience::on_actionStatus_bar_toggled(bool checked)
{
401
402
403
404
405
406
407
408
    if(checked) {
        ui.statusbar->show();
        m_statusBarVisible = true;
    }
    else {
        ui.statusbar->hide();
        m_statusBarVisible = false;
    }
409
410
411
}

void PulsatingScience::on_dockAnimControl_visibilityChanged(bool visible) {
412
    m_animControlVisible = visible;
413
414
415
}

void PulsatingScience::on_dockAnimControl_topLevelChanged(bool topLevel) {
416
    m_animControlFloating = topLevel;
Oliver Bock's avatar
Oliver Bock committed
417
}
Oliver Bock's avatar
Oliver Bock committed
418

419
void PulsatingScience::on_actionHelp_triggered()
420
{
421
422
    PulsatingScienceHelp help(this);
    help.exec();
423
424
}

425
void PulsatingScience::on_actionWebsite_triggered()
Oliver Bock's avatar
Oliver Bock committed
426
{
427
    QDesktopServices::openUrl(QUrl("http://www.aei.mpg.de"));
Oliver Bock's avatar
Oliver Bock committed
428
429
}

430
void PulsatingScience::on_actionAbout_triggered()
Oliver Bock's avatar
Oliver Bock committed
431
{
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
    QString content = "<b>%1</b><br>"
            "%2<br><br>"
            "%3: Oliver Bock, Benjamin Knispel<br><br>"
            "%4<br>"
            "(%5 ESO/IDA/Danish 1.5 m/R.Gendler, J-E. Ovaldsen, C. Th&ouml;ne, C. Feron)<br><br>"
            "%6: GNU General Public License (Version 3)<br><br>"
            "Copyright &copy; 2009 Max-Planck-Institut f&uuml;r Gravitationsphysik";

    content = content.arg(
                tr("Pulsating Science"),
                tr("International Year of Astronomy 2009"),
                tr("Authors"),
                tr("Background image: The Carina Nebula"),
                tr("Courtesy of"),
                tr("License"));

    QMessageBox::about(this, tr("About \"Pulsating Science\""), content);
Oliver Bock's avatar
Oliver Bock committed
449
}
Oliver Bock's avatar
Oliver Bock committed
450
451
452

void PulsatingScience::updatePulsarSemiMajorAxisValue(double value)
{
453
454
455
456
457
458
459
460
461
462
463
    ui.sliderPulsarSemiMajorAxis->setValue(qRound(value * 1000.0));

    if((int)value <= 1 || (int)value >= 20) {
        if((int)value < 1 || (int)value > 20) {
            ui.lcdPulsarSemiMajorAxis->setStyleSheet("color: red");
        }
        else {
            ui.lcdPulsarSemiMajorAxis->setStyleSheet("color: black");
        }
        ui.lcdPulsarSemiMajorAxis->display(QString::number(value, 'f', 1));
    }
Oliver Bock's avatar
Oliver Bock committed
464
}
Oliver Bock's avatar
Oliver Bock committed
465
466
467

void PulsatingScience::toggleHiddenDemoMode()
{
468
    if(m_hiddenDemoModeActivated) {
469
#ifdef __APPLE__
470
471
472
473
474
475
        // show Menubar & Dock
        // unavailable in Qt 4.6: SetSystemUIMode(kUIModeNormal, 0);
        window()->setWindowFlags(windowFlags()
                                 & ~Qt::FramelessWindowHint
                                 & ~Qt::WindowStaysOnTopHint);
        window()->showNormal();
476
#endif
477
478
479
480
481
482
483
484
485
        on_actionMenu_bar_toggled(true);
        ui.actionMenu_bar->setChecked(true);
        window()->setWindowState(windowState() & ~Qt::WindowFullScreen);
        ui.dockAnimControl->setFeatures(QDockWidget::DockWidgetClosable
                                        | QDockWidget::DockWidgetMovable
                                        | QDockWidget::DockWidgetFloatable);
        m_hiddenDemoModeActivated = false;
    }
    else {
486
#ifdef __APPLE__
487
        // hide Menubar & Dock
Oliver Bock's avatar
Oliver Bock committed
488
        // unavailable in Qt 4.6: SetSystemUIMode(kUIModeAllHidden, 0);
489
490
491
492
493
494
495
        // don't ever ask me why this works _only_ in exactly this order on the Mac
        window()->setWindowFlags(windowFlags()
                                 | Qt::FramelessWindowHint
                                 | Qt::WindowStaysOnTopHint);
        window()->showMaximized();
        // might be needed to remove the resize handle on some systems
        // window()->setFixedSize(width(), height());
496
#endif
497
498
499
500
501
502
        on_actionMenu_bar_toggled(false);
        ui.actionMenu_bar->setChecked(false);
        window()->setWindowState(windowState() | Qt::WindowFullScreen);
        ui.dockAnimControl->setFeatures(QDockWidget::NoDockWidgetFeatures);
        m_hiddenDemoModeActivated = true;
    }
Oliver Bock's avatar
Oliver Bock committed
503
}