/****************************************************************************** * 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 . * * * ******************************************************************************/ #include "pulsatingscience.h" #ifdef __APPLE__ #include "/System/Library/Frameworks/Carbon.framework/Versions/A/Headers/Carbon.h" #endif PulsatingScience::PulsatingScience(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); QAction* animControl = ui.dockAnimControl->toggleViewAction(); animControl->setStatusTip(tr("Toggle the animation control visibility")); animControl->setShortcut(QKeySequence(tr("Alt+A"))); ui.menuView->addAction(animControl); #ifdef __APPLE__ ui.actionMenu_bar->setEnabled(false); #endif // 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; // 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); // register "hidden" demo mode shortcut for IYA2009 exhibition m_hiddenShortcut = new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::ALT + Qt::Key_D, this); // establish object communications connect(ui.pushRun, SIGNAL(clicked()), ui.pulsarGlWidget, SLOT(runAnimation())); connect(ui.actionRun, SIGNAL(triggered()), ui.pulsarGlWidget, SLOT(runAnimation())); connect(ui.actionRun, SIGNAL(triggered()), this, SLOT(on_pushRun_clicked())); connect(ui.pushPause, SIGNAL(clicked()), ui.pulsarGlWidget, SLOT(pauseAnimation())); connect(ui.actionPause, SIGNAL(triggered()), ui.pulsarGlWidget, SLOT(pauseAnimation())); connect(ui.actionPause, SIGNAL(triggered()), this, SLOT(on_pushPause_clicked())); connect(ui.pushStop, SIGNAL(clicked()), ui.pulsarGlWidget, SLOT(stopAnimation())); connect(ui.actionStop, SIGNAL(triggered()), ui.pulsarGlWidget, SLOT(stopAnimation())); connect(ui.actionStop, SIGNAL(triggered()), this, SLOT(on_pushStop_clicked())); connect(ui.actionPermanent_orbits, SIGNAL(toggled(bool)), ui.pulsarGlWidget, SLOT(showOrbits(bool))); connect(ui.actionRotationAxes, SIGNAL(toggled(bool)), ui.pulsarGlWidget, SLOT(showRotationAxes(bool))); connect(ui.pulsarGlWidget, SIGNAL(pulsarSemiMajorAxisUpdated(double)), this, SLOT(updatePulsarSemiMajorAxisValue(double))); connect(ui.pulsarGlWidget, SIGNAL(pulsarAnimationStep(double)), ui.pulseScopeWidget, SLOT(setMarker(double)), Qt::DirectConnection); connect(ui.pulsarGlWidget, SIGNAL(pulseProfileUpdated(const QVector&)), ui.pulseScopeWidget, SLOT(drawCurve(const QVector&)), Qt::DirectConnection); connect(m_hiddenShortcut, SIGNAL(activated()), this, SLOT(toggleHiddenDemoMode())); } PulsatingScience::~PulsatingScience() { 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; } } void PulsatingScience::closeEvent(QCloseEvent *event) { if(m_hiddenDemoModeActivated) { event->ignore(); } else { event->accept(); } } void PulsatingScience::on_pushRun_clicked() { 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); } } void PulsatingScience::on_pushPause_clicked() { ui.pushRun->setEnabled(true); ui.pushPause->setEnabled(false); ui.pushStop->setEnabled(true); } void PulsatingScience::on_pushStop_clicked() { ui.pushRun->setEnabled(true); ui.pushPause->setEnabled(false); ui.pushStop->setEnabled(false); } void PulsatingScience::on_radioCompanionWD_toggled(bool checked) { if(checked) { ui.pulsarGlWidget->setCompanionMass(0.6); ui.lcdCompanionMass->display(QString::number(0.6, 'f', 1)); } } void PulsatingScience::on_radioCompanionSun_toggled(bool checked) { if(checked) { ui.pulsarGlWidget->setCompanionMass(1.0); ui.lcdCompanionMass->display(QString::number(1.0, 'f', 1)); } } void PulsatingScience::on_radioCompanionNS_toggled(bool checked) { if(checked) { ui.pulsarGlWidget->setCompanionMass(1.4); ui.lcdCompanionMass->display(QString::number(1.4, 'f', 1)); } } void PulsatingScience::on_sliderPulsarMass_valueChanged(int value) { ui.pulsarGlWidget->setPulsarMass(value * 0.1); ui.lcdPulsarMass->display(QString::number(value * 0.1, 'f', 1)); } void PulsatingScience::on_sliderPulsarSpinFrequency_valueChanged(int value) { ui.pulsarGlWidget->setPulsarSpinFrequency(value * 0.1); ui.lcdPulsarSpinFrequency->display(QString::number(value * 0.1, 'f', 1)); } void PulsatingScience::on_sliderPulsarSpinAxisInclination_valueChanged(int value) { ui.pulsarGlWidget->setPulsarSpinAxisInclination(value); ui.lcdPulsarSpinAxisInclination->display(QString::number(value)); } void PulsatingScience::on_sliderPulsarMagneticAxisInclination_valueChanged(int value) { ui.pulsarGlWidget->setPulsarMagneticAxisInclination(value); ui.lcdPulsarMagneticAxisInclination->display(QString::number(value)); } void PulsatingScience::on_sliderPulsarSemiMajorAxis_valueChanged(int value) { ui.pulsarGlWidget->setPulsarSemiMajorAxis(value * 0.001); ui.lcdPulsarSemiMajorAxis->display(QString::number(value * 0.001, 'f', 1)); ui.lcdPulsarSemiMajorAxis->setStyleSheet("color: black"); } void PulsatingScience::permanentOrbitsToggled() { if(m_permanentOrbits) { on_actionPermanent_orbits_toggled(false); ui.actionPermanent_orbits->setChecked(false); } else { on_actionPermanent_orbits_toggled(true); ui.actionPermanent_orbits->setChecked(true); } } void PulsatingScience::on_actionPermanent_orbits_toggled(bool checked) { m_permanentOrbits = checked; } void PulsatingScience::rotationAxesToggled() { if(m_rotationAxesVisible) { on_actionRotationAxes_toggled(false); ui.actionRotationAxes->setChecked(false); } else { on_actionRotationAxes_toggled(true); ui.actionRotationAxes->setChecked(true); } } void PulsatingScience::on_actionRotationAxes_toggled(bool checked) { m_rotationAxesVisible = checked; } void PulsatingScience::menuBarToggled() { 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); } } void PulsatingScience::on_actionMenu_bar_toggled(bool checked) { 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())); } } void PulsatingScience::fullscreenToggled() { if((windowState() & Qt::WindowFullScreen) > 0) { on_actionFullscreen_toggled(false); ui.actionFullscreen->setChecked(false); } else { on_actionFullscreen_toggled(true); ui.actionFullscreen->setChecked(true); } } void PulsatingScience::on_actionFullscreen_toggled(bool checked) { if(checked) { window()->setWindowState(windowState() | Qt::WindowFullScreen); // assuming text being black setBackgroundRole(QPalette::Text); #ifndef __APPLE__ if(m_menuBarVisible) { on_actionMenu_bar_toggled(false); // keep visibility setting m_menuBarVisible = true; } #endif 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); #ifndef __APPLE__ if(m_menuBarVisible) on_actionMenu_bar_toggled(true); #endif if(m_statusBarVisible) ui.statusbar->show(); if(m_animControlVisible && !m_animControlFloating) ui.dockAnimControl->show(); } } void PulsatingScience::on_actionStatus_bar_toggled(bool checked) { if(checked) { ui.statusbar->show(); m_statusBarVisible = true; } else { ui.statusbar->hide(); m_statusBarVisible = false; } } void PulsatingScience::on_dockAnimControl_visibilityChanged(bool visible) { m_animControlVisible = visible; } void PulsatingScience::on_dockAnimControl_topLevelChanged(bool topLevel) { m_animControlFloating = topLevel; } void PulsatingScience::on_actionHelp_triggered() { PulsatingScienceHelp help(this); help.exec(); } void PulsatingScience::on_actionWebsite_triggered() { QDesktopServices::openUrl(QUrl("http://www.aei.mpg.de")); } void PulsatingScience::on_actionAbout_triggered() { QString content = "%1
" "%2

" "%3: Oliver Bock, Benjamin Knispel

" "%4
" "(%5 ESO/IDA/Danish 1.5 m/R.Gendler, J-E. Ovaldsen, C. Thöne, C. Feron)

" "%6: GNU General Public License (Version 3)

" "Copyright © 2009 Max-Planck-Institut fü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); } void PulsatingScience::updatePulsarSemiMajorAxisValue(double value) { 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)); } } void PulsatingScience::toggleHiddenDemoMode() { if(m_hiddenDemoModeActivated) { #ifdef __APPLE__ // show Menubar & Dock SetSystemUIMode(kUIModeNormal, 0); window()->setWindowFlags(windowFlags() & ~Qt::FramelessWindowHint & ~Qt::WindowStaysOnTopHint); window()->showNormal(); #endif 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 { #ifdef __APPLE__ // hide Menubar & Dock SetSystemUIMode(kUIModeAllHidden, 0); // don't ever ask my 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()); #endif on_actionMenu_bar_toggled(false); ui.actionMenu_bar->setChecked(false); window()->setWindowState(windowState() | Qt::WindowFullScreen); ui.dockAnimControl->setFeatures(QDockWidget::NoDockWidgetFeatures); m_hiddenDemoModeActivated = true; } }