pulsatingscience.cpp 17.9 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
    m_fullscreenESCShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
    m_fullscreenESCShortcut->setEnabled(false);
68

69
70
    // 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
71

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

76
77
    connect(ui.actionRun, SIGNAL(triggered()),
            ui.pulsarGlWidget, SLOT(runAnimation()));
78

79
80
    connect(ui.actionRun, SIGNAL(triggered()),
            this, SLOT(on_pushRun_clicked()));
81

82
83
    connect(ui.pushPause, SIGNAL(clicked()),
            ui.pulsarGlWidget, SLOT(pauseAnimation()));
84

85
86
    connect(ui.actionPause, SIGNAL(triggered()),
            ui.pulsarGlWidget, SLOT(pauseAnimation()));
87

88
89
    connect(ui.actionPause, SIGNAL(triggered()),
            this, SLOT(on_pushPause_clicked()));
90

91
92
    connect(ui.pushStop, SIGNAL(clicked()),
            ui.pulsarGlWidget, SLOT(stopAnimation()));
93

94
95
    connect(ui.actionStop, SIGNAL(triggered()),
            ui.pulsarGlWidget, SLOT(stopAnimation()));
96

97
98
    connect(ui.actionStop, SIGNAL(triggered()),
            this, SLOT(on_pushStop_clicked()));
99

100
101
    connect(ui.actionPermanent_orbits, SIGNAL(toggled(bool)),
            ui.pulsarGlWidget, SLOT(showOrbits(bool)));
102

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

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

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

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

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

    // 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
127
128
129
130
}

PulsatingScience::~PulsatingScience()
{
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
    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;
    }

166
167
168
169
170
    if(m_fullscreenESCShortcut) {
        m_fullscreenESCShortcut->disconnect();
        delete m_fullscreenESCShortcut;
    }

171
172
173
174
    if(m_hiddenShortcut) {
        m_hiddenShortcut->disconnect();
        delete m_hiddenShortcut;
    }
Oliver Bock's avatar
Oliver Bock committed
175
176
177
178
179
}

void PulsatingScience::closeEvent(QCloseEvent *event)
{
    if(m_hiddenDemoModeActivated) {
180
        event->ignore();
Oliver Bock's avatar
Oliver Bock committed
181
182
    }
    else {
Oliver Bock's avatar
Oliver Bock committed
183
        // save window and splitter layout
184
185
186
187
188
        QSettings settings;
        settings.setValue("windowGeometry", saveGeometry());
        settings.setValue("windowState", saveState());
        settings.setValue("splitterSizes", ui.splitter->saveState());

Oliver Bock's avatar
Oliver Bock committed
189
190
        event->accept();
    }
Oliver Bock's avatar
Oliver Bock committed
191
}
192

Oliver Bock's avatar
Oliver Bock committed
193
194
void PulsatingScience::on_pushRun_clicked()
{
195
196
197
198
199
200
201
202
203
204
    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
205
206
207
208
}

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

void PulsatingScience::on_pushStop_clicked()
{
216
217
218
    ui.pushRun->setEnabled(true);
    ui.pushPause->setEnabled(false);
    ui.pushStop->setEnabled(false);
Oliver Bock's avatar
Oliver Bock committed
219
220
}

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

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

void PulsatingScience::on_radioCompanionNS_toggled(bool checked)
{
239
240
241
242
    if(checked) {
        ui.pulsarGlWidget->setCompanionMass(1.4);
        ui.lcdCompanionMass->display(QString::number(1.4, 'f', 1));
    }
Oliver Bock's avatar
Oliver Bock committed
243
244
245
246
}

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

Oliver Bock's avatar
Oliver Bock committed
251
void PulsatingScience::on_sliderPulsarSpinFrequency_valueChanged(int value)
252
{
253
254
    ui.pulsarGlWidget->setPulsarSpinFrequency(value * 0.1);
    ui.lcdPulsarSpinFrequency->display(QString::number(value * 0.1, 'f', 1));
Oliver Bock's avatar
Oliver Bock committed
255
256
}

257
258
void PulsatingScience::on_sliderPulsarSpinAxisInclination_valueChanged(int value)
{
259
260
    ui.pulsarGlWidget->setPulsarSpinAxisInclination(value);
    ui.lcdPulsarSpinAxisInclination->display(QString::number(value));
261
262
}

263
264
void PulsatingScience::on_sliderPulsarMagneticAxisInclination_valueChanged(int value)
{
265
266
    ui.pulsarGlWidget->setPulsarMagneticAxisInclination(value);
    ui.lcdPulsarMagneticAxisInclination->display(QString::number(value));
267
268
}

Oliver Bock's avatar
Oliver Bock committed
269
void PulsatingScience::on_sliderPulsarSemiMajorAxis_valueChanged(int value)
Oliver Bock's avatar
Oliver Bock committed
270
{
271
272
273
    ui.pulsarGlWidget->setPulsarSemiMajorAxis(value * 0.001);
    ui.lcdPulsarSemiMajorAxis->display(QString::number(value * 0.001, 'f', 1));
    ui.lcdPulsarSemiMajorAxis->setStyleSheet("color: black");
274
}
Oliver Bock's avatar
Oliver Bock committed
275

276
void PulsatingScience::permanentOrbitsToggled() {
277
278
279
280
281
282
283
284
    if(m_permanentOrbits) {
        on_actionPermanent_orbits_toggled(false);
        ui.actionPermanent_orbits->setChecked(false);
    }
    else {
        on_actionPermanent_orbits_toggled(true);
        ui.actionPermanent_orbits->setChecked(true);
    }
285
286
287
}

void PulsatingScience::on_actionPermanent_orbits_toggled(bool checked) {
288
    m_permanentOrbits = checked;
289
290
}

291
void PulsatingScience::rotationAxesToggled() {
292
293
294
295
296
297
298
299
    if(m_rotationAxesVisible) {
        on_actionRotationAxes_toggled(false);
        ui.actionRotationAxes->setChecked(false);
    }
    else {
        on_actionRotationAxes_toggled(true);
        ui.actionRotationAxes->setChecked(true);
    }
300
301
302
}

void PulsatingScience::on_actionRotationAxes_toggled(bool checked) {
303
    m_rotationAxesVisible = checked;
304
305
306
307
}

void PulsatingScience::menuBarToggled()
{
308
309
310
311
312
313
314
315
316
    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);
    }
317
318
}

Oliver Bock's avatar
Oliver Bock committed
319
320
void PulsatingScience::on_actionMenu_bar_toggled(bool checked)
{
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
354
355
356
357
358
359
360
    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()));
    }
361
362
363
364
}

void PulsatingScience::fullscreenToggled()
{
365
366
367
368
369
370
371
372
    if((windowState() & Qt::WindowFullScreen) > 0) {
        on_actionFullscreen_toggled(false);
        ui.actionFullscreen->setChecked(false);
    }
    else {
        on_actionFullscreen_toggled(true);
        ui.actionFullscreen->setChecked(true);
    }
373
374
375
376
}

void PulsatingScience::on_actionFullscreen_toggled(bool checked)
{
377
378
379
380
    if(checked) {
        window()->setWindowState(windowState() | Qt::WindowFullScreen);
        // assuming text being black
        setBackgroundRole(QPalette::Text);
381
#ifndef __APPLE__
382
383
384
385
386
        if(m_menuBarVisible) {
            on_actionMenu_bar_toggled(false);
            // keep visibility setting
            m_menuBarVisible = true;
        }
387
#endif
388
389
390
391
392
393
        if(m_statusBarVisible) ui.statusbar->hide();
        if(m_animControlVisible && !m_animControlFloating) {
            ui.dockAnimControl->hide();
            // keep visibility setting
            m_animControlVisible = true;
        }
394
395
396

        m_fullscreenESCShortcut->setEnabled(true);
        connect(m_fullscreenESCShortcut, SIGNAL(activated()), this, SLOT(fullscreenToggled()));
397
398
399
400
    }
    else {
        window()->setWindowState(windowState() & ~Qt::WindowFullScreen);
        setBackgroundRole(QPalette::Window);
401
#ifndef __APPLE__
402
        if(m_menuBarVisible) on_actionMenu_bar_toggled(true);
403
404
#endif
        if(m_statusBarVisible) ui.statusbar->show();
405
        if(m_animControlVisible && !m_animControlFloating) ui.dockAnimControl->show();
406
407
408

        m_fullscreenESCShortcut->disconnect();
        m_fullscreenESCShortcut->setEnabled(false);
409
    }
Oliver Bock's avatar
Oliver Bock committed
410
411
412
413
}

void PulsatingScience::on_actionStatus_bar_toggled(bool checked)
{
414
415
416
417
418
419
420
421
    if(checked) {
        ui.statusbar->show();
        m_statusBarVisible = true;
    }
    else {
        ui.statusbar->hide();
        m_statusBarVisible = false;
    }
422
423
424
}

void PulsatingScience::on_dockAnimControl_visibilityChanged(bool visible) {
425
    m_animControlVisible = visible;
426
427
428
}

void PulsatingScience::on_dockAnimControl_topLevelChanged(bool topLevel) {
429
    m_animControlFloating = topLevel;
Oliver Bock's avatar
Oliver Bock committed
430
}
Oliver Bock's avatar
Oliver Bock committed
431

432
void PulsatingScience::on_actionHelp_triggered()
433
{
434
435
    PulsatingScienceHelp help(this);
    help.exec();
436
437
}

438
void PulsatingScience::on_actionWebsite_triggered()
Oliver Bock's avatar
Oliver Bock committed
439
{
440
    QDesktopServices::openUrl(QUrl("http://www.aei.mpg.de"));
Oliver Bock's avatar
Oliver Bock committed
441
442
}

443
void PulsatingScience::on_actionAbout_triggered()
Oliver Bock's avatar
Oliver Bock committed
444
{
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
    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
462
}
Oliver Bock's avatar
Oliver Bock committed
463
464
465

void PulsatingScience::updatePulsarSemiMajorAxisValue(double value)
{
466
467
468
469
470
471
472
473
474
475
476
    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
477
}
Oliver Bock's avatar
Oliver Bock committed
478
479
480

void PulsatingScience::toggleHiddenDemoMode()
{
481
    if(m_hiddenDemoModeActivated) {
482
#ifdef __APPLE__
483
484
485
486
487
488
        // show Menubar & Dock
        // unavailable in Qt 4.6: SetSystemUIMode(kUIModeNormal, 0);
        window()->setWindowFlags(windowFlags()
                                 & ~Qt::FramelessWindowHint
                                 & ~Qt::WindowStaysOnTopHint);
        window()->showNormal();
489
#endif
490
491
492
493
494
495
496
497
498
        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 {
499
#ifdef __APPLE__
500
        // hide Menubar & Dock
Oliver Bock's avatar
Oliver Bock committed
501
        // unavailable in Qt 4.6: SetSystemUIMode(kUIModeAllHidden, 0);
502
503
504
505
506
507
508
        // 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());
509
#endif
510
511
512
513
514
515
        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
516
}