Select Git revision
test.single.2
Forked from
einsteinathome / libclfft
Source project has a limited visibility.
pulsatingscience.cpp 21.90 KiB
/******************************************************************************
* 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"
#include <QSettings>
#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_pulseFlashesVisible = ui.actionPulseFlashes->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_pulseFlashesShortcut = new QShortcut(ui.actionPulseFlashes->shortcut(), this);
m_pulseFlashesShortcut->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);
m_fullscreenESCShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
m_fullscreenESCShortcut->setEnabled(false);
// register "hidden" demo mode shortcut for IYA2009 exhibition
m_hiddenShortcut = new QShortcut(QKeySequence(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.actionPulseFlashes, SIGNAL(toggled(bool)),
ui.pulsarGlWidget, SLOT(showPulseFlashes(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<double>&)),
ui.pulseScopeWidget, SLOT(drawCurve(const QVector<double>&)), Qt::DirectConnection);
connect(m_hiddenShortcut, SIGNAL(activated()),
this, SLOT(toggleHiddenDemoMode()));
// prepare inactivity timer
saveOrRestoreInitialAnimationSettings();
m_inactivityTimer = new QTimer(this);
connect(m_inactivityTimer, SIGNAL(timeout()), this, SLOT(userInactivityCallback()));
// 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());
// restore view features
ui.actionPermanent_orbits->setChecked(settings.value("viewOrbitalPlanes", m_permanentOrbits).toBool());
ui.actionRotationAxes->setChecked(settings.value("viewRotationAxes", m_rotationAxesVisible).toBool());
ui.actionPulseFlashes->setChecked(settings.value("viewPulseFlashes", m_pulseFlashesVisible).toBool());
}
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_pulseFlashesShortcut) {
m_pulseFlashesShortcut->disconnect();
delete m_pulseFlashesShortcut;
}
if(m_menuBarShortcut) {
m_menuBarShortcut->disconnect();
delete m_menuBarShortcut;
}
if(m_fullscreenShortcut) {
m_fullscreenShortcut->disconnect();
delete m_fullscreenShortcut;
}
if(m_fullscreenESCShortcut) {
m_fullscreenESCShortcut->disconnect();
delete m_fullscreenESCShortcut;
}
if(m_hiddenShortcut) {
m_hiddenShortcut->disconnect();
delete m_hiddenShortcut;
}
if(m_inactivityTimer) {
delete m_inactivityTimer;
}
}
void PulsatingScience::closeEvent(QCloseEvent *event)
{
if(m_hiddenDemoModeActivated) {
event->ignore();
}
else {
// save window and splitter layout
QSettings settings;
settings.setValue("windowGeometry", saveGeometry());
settings.setValue("windowState", saveState());
settings.setValue("splitterSizes", ui.splitter->saveState());
// save view features
settings.setValue("viewOrbitalPlanes", m_permanentOrbits);
settings.setValue("viewRotationAxes", m_rotationAxesVisible);
settings.setValue("viewPulseFlashes", m_pulseFlashesVisible);
event->accept();
}
}
void PulsatingScience::on_pushRun_clicked()
{
ui.pushRun->setEnabled(false);
ui.pushPause->setEnabled(true);
ui.pushStop->setEnabled(true);
}
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::pulseFlashesToggled() {
if(m_pulseFlashesVisible) {
on_actionPulseFlashes_toggled(false);
ui.actionPulseFlashes->setChecked(false);
}
else {
on_actionPulseFlashes_toggled(true);
ui.actionPulseFlashes->setChecked(true);
}
}
void PulsatingScience::on_actionPulseFlashes_toggled(bool checked) {
m_pulseFlashesVisible = 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_pulseFlashesShortcut->disconnect();
m_pulseFlashesShortcut->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_pulseFlashesShortcut->setEnabled(true);
connect(m_pulseFlashesShortcut, SIGNAL(activated()), this, SLOT(pulseFlashesToggled()));
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;
}
m_fullscreenESCShortcut->setEnabled(true);
connect(m_fullscreenESCShortcut, SIGNAL(activated()), this, SLOT(fullscreenToggled()));
}
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();
m_fullscreenESCShortcut->disconnect();
m_fullscreenESCShortcut->setEnabled(false);
}
}
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 = "<b>%1</b><br>"
"%2<br>"
"<br>"
"%3: Oliver Bock<br>"
"%4: Benjamin Knispel<br>"
"<br>"
"%5<br>"
"(%6 ESO/IDA/Danish 1.5m - R.Gendler, J-E. Ovaldsen, C. Thöne, C. Feron)<br>"
"<br>"
"%7: GNU General Public License v3<br>"
"<br>"
"Copyright © 2009-2013 %8";
content = content.arg(
tr("Pulsating Science"),
tr("International Year of Astronomy 2009"),
tr("Author"),
tr("Consultant"),
tr("Background image: The Carina Nebula"),
tr("Courtesy of"),
tr("License"),
tr("Max Planck Institute for Gravitational Physics"));
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__
window()->setWindowFlags(windowFlags()
& ~Qt::FramelessWindowHint
& ~Qt::WindowStaysOnTopHint);
window()->showNormal();
#endif
// show Menubar & Dock
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_inactivityTimer->stop();
m_hiddenDemoModeActivated = false;
}
else {
#ifdef __APPLE__
window()->setWindowFlags(windowFlags()
| Qt::FramelessWindowHint
| Qt::WindowStaysOnTopHint);
window()->showMaximized();
#endif
// hide Menubar & Dock
on_actionMenu_bar_toggled(false);
ui.actionMenu_bar->setChecked(false);
window()->setWindowState(windowState() | Qt::WindowFullScreen);
ui.dockAnimControl->setFeatures(QDockWidget::NoDockWidgetFeatures);
m_inactivityTimer->start(600000);
m_hiddenDemoModeActivated = true;
}
}
bool PulsatingScience::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::MouseButtonPress) {
userActivity();
}
// return original event (we don't want to change any behavior)
return QObject::eventFilter(obj, event);
}
void PulsatingScience::userActivity()
{
if(m_hiddenDemoModeActivated) {
// restart existing timer
m_inactivityTimer->start();
}
}
void PulsatingScience::userInactivityCallback()
{
saveOrRestoreInitialAnimationSettings();
}
void PulsatingScience::saveOrRestoreInitialAnimationSettings()
{
static bool initialized = false;
static bool radioCompanionWD;
static bool radioCompanionSun;
static bool radioCompanionNS;
static int sliderPulsarMass;
static int sliderPulsarSpinFrequency;
static int sliderPulsarSpinAxisInclination;
static int sliderPulsarMagneticAxisInclination;
static int sliderPulsarSemiMajorAxis;
static double cameraAngleH;
static double cameraAngleV;
static double cameraZoom;
if(initialized) {
// restore intial settings
ui.radioCompanionWD->setChecked(radioCompanionWD);
ui.radioCompanionSun->setChecked(radioCompanionSun);
ui.radioCompanionNS->setChecked(radioCompanionNS);
ui.sliderPulsarMass->setValue(sliderPulsarMass);
ui.sliderPulsarSpinFrequency->setValue(sliderPulsarSpinFrequency);
ui.sliderPulsarSpinAxisInclination->setValue(sliderPulsarSpinAxisInclination);
ui.sliderPulsarMagneticAxisInclination->setValue(sliderPulsarMagneticAxisInclination);
ui.sliderPulsarSemiMajorAxis->setValue(sliderPulsarSemiMajorAxis);
ui.pulsarGlWidget->resetCameraPosition(cameraAngleH, cameraAngleV, cameraZoom);
}
else {
// save initial settings
radioCompanionWD = ui.radioCompanionWD->isChecked();
radioCompanionSun = ui.radioCompanionSun->isChecked();
radioCompanionNS = ui.radioCompanionNS->isChecked();
sliderPulsarMass = ui.sliderPulsarMass->value();
sliderPulsarSpinFrequency = ui.sliderPulsarSpinFrequency->value();
sliderPulsarSpinAxisInclination = ui.sliderPulsarSpinAxisInclination->value();
sliderPulsarMagneticAxisInclination = ui.sliderPulsarMagneticAxisInclination->value();
sliderPulsarSemiMajorAxis = ui.sliderPulsarSemiMajorAxis->value();
ui.pulsarGlWidget->getCameraPosition(cameraAngleH, cameraAngleV, cameraZoom);
initialized = true;
}
}