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 {
176 177 178 179 180 181
        // save splitter layout
        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
}