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
}