StelMainView.cpp   StelMainView.cpp 
skipping to change at line 35 skipping to change at line 35
#include "StelModuleMgr.hpp" #include "StelModuleMgr.hpp"
#include "StelPainter.hpp" #include "StelPainter.hpp"
#include "StelGui.hpp" #include "StelGui.hpp"
#include "StelTranslator.hpp" #include "StelTranslator.hpp"
#include "StelUtils.hpp" #include "StelUtils.hpp"
#include "StelActionMgr.hpp" #include "StelActionMgr.hpp"
#include "StelOpenGL.hpp" #include "StelOpenGL.hpp"
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
#if STEL_USE_NEW_OPENGL_WIDGETS #ifdef USE_OLD_QGLWIDGET
#include <QOpenGLWidget>
#else
#include <QGLWidget> #include <QGLWidget>
#else
#include <QOpenGLWidget>
#endif #endif
#include <QApplication> #include <QApplication>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QGuiApplication> #include <QGuiApplication>
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QGraphicsAnchorLayout> #include <QGraphicsAnchorLayout>
#include <QGraphicsWidget> #include <QGraphicsWidget>
#include <QGraphicsEffect> #include <QGraphicsEffect>
#include <QFileInfo> #include <QFileInfo>
#include <QIcon> #include <QIcon>
skipping to change at line 64 skipping to change at line 64
#include <QThread> #include <QThread>
#include <QTimer> #include <QTimer>
#include <QWidget> #include <QWidget>
#include <QWindow> #include <QWindow>
#include <QMessageBox> #include <QMessageBox>
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
#include <QPinchGesture> #include <QPinchGesture>
#endif #endif
#include <QOpenGLShader> #include <QOpenGLShader>
#include <QOpenGLShaderProgram> #include <QOpenGLShaderProgram>
#include <QGLFramebufferObject> #include <QOpenGLFramebufferObject>
#include <QGLShaderProgram> #include <QOpenGLPaintDevice>
#ifdef OPENGL_DEBUG_LOGGING
#include <QOpenGLDebugLogger>
#endif
#include <clocale> #include <clocale>
// Initialize static variables // Initialize static variables
StelMainView* StelMainView::singleton = NULL; StelMainView* StelMainView::singleton = NULL;
#ifdef USE_OLD_QGLWIDGET
class StelGLWidget : public QGLWidget
#else
class StelGLWidget : public QOpenGLWidget
#endif
{
public:
StelGLWidget(const QSurfaceFormat& fmt, StelMainView* parent)
:
#ifdef USE_OLD_QGLWIDGET
QGLWidget(QGLFormat::fromSurfaceFormat(fmt),parent),
#else
QOpenGLWidget(parent),
#endif
parent(parent),
initialized(false)
{
qDebug()<<"StelGLWidget constructor";
#ifndef USE_OLD_QGLWIDGET
setFormat(fmt);
#endif
//because we always draw the full background,
//lets skip drawing the system background
setAttribute(Qt::WA_OpaquePaintEvent);
setAutoFillBackground(false);
}
~StelGLWidget()
{
qDebug()<<"StelGLWidget destroyed";
}
virtual void initializeGL() Q_DECL_OVERRIDE
{
if(initialized)
{
qWarning()<<"Double initialization, should not happe
n";
Q_ASSERT(false);
return;
}
//This seems to be the correct place to initialize all
//GL related stuff of the application
//this includes all the init() calls of the modules
#ifdef USE_OLD_QGLWIDGET
QOpenGLContext* ctx = context()->contextHandle();
#else
QOpenGLContext* ctx = context();
#endif
Q_ASSERT(ctx == QOpenGLContext::currentContext());
StelOpenGL::mainContext = ctx; //throw an error when StelOpe
nGL functions are executed in another context
qDebug()<<"initializeGL";
qDebug() << "OpenGL supported version: " << QString((char*)c
tx->functions()->glGetString(GL_VERSION));
qDebug() << "Current Format: " << this->format();
if (qApp->property("onetime_compat33")==true)
{
// This may not return the version number set previo
usly!
qDebug() << "StelGLWidget context format version:" <
< ctx->format().majorVersion() << "." << context()->format().minorVersion()
;
qDebug() << "StelGLWidget has CompatibilityProfile:"
<< (ctx->format().profile()==QSurfaceFormat::CompatibilityProfile ? "yes"
: "no") << "(" <<context()->format().profile() << ")";
}
parent->init();
initialized = true;
}
protected:
virtual void paintGL() Q_DECL_OVERRIDE
{
//this is actually never called because the
//QGraphicsView intercepts the paint event
//we have to draw in the background of the scene
//or as a QGraphicsItem
qDebug()<<"paintGL";
}
virtual void resizeGL(int w, int h) Q_DECL_OVERRIDE
{
//we probably can ignore this method,
//it seems it is also never called
qDebug()<<"resizeGL"<<w<<h;
}
private:
StelMainView* parent;
bool initialized;
};
// A custom QGraphicsEffect to apply the night mode on top of the screen. // A custom QGraphicsEffect to apply the night mode on top of the screen.
class NightModeGraphicsEffect : public QGraphicsEffect class NightModeGraphicsEffect : public QGraphicsEffect
{ {
public: public:
NightModeGraphicsEffect(QObject* parent = NULL); NightModeGraphicsEffect(StelMainView* parent = NULL)
: QGraphicsEffect(parent),
parent(parent), fbo(NULL)
{
Q_ASSERT(parent->glContext() == QOpenGLContext::currentConte
xt());
program = new QOpenGLShaderProgram(this);
QString vertexCode =
"attribute highp vec4 a_pos;\n"
"attribute highp vec2 a_texCoord;\n"
"varying highp vec2 v_texCoord;\n"
"void main(void)\n"
"{\n"
"v_texCoord = a_texCoord;\n"
"gl_Position = a_pos;\n"
"}\n";
QString fragmentCode =
"varying highp vec2 v_texCoord;\n"
"uniform sampler2D u_source;\n"
"void main(void)\n"
"{\n"
" mediump vec3 color = texture2D(u_sou
rce, v_texCoord).rgb;\n"
" mediump float luminance = max(max(co
lor.r, color.g), color.b);\n"
" gl_FragColor = vec4(luminance, 0.0,
0.0, 1.0);\n"
"}\n";
program->addShaderFromSourceCode(QOpenGLShader::Vertex, vert
exCode);
program->addShaderFromSourceCode(QOpenGLShader::Fragment, fr
agmentCode);
program->link();
vars.pos = program->attributeLocation("a_pos");
vars.texCoord = program->attributeLocation("a_texCoord");
vars.source = program->uniformLocation("u_source");
}
virtual ~NightModeGraphicsEffect()
{
Q_ASSERT(parent->glContext() == QOpenGLContext::currentConte
xt());
//clean up fbo
delete fbo;
}
protected: protected:
virtual void draw(QPainter* painter); virtual void draw(QPainter* painter) Q_DECL_OVERRIDE
{
Q_ASSERT(parent->glContext() == QOpenGLContext::currentConte
xt());
QOpenGLFunctions* gl = QOpenGLContext::currentContext()->fun
ctions();
QPaintDevice* paintDevice = painter->device();
int mainFBO;
gl->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mainFBO);
int pixelRatio = paintDevice->devicePixelRatio();
QSize size(paintDevice->width() * pixelRatio, paintDevice->h
eight() * pixelRatio);
if (fbo && fbo->size() != size)
{
delete fbo;
fbo = NULL;
}
if (!fbo)
{
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::Combi
nedDepthStencil);
format.setInternalTextureFormat(GL_RGBA);
fbo = new QOpenGLFramebufferObject(size, format);
}
// we have to use our own paint device
// we need this because using the original paint device (QOp
enGLWidgetPaintDevice when used with QOpenGLWidget) will rebind the default
FBO randomly
// but using 2 GL painters at the same time can mess up the
GL state, so we should close the old one first
// stop drawing to the old paint device to make sure state i
s reset correctly
painter->end();
// create our paint device
QOpenGLPaintDevice fboPaintDevice(size);
fboPaintDevice.setDevicePixelRatio(pixelRatio);
fbo->bind();
painter->begin(&fboPaintDevice);
drawSource(painter);
painter->end();
painter->begin(paintDevice);
//painter->beginNativePainting();
program->bind();
const GLfloat pos[] = {-1, -1, +1, -1, -1, +1, +1, +1};
const GLfloat texCoord[] = {0, 0, 1, 0, 0, 1, 1, 1};
program->setUniformValue(vars.source, 0);
program->setAttributeArray(vars.pos, pos, 2);
program->setAttributeArray(vars.texCoord, texCoord, 2);
program->enableAttributeArray(vars.pos);
program->enableAttributeArray(vars.texCoord);
gl->glBindTexture(GL_TEXTURE_2D, fbo->texture());
gl->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
program->release();
//painter->endNativePainting();
}
private: private:
QGLFramebufferObject* fbo; StelMainView* parent;
QGLShaderProgram *program; QOpenGLFramebufferObject* fbo;
QOpenGLShaderProgram *program;
struct { struct {
int pos; int pos;
int texCoord; int texCoord;
int source; int source;
} vars; } vars;
}; };
NightModeGraphicsEffect::NightModeGraphicsEffect(QObject* parent) : class StelGraphicsScene : public QGraphicsScene
QGraphicsEffect(parent)
, fbo(NULL)
{
program = new QGLShaderProgram(this);
QString vertexCode =
"attribute highp vec4 a_pos;\n"
"attribute highp vec2 a_texCoord;\n"
"varying highp vec2 v_texCoord;\n"
"void main(void)\n"
"{\n"
"v_texCoord = a_texCoord;\n"
"gl_Position = a_pos;\n"
"}\n";
QString fragmentCode =
"varying highp vec2 v_texCoord;\n"
"uniform sampler2D u_source;\n"
"void main(void)\n"
"{\n"
" mediump vec3 color = texture2D(u_source, v_texCoord)
.rgb;\n"
" mediump float luminance = max(max(color.r, color.g),
color.b);\n"
" gl_FragColor = vec4(luminance, 0.0, 0.0, 1.0);\n"
"}\n";
program->addShaderFromSourceCode(QGLShader::Vertex, vertexCode);
program->addShaderFromSourceCode(QGLShader::Fragment, fragmentCode);
program->link();
vars.pos = program->attributeLocation("a_pos");
vars.texCoord = program->attributeLocation("a_texCoord");
vars.source = program->uniformLocation("u_source");
}
// Qt 5.5 does not support setting the devicePixelRatio of a QGLFramebuffer
Object,
// So here we make a sub class just so that we can return the correct ratio
when
// using the buffer on a retina display.
class NightModeGraphicsEffectFbo : public QGLFramebufferObject
{ {
public: public:
NightModeGraphicsEffectFbo(const QSize& s, const QGLFramebufferObjec StelGraphicsScene(StelMainView* parent)
tFormat& f, int pixelRatio_) : : QGraphicsScene(parent), parent(parent)
QGLFramebufferObject(s, f), pixelRatio(pixelRatio_) {}
protected:
virtual int metric(PaintDeviceMetric m) const
{ {
if (m == QPaintDevice::PdmDevicePixelRatio) return pixelRati qDebug()<<"StelGraphicsScene constructor";
o;
return QGLFramebufferObject::metric(m);
} }
private:
int pixelRatio;
};
void NightModeGraphicsEffect::draw(QPainter* painter) protected:
{
int pixelRatio = painter->device()->devicePixelRatio(); void keyPressEvent(QKeyEvent* event) Q_DECL_OVERRIDE
QSize size(painter->device()->width() * pixelRatio, painter->device(
)->height() * pixelRatio);
if (fbo && fbo->size() != size)
{ {
delete fbo; // Try to trigger a global shortcut.
fbo = NULL; StelActionMgr* actionMgr = StelApp::getInstance().getStelAct
ionManager();
if (actionMgr->pushKey(event->key() + event->modifiers(), tr
ue)) {
event->setAccepted(true);
parent->thereWasAnEvent(); // Refresh screen ASAP
return;
}
//pass event on to items otherwise
QGraphicsScene::keyPressEvent(event);
} }
if (!fbo)
{
QGLFramebufferObjectFormat format;
format.setAttachment(QGLFramebufferObject::CombinedDepthSten
cil);
format.setInternalTextureFormat(GL_RGBA);
fbo = new NightModeGraphicsEffectFbo(size, format, pixelRati
o);
}
QPainter fboPainter(fbo);
drawSource(&fboPainter);
painter->save();
painter->beginNativePainting();
program->bind();
const GLfloat pos[] = {-1, -1, +1, -1, -1, +1, +1, +1};
const GLfloat texCoord[] = {0, 0, 1, 0, 0, 1, 1, 1};
program->setUniformValue(vars.source, 0);
program->setAttributeArray(vars.pos, pos, 2);
program->setAttributeArray(vars.texCoord, texCoord, 2);
program->enableAttributeArray(vars.pos);
program->enableAttributeArray(vars.texCoord);
glBindTexture(GL_TEXTURE_2D, fbo->texture());
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
program->release();
painter->endNativePainting();
painter->restore();
}
//! Render Stellarium sky.
class StelSkyItem : public QGraphicsWidget
{
public:
StelSkyItem(QGraphicsItem* parent = NULL);
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option
, QWidget* widget = 0);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent* event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
void mouseMoveEvent(QGraphicsSceneMouseEvent* event);
void wheelEvent(QGraphicsSceneWheelEvent *event);
void keyPressEvent(QKeyEvent *event);
void keyReleaseEvent(QKeyEvent *event);
void resizeEvent(QGraphicsSceneResizeEvent* event);
#ifdef Q_OS_WIN
bool event(QEvent * e);
#endif
private: private:
double previousPaintTime; StelMainView* parent;
// void onSizeChanged();
#ifdef Q_OS_WIN
void pinchTriggered(QPinchGesture *gesture);
bool gestureEvent(QGestureEvent *event);
#endif
}; };
//! Initialize and render Stellarium gui. class StelRootItem : public QGraphicsObject
class StelGuiItem : public QGraphicsWidget
{ {
public: public:
StelGuiItem(QGraphicsItem* parent = NULL); StelRootItem(StelMainView* mainView, QGraphicsItem* parent = NULL)
protected: : QGraphicsObject(parent), mainView(mainView)
void resizeEvent(QGraphicsSceneResizeEvent* event); {
private: setFlag(QGraphicsItem::ItemClipsToShape);
QGraphicsWidget *widget; setFlag(QGraphicsItem::ItemClipsChildrenToShape);
// void onSizeChanged(); setFlag(QGraphicsItem::ItemIsFocusable);
};
setAcceptHoverEvents(true);
StelSkyItem::StelSkyItem(QGraphicsItem* parent)
{
Q_UNUSED(parent);
setObjectName("SkyItem");
setFlag(QGraphicsItem::ItemHasNoContents, false);
setFlag(QGraphicsItem::ItemIsFocusable, true);
setAcceptHoverEvents(true);
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
setAcceptTouchEvents(true); setAcceptTouchEvents(true);
grabGesture(Qt::PinchGesture); grabGesture(Qt::PinchGesture);
#endif #endif
setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton | Qt::Middl setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton | Q
eButton); t::MiddleButton);
previousPaintTime = StelApp::getTotalRunTime(); previousPaintTime = StelApp::getTotalRunTime();
setFocus(); }
}
void StelSkyItem::resizeEvent(QGraphicsSceneResizeEvent* event)
{
QGraphicsWidget::resizeEvent(event);
StelApp::getInstance().glWindowHasBeenResized(scenePos().x(), scene(
)->sceneRect().height()-(scenePos().y()+geometry().height()), geometry().wi
dth(), geometry().height());
}
void StelSkyItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *
option, QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
const double now = StelApp::getTotalRunTime(); void setSize(const QSize& size)
double dt = now - previousPaintTime; {
previousPaintTime = now; prepareGeometryChange();
rect.setSize(size);
}
painter->beginNativePainting(); protected:
glClearColor(0, 0, 0, 1); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem
glClear(GL_COLOR_BUFFER_BIT); *option, QWidget *widget) Q_DECL_OVERRIDE
StelApp::getInstance().update(dt); {
StelApp::getInstance().draw(); Q_UNUSED(option);
Q_UNUSED(widget);
painter->endNativePainting(); //a sanity check
} Q_ASSERT(mainView->glContext() == QOpenGLContext::currentCon
text());
void StelSkyItem::mousePressEvent(QGraphicsSceneMouseEvent *event) const double now = StelApp::getTotalRunTime();
{ double dt = now - previousPaintTime;
//To get back the focus from dialogs //qDebug()<<"dt"<<dt;
setFocus(); previousPaintTime = now;
QPointF pos = event->scenePos();
pos.setY(size().height() - 1 - pos.y());
QMouseEvent newEvent(QEvent::MouseButtonPress, QPoint(pos.x(), pos.y
()), event->button(), event->buttons(), event->modifiers());
StelApp::getInstance().handleClick(&newEvent);
}
void StelSkyItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) //important to call this, or Qt may have invalid state after
{ we have drawn (wrong textures, etc...)
QPointF pos = event->scenePos(); painter->beginNativePainting();
pos.setY(size().height() - 1 - pos.y());
QMouseEvent newEvent(QEvent::MouseButtonRelease, QPoint(pos.x(), pos
.y()), event->button(), event->buttons(), event->modifiers());
StelApp::getInstance().handleClick(&newEvent);
}
void StelSkyItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event) //fix for bug 1628072 caused by QTBUG-56798
{ #ifndef QT_NO_DEBUG
QPointF pos = event->scenePos(); StelOpenGL::clearGLErrors();
pos.setY(size().height() - 1 - pos.y()); #endif
StelApp::getInstance().handleMove(pos.x(), pos.y(), event->buttons()
);
}
void StelSkyItem::wheelEvent(QGraphicsSceneWheelEvent *event) QOpenGLFunctions* gl = QOpenGLContext::currentContext()->fun
{ ctions();
QPointF pos = event->scenePos();
pos.setY(size().height() - 1 - pos.y());
QWheelEvent newEvent(QPoint(pos.x(),pos.y()), event->delta(), event-
>buttons(), event->modifiers(), event->orientation());
StelApp::getInstance().handleWheel(&newEvent);
}
#ifdef Q_OS_WIN //clear the buffer (not strictly required for us because we
bool StelSkyItem::event(QEvent * e) repaint all pixels, but should improve perf on tile-based renderers)
{ gl->glClearColor(0,0,0,0); //we also clear alpha to zero
switch (e->type()){ gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_S
case QEvent::TouchBegin: TENCIL_BUFFER_BIT);
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
{
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->tou
chPoints();
if (touchPoints.count() == 1) //update and draw
setAcceptedMouseButtons(Qt::LeftButton | Qt::RightBu StelApp& app = StelApp::getInstance();
tton | Qt::MiddleButton); app.update(dt); // may also issue GL calls
app.draw();
painter->endNativePainting();
return true; mainView->drawEnded();
break;
} }
case QEvent::Gesture: virtual QRectF boundingRect() const Q_DECL_OVERRIDE
setAcceptedMouseButtons(0); {
return gestureEvent(static_cast<QGestureEvent*>(e)); return rect;
break; }
default: //*** Main event handlers to pass on to StelApp ***//
return QGraphicsWidget::event(e); void mousePressEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRID
E
{
QMouseEvent ev = convertMouseEvent(event);
StelApp::getInstance().handleClick(&ev);
event->setAccepted(ev.isAccepted());
if(ev.isAccepted())
mainView->thereWasAnEvent();
} }
}
bool StelSkyItem::gestureEvent(QGestureEvent *event) void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERR
{ IDE
if (QGesture *pinch = event->gesture(Qt::PinchGesture)) {
pinchTriggered(static_cast<QPinchGesture *>(pinch)); QMouseEvent ev = convertMouseEvent(event);
StelApp::getInstance().handleClick(&ev);
event->setAccepted(ev.isAccepted());
if(ev.isAccepted())
mainView->thereWasAnEvent();
}
return true; void mouseMoveEvent(QGraphicsSceneMouseEvent *event) Q_DECL_OVERRIDE
} {
QMouseEvent ev = convertMouseEvent(event);
QPointF pos = ev.pos();
event->setAccepted(StelApp::getInstance().handleMove(pos.x()
, pos.y(), ev.buttons()));
if(event->isAccepted())
mainView->thereWasAnEvent();
}
void StelSkyItem::pinchTriggered(QPinchGesture *gesture) void wheelEvent(QGraphicsSceneWheelEvent *event) Q_DECL_OVERRIDE
{ {
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags(); QPointF pos = event->scenePos();
if (changeFlags & QPinchGesture::ScaleFactorChanged) { pos.setY(rect.height() - 1 - pos.y());
qreal zoom = gesture->scaleFactor(); QWheelEvent newEvent(QPoint(pos.x(),pos.y()), event->delta()
, event->buttons(), event->modifiers(), event->orientation());
StelApp::getInstance().handleWheel(&newEvent);
event->setAccepted(newEvent.isAccepted());
if(newEvent.isAccepted())
mainView->thereWasAnEvent();
}
if (zoom < 2 && zoom > 0.5){ void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE
StelApp::getInstance().handlePinch(zoom, true); {
} StelApp::getInstance().handleKeys(event);
if(event->isAccepted())
mainView->thereWasAnEvent();
} }
}
#endif
void StelSkyItem::keyPressEvent(QKeyEvent* event) void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE
{ {
StelApp::getInstance().handleKeys(event); StelApp::getInstance().handleKeys(event);
} if(event->isAccepted())
mainView->thereWasAnEvent();
}
void StelSkyItem::keyReleaseEvent(QKeyEvent* event) //*** Gesture and touch support, currently only for Windows
{ #ifdef Q_OS_WIN
StelApp::getInstance().handleKeys(event); bool event(QEvent * e) Q_DECL_OVERRIDE
} {
switch (e->type()){
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
{
QTouchEvent *touchEvent = static_cast<QTouch
Event *>(e);
QList<QTouchEvent::TouchPoint> touchPoints =
touchEvent->touchPoints();
StelGuiItem::StelGuiItem(QGraphicsItem* parent) : QGraphicsWidget(parent) if (touchPoints.count() == 1)
{ setAcceptedMouseButtons(Qt::LeftButt
widget = new QGraphicsWidget(this); on | Qt::RightButton | Qt::MiddleButton);
StelApp::getInstance().getGui()->init(widget);
}
void StelGuiItem::resizeEvent(QGraphicsSceneResizeEvent* event) return true;
{ break;
Q_UNUSED(event); }
widget->setGeometry(0, 0, size().width(), size().height());
StelApp::getInstance().getGui()->forceRefreshGui();
}
#if STEL_USE_NEW_OPENGL_WIDGETS case QEvent::Gesture:
setAcceptedMouseButtons(0);
return gestureEvent(static_cast<QGestureEven
t*>(e));
break;
class StelQOpenGLWidget : public QOpenGLWidget default:
{ return QGraphicsObject::event(e);
public: }
StelQOpenGLWidget(QWidget* parent) : QOpenGLWidget(parent)
{
// TODO: Unclear if tese attributes make sense?
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_OpaquePaintEvent);
} }
protected: private:
virtual void initializeGL() bool gestureEvent(QGestureEvent *event)
{ {
qDebug() << "It appears this was never called?"; if (QGesture *pinch = event->gesture(Qt::PinchGesture))
qDebug() << "OpenGL supported version: " << QString((char*)g pinchTriggered(static_cast<QPinchGesture *>(pinch));
lGetString(GL_VERSION));
QOpenGLWidget::initializeGL(); return true;
this->makeCurrent(); // Do we need this?
// GZ I have no idea how to proceed, sorry.
QSurfaceFormat format=this->format();
qDebug() << "Current Format: " << this->format();
// TODO: Test something? The old tests may be obsolete as al
l OpenGL2 formats/contexts have these?
} }
virtual void paintGL()
void pinchTriggered(QPinchGesture *gesture)
{ {
// TODO: what shall this do exactly? QPinchGesture::ChangeFlags changeFlags = gesture->changeFlag
s();
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
qreal zoom = gesture->scaleFactor();
if (zoom < 2 && zoom > 0.5){
StelApp::getInstance().handlePinch(zoom, tru
e);
}
}
} }
virtual void resizeGL() #endif
private:
//! Helper function to convert a QGraphicsSceneMouseEvent to a QMous
eEvent suitable for StelApp consumption
QMouseEvent convertMouseEvent(QGraphicsSceneMouseEvent *event) const
{ {
// TODO: what shall this do exactly? //convert graphics scene mouse event to widget style mouse e
vent
QEvent::Type t = QEvent::None;
switch(event->type())
{
case QEvent::GraphicsSceneMousePress:
t = QEvent::MouseButtonPress;
break;
case QEvent::GraphicsSceneMouseRelease:
t = QEvent::MouseButtonRelease;
break;
case QEvent::GraphicsSceneMouseMove:
t = QEvent::MouseMove;
break;
case QEvent::GraphicsSceneMouseDoubleClick:
//note: the old code seems to have ignored d
ouble clicks
// and handled them the same as normal mouse
presses
//if we ever want to handle double clicks, s
witch out these lines
//t = QEvent::MouseButtonDblClick;
t = QEvent::MouseButtonPress;
break;
default:
//warn in release and assert in debug
qWarning("Unhandled mouse event type %d",eve
nt->type());
Q_ASSERT(false);
}
QPointF pos = event->scenePos();
//Y needs to be inverted
pos.setY(rect.height() - 1 - pos.y());
return QMouseEvent(t,pos,event->button(),event->buttons(),ev
ent->modifiers());
} }
QRectF rect;
double previousPaintTime;
StelMainView* mainView;
}; };
#else //! Initialize and render Stellarium gui.
class StelQGLWidget : public QGLWidget class StelGuiItem : public QGraphicsWidget
{ {
public: public:
StelQGLWidget(QGLContext* ctx, QWidget* parent) : QGLWidget(ctx, par StelGuiItem(QGraphicsItem* parent = NULL)
ent) : QGraphicsWidget(parent)
{ {
setAttribute(Qt::WA_PaintOnScreen); StelApp::getInstance().getGui()->init(this);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_OpaquePaintEvent);
} }
protected: protected:
virtual void initializeGL() void resizeEvent(QGraphicsSceneResizeEvent* event) Q_DECL_OVERRIDE
{ {
qDebug() << "It appears this is never called?"; Q_UNUSED(event);
Q_ASSERT(0); //widget->setGeometry(0, 0, size().width(), size().height())
qDebug() << "OpenGL supported version: " << QString((char*)g ;
lGetString(GL_VERSION)); StelApp::getInstance().getGui()->forceRefreshGui();
QGLWidget::initializeGL();
qDebug() << "Current Context: " << this->format();
if (!format().stencil())
qWarning("Could not get stencil buffer; results will
be suboptimal");
if (!format().depth())
qWarning("Could not get depth buffer; results will b
e suboptimal");
if (!format().doubleBuffer())
qWarning("Could not get double buffer; results will
be suboptimal");
} }
private:
//QGraphicsWidget *widget;
// void onSizeChanged();
}; };
#endif
StelMainView::StelMainView(QWidget* parent) StelMainView::StelMainView(QSettings* settings)
: QGraphicsView(parent), guiItem(NULL), : QGraphicsView(),
guiItem(NULL),
gui(NULL), gui(NULL),
stelApp(NULL),
updateQueued(false),
flagInvertScreenShotColors(false), flagInvertScreenShotColors(false),
flagOverwriteScreenshots(false), flagOverwriteScreenshots(false),
screenShotPrefix("stellarium-"), screenShotPrefix("stellarium-"),
screenShotDir(""), screenShotDir(""),
cursorTimeout(-1.f), flagCursorTimeout(false), minFpsTimer(NULL), maxfps(10000.f) cursorTimeout(-1.f), flagCursorTimeout(false), maxfps(10000.f)
{ {
setAttribute(Qt::WA_OpaquePaintEvent);
setAutoFillBackground(false);
configuration = settings;
StelApp::initStatic(); StelApp::initStatic();
minFpsTimer = new QTimer(this);
minFpsTimer->setTimerType(Qt::PreciseTimer);
minFpsTimer->setInterval(1000/minfps);
connect(minFpsTimer,SIGNAL(timeout()),this,SLOT(minFPSUpdate()));
// Can't create 2 StelMainView instances // Can't create 2 StelMainView instances
Q_ASSERT(!singleton); Q_ASSERT(!singleton);
singleton = this; singleton = this;
setWindowIcon(QIcon(":/mainWindow/icon.bmp")); setWindowIcon(QIcon(":/mainWindow/icon.bmp"));
initTitleI18n(); initTitleI18n();
setObjectName("Mainview"); setObjectName("Mainview");
// Allows for precise FPS control
setViewportUpdateMode(QGraphicsView::NoViewportUpdate); setViewportUpdateMode(QGraphicsView::NoViewportUpdate);
setFrameShape(QFrame::NoFrame); setFrameShape(QFrame::NoFrame);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setFocusPolicy(Qt::StrongFocus); //because we only want child elements to have focus, we turn it off
here
setFocusPolicy(Qt::NoFocus);
connect(this, SIGNAL(screenshotRequested()), this, SLOT(doScreenshot ())); connect(this, SIGNAL(screenshotRequested()), this, SLOT(doScreenshot ()));
lastEventTimeSec = 0; lastEventTimeSec = 0;
#if STEL_USE_NEW_OPENGL_WIDGETS #ifdef OPENGL_DEBUG_LOGGING
// Primary test for OpenGL existence glLogger = new QOpenGLDebugLogger(this);
if (QSurfaceFormat::defaultFormat().majorVersion() < 2) connect(glLogger, SIGNAL(messageLogged(QOpenGLDebugMessage)), this,
{ SLOT(logGLMessage(QOpenGLDebugMessage)));
qWarning() << "No OpenGL 2 support on this system. Aborting. #endif
";
QMessageBox::critical(0, "Stellarium", q_("No OpenGL 2 found
on this system. Please upgrade hardware or use MESA or an older version.")
, QMessageBox::Abort, QMessageBox::Abort);
exit(0);
}
//QSurfaceFormat format();
//// TBD: What options shall be default?
//QSurfaceFormat::setDefaultFormat(format);
////QOpenGLContext* context=new QOpenGLContext::create();
glWidget = new StelQOpenGLWidget(this);
//glWidget->setFormat(format);
#else
// Primary test for OpenGL existence
if (QGLFormat::openGLVersionFlags() < QGLFormat::OpenGL_Version_2_1)
{
qWarning() << "No OpenGL 2.1 support on this system. Abortin
g.";
QMessageBox::critical(0, "Stellarium", q_("No OpenGL 2 found
on this system. Please upgrade hardware or use MESA or an older version.")
, QMessageBox::Abort, QMessageBox::Abort);
exit(1);
}
// Create an openGL viewport
QGLFormat glFormat(QGL::StencilBuffer | QGL::DepthBuffer | QGL::Doub
leBuffer);
// Even if setting a version here, it may not be accepted in StelQGL
Widget()!
// Currently, not setting a version explicitly works on Windows and
Linux.
// Apparently some Macs have problems however and default to 2.1.
// We try a new CLI flag here which requests 3.3 Compatibiliy Profil
e which modern Macs should deliver.
// OpenGL Specs say this will deliver at least the requested version
, if possible.
// TBD: Maybe this must make a differentiation between OpenGL and Op
enGL ES!
// TBD: If this works for Mac, it should be requested on all Macs wi
thout CLI option!
if (qApp->property("onetime_compat33")==true)
{
if (!(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Ve
rsion_3_3))
{
qWarning() << "No OpenGL 3.3 found here. We will get
whatever is available.";
qDebug() << "FYI: OpenGL Versions Supported: " <<
QGLFormat::openGLVersionFlags();
}
glFormat.setVersion(3, 3);
glFormat.setProfile(QGLFormat::CompatibilityProfile);
}
QGLContext* context=new QGLContext(glFormat);
if (context->format() != glFormat) //get the desired opengl format parameters
{ QSurfaceFormat glFormat = getDesiredGLFormat();
qWarning() << "Cannot provide requested OpenGL format. Appar // VSync control
ently insufficient OpenGL resources on this system."; QVariant vsync = configuration->value("video/vsync");
QMessageBox::critical(0, "Stellarium", q_("Cannot acquire ne if(vsync.isValid() && vsync.canConvert<bool>()) // if the config par
cessary OpenGL resources."), QMessageBox::Abort, QMessageBox::Abort); ameter is not set we use system default (which should be true)
exit(1); glFormat.setSwapInterval(vsync.toBool());
}
glWidget = new StelQGLWidget(context, this); qDebug()<<"Desired surface format: "<<glFormat;
if (qApp->property("onetime_compat33")==true)
{ #if QT_VERSION >= QT_VERSION_CHECK(5,4,0)
// This may not return the version number set previously! //we set the default format to our required format, if possible
qDebug() << "StelQGLWidget context format version:" << glWid //this only works with Qt 5.4+
get->context()->format().majorVersion() << "." << glWidget->context()->form QSurfaceFormat defFmt = glFormat;
at().minorVersion(); //we don't need these buffers in the background
qDebug() << "StelQGLWidget has CompatibilityProfile:" << (gl defFmt.setAlphaBufferSize(0);
Widget->context()->format().profile()==QGLFormat::CompatibilityProfile ? "y defFmt.setStencilBufferSize(0);
es" : "no") << "(" <<glWidget->context()->format().profile() << ")"; defFmt.setDepthBufferSize(0);
} QSurfaceFormat::setDefaultFormat(defFmt);
#endif #endif
//QGLWidget should set the format in constructor to prevent creating
an unnecessary temporary context
glWidget = new StelGLWidget(glFormat, this);
setViewport(glWidget); setViewport(glWidget);
setScene(new QGraphicsScene(this)); stelScene = new StelGraphicsScene(this);
setScene(stelScene);
scene()->setItemIndexMethod(QGraphicsScene::NoIndex); scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
rootItem = new QGraphicsWidget(); rootItem = new StelRootItem(this);
rootItem->setFocusPolicy(Qt::NoFocus);
// Workaround (see Bug #940638) Although we have already explicitly set // Workaround (see Bug #940638) Although we have already explicitly set
// LC_NUMERIC to "C" in main.cpp there seems to be a bug in OpenGL w here // LC_NUMERIC to "C" in main.cpp there seems to be a bug in OpenGL w here
// it will silently reset LC_NUMERIC to the value of LC_ALL during O penGL // it will silently reset LC_NUMERIC to the value of LC_ALL during O penGL
// initialization. This has been observed on Ubuntu 11.10 under cert ain // initialization. This has been observed on Ubuntu 11.10 under cert ain
// circumstances, so here we set it again just to be on the safe sid e. // circumstances, so here we set it again just to be on the safe sid e.
setlocale(LC_NUMERIC, "C"); setlocale(LC_NUMERIC, "C");
// End workaround // End workaround
#ifdef USE_OLD_QGLWIDGET
// StelGLWidget::initializeGL is seemingly never called automaticall
y with the QGLWidget, so we have to do it ourselves
//we have to force context creation here
glWidget->makeCurrent();
glWidget->initializeGL();
#endif
} }
void StelMainView::resizeEvent(QResizeEvent* event) void StelMainView::resizeEvent(QResizeEvent* event)
{ {
scene()->setSceneRect(QRect(QPoint(0, 0), event->size())); if(scene())
rootItem->setGeometry(0,0,event->size().width(),event->size().height {
()); const QSize& sz = event->size();
scene()->setSceneRect(QRect(QPoint(0, 0), sz));
rootItem->setSize(sz);
if(guiItem)
guiItem->setGeometry(QRectF(0.0f,0.0f,sz.width(),sz.
height()));
}
QGraphicsView::resizeEvent(event); QGraphicsView::resizeEvent(event);
} }
void StelMainView::focusSky() { void StelMainView::focusSky() {
scene()->setActiveWindow(0); //scene()->setActiveWindow(0);
skyItem->setFocus(); rootItem->setFocus();
} }
StelMainView::~StelMainView() StelMainView::~StelMainView()
{ {
//delete the night view graphic effect here while GL context is stil
l valid
rootItem->setGraphicsEffect(Q_NULLPTR);
StelApp::deinitStatic(); StelApp::deinitStatic();
} }
void StelMainView::init(QSettings* conf) QSurfaceFormat StelMainView::getDesiredGLFormat() const
{ {
gui = new StelGui(); #if QT_VERSION < QT_VERSION_CHECK(5,4,0)
//default-constructed format
#if STEL_USE_NEW_OPENGL_WIDGETS QSurfaceFormat fmt;
//glWidget->initializeGL(); // protected...
//Q_ASSERT(glWidget->isValid());
#else #else
Q_ASSERT(glWidget->isValid()); //use the default format as basis
glWidget->makeCurrent(); QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
qDebug()<<"Default surface format: "<<fmt;
#endif
//if on an GLES build, do not set the format
#ifndef QT_OPENGL_ES_2
// OGL 2.1 + FBOs should basically be the minimum required for Stell
arium
fmt.setRenderableType(QSurfaceFormat::OpenGL);
fmt.setMajorVersion(2);
fmt.setMinorVersion(1);
// The following is NOT needed (or even supported) when we request a
2.1 context
// The implementation may give us a newer context,
// but compatibility with 2.1 should be ensured automatically
//fmt.setProfile(QSurfaceFormat::CompatibilityProfile);
//fmt.setOption(QSurfaceFormat::DeprecatedFunctions);
#endif
//request some sane buffer formats
fmt.setRedBufferSize(8);
fmt.setGreenBufferSize(8);
fmt.setBlueBufferSize(8);
fmt.setAlphaBufferSize(8);
fmt.setDepthBufferSize(24);
//I dont think we use the stencil buffer for anything
//but maybe Qt needs it
fmt.setStencilBufferSize(8);
#ifdef OPENGL_DEBUG_LOGGING
//try to enable GL debugging using GL_KHR_debug
fmt.setOption(QSurfaceFormat::DebugContext);
#endif
//vsync needs to be set on the default format for it to work
//fmt.setSwapInterval(0);
return fmt;
}
void StelMainView::init()
{
#ifdef OPENGL_DEBUG_LOGGING
if(!QOpenGLContext::currentContext()->hasExtension(QByteArrayLiteral
("GL_KHR_debug")))
qWarning()<<"GL_KHR_debug extension missing, OpenGL debug lo
gger will likely not work";
if(glLogger->initialize())
{
qDebug()<<"OpenGL debug logger initialized";
QVector<GLuint> disabledMsgs;
//if your GL implementation spams some output you are not in
terested in,
//you can disable their message IDs here
//disabledMsgs.append(100);
glLogger->disableMessages(disabledMsgs);
glLogger->startLogging(QOpenGLDebugLogger::SynchronousLoggin
g);
//the internal log buffer may not be empty, so check it
foreach(const QOpenGLDebugMessage& msg, glLogger->loggedMess
ages())
{
logGLMessage(msg);
}
}
else
qWarning()<<"Failed to initialize OpenGL debug logger";
connect(QOpenGLContext::currentContext(),SIGNAL(aboutToBeDestroyed()
),this,SLOT(contextDestroyed()));
//for easier debugging, print the adress of the main GL context
qDebug()<<"CurCtxPtr:"<<QOpenGLContext::currentContext();
#endif #endif
qDebug()<<"StelMainView::init";
glInfo.mainContext = QOpenGLContext::currentContext();
glInfo.functions = glInfo.mainContext->functions();
glInfo.vendor = QString(reinterpret_cast<const char*>(glInfo.functio
ns->glGetString(GL_VENDOR)));
glInfo.renderer = QString(reinterpret_cast<const char*>(glInfo.funct
ions->glGetString(GL_RENDERER)));
gui = new StelGui();
QSettings* conf = configuration;
// Should be check of requirements disabled? // Should be check of requirements disabled?
if (conf->value("main/check_requirements", true).toBool()) if (conf->value("main/check_requirements", true).toBool())
{ {
// Find out lots of debug info about supported version of Op enGL and vendor/renderer. // Find out lots of debug info about supported version of Op enGL and vendor/renderer.
processOpenGLdiagnosticsAndWarnings(conf, glWidget); processOpenGLdiagnosticsAndWarnings(conf, QOpenGLContext::cu rrentContext());
} }
stelApp= new StelApp(); //create and initialize main app
stelApp = new StelApp(this);
stelApp->setGui(gui); stelApp->setGui(gui);
stelApp->init(conf); stelApp->init(conf);
//this makes sure the app knows how large the window is
connect(stelScene,SIGNAL(sceneRectChanged(QRectF)),stelApp,SLOT(glWi
ndowHasBeenResized(QRectF)));
//also immediately set the current values
stelApp->glWindowHasBeenResized(stelScene->sceneRect());
StelActionMgr *actionMgr = stelApp->getStelActionManager(); StelActionMgr *actionMgr = stelApp->getStelActionManager();
actionMgr->addAction("actionSave_Screenshot_Global", N_("Miscellaneo us"), N_("Save screenshot"), this, "saveScreenShot()", "Ctrl+S"); actionMgr->addAction("actionSave_Screenshot_Global", N_("Miscellaneo us"), N_("Save screenshot"), this, "saveScreenShot()", "Ctrl+S");
actionMgr->addAction("actionSet_Full_Screen_Global", N_("Display Opt ions"), N_("Full-screen mode"), this, "fullScreen", "F11"); actionMgr->addAction("actionSet_Full_Screen_Global", N_("Display Opt ions"), N_("Full-screen mode"), this, "fullScreen", "F11");
StelPainter::initGLShaders(); StelPainter::initGLShaders();
skyItem = new StelSkyItem(); guiItem = new StelGuiItem(rootItem);
guiItem = new StelGuiItem();
QGraphicsAnchorLayout* l = new QGraphicsAnchorLayout(rootItem);
l->setSpacing(0);
l->setContentsMargins(0,0,0,0);
l->addCornerAnchors(skyItem, Qt::TopLeftCorner, l, Qt::TopLeftCorner
);
l->addCornerAnchors(skyItem, Qt::BottomRightCorner, l, Qt::BottomRig
htCorner);
l->addCornerAnchors(guiItem, Qt::BottomLeftCorner, l, Qt::BottomLeft
Corner);
l->addCornerAnchors(guiItem, Qt::TopRightCorner, l, Qt::TopRightCorn
er);
rootItem->setLayout(l);
scene()->addItem(rootItem); scene()->addItem(rootItem);
//set the default focus to the sky
focusSky();
nightModeEffect = new NightModeGraphicsEffect(this); nightModeEffect = new NightModeGraphicsEffect(this);
updateNightModeProperty(StelApp::getInstance().getVisionModeNight()) ; updateNightModeProperty(StelApp::getInstance().getVisionModeNight()) ;
//install the effect on the whole view
rootItem->setGraphicsEffect(nightModeEffect); rootItem->setGraphicsEffect(nightModeEffect);
QSize size = glWidget->windowHandle()->screen()->size();
size = QSize(conf->value("video/screen_w", size.width()).toInt(),
conf->value("video/screen_h", size.height()).toInt());
bool fullscreen = conf->value("video/fullscreen", true).toBool();
// Without this, the screen is not shown on a Mac + we should use re
size() for correct work of fullscreen/windowed mode switch. --AW WTF???
resize(size);
QDesktopWidget *desktop = QApplication::desktop(); QDesktopWidget *desktop = QApplication::desktop();
int screen = conf->value("video/screen_number", 0).toInt(); int screen = conf->value("video/screen_number", 0).toInt();
if (screen < 0 || screen >= desktop->screenCount()) if (screen < 0 || screen >= desktop->screenCount())
{ {
qWarning() << "WARNING: screen" << screen << "not found"; qWarning() << "WARNING: screen" << screen << "not found";
screen = 0; screen = 0;
} }
QRect screenGeom = desktop->screenGeometry(screen); QRect screenGeom = desktop->screenGeometry(screen);
QSize size = QSize(conf->value("video/screen_w", screenGeom.width())
.toInt(),
conf->value("video/screen_h", screenGeom.height()).toIn
t());
bool fullscreen = conf->value("video/fullscreen", true).toBool();
// Without this, the screen is not shown on a Mac + we should use re
size() for correct work of fullscreen/windowed mode switch. --AW WTF???
resize(size);
if (fullscreen) if (fullscreen)
{ {
// The "+1" below is to work around Linux/Gnome problem with mouse focus. // The "+1" below is to work around Linux/Gnome problem with mouse focus.
move(screenGeom.x()+1, screenGeom.y()+1); move(screenGeom.x()+1, screenGeom.y()+1);
// The fullscreen window appears on screen where is the majo rity of // The fullscreen window appears on screen where is the majo rity of
// the normal window. Therefore we crop the normal window to the // the normal window. Therefore we crop the normal window to the
// screen area to ensure that the majority is not on another screen. // screen area to ensure that the majority is not on another screen.
setGeometry(geometry() & screenGeom); setGeometry(geometry() & screenGeom);
setFullScreen(true); setFullScreen(true);
} }
skipping to change at line 631 skipping to change at line 811
{ {
setFullScreen(false); setFullScreen(false);
int x = conf->value("video/screen_x", 0).toInt(); int x = conf->value("video/screen_x", 0).toInt();
int y = conf->value("video/screen_y", 0).toInt(); int y = conf->value("video/screen_y", 0).toInt();
move(x + screenGeom.x(), y + screenGeom.y()); move(x + screenGeom.x(), y + screenGeom.y());
} }
flagInvertScreenShotColors = conf->value("main/invert_screenshots_co lors", false).toBool(); flagInvertScreenShotColors = conf->value("main/invert_screenshots_co lors", false).toBool();
setFlagCursorTimeout(conf->value("gui/flag_mouse_cursor_timeout", fa lse).toBool()); setFlagCursorTimeout(conf->value("gui/flag_mouse_cursor_timeout", fa lse).toBool());
setCursorTimeout(conf->value("gui/mouse_cursor_timeout", 10.f).toFlo at()); setCursorTimeout(conf->value("gui/mouse_cursor_timeout", 10.f).toFlo at());
maxfps = conf->value("video/maximum_fps",10000.f).toFloat(); setMaxFps(conf->value("video/maximum_fps",10000.f).toFloat());
minfps = conf->value("video/minimum_fps",10000.f).toFloat(); setMinFps(conf->value("video/minimum_fps",10000.f).toFloat());
flagMaxFpsUpdatePending = false;
// XXX: This should be done in StelApp::init(), unfortunately for th e moment we need to init the gui before the // XXX: This should be done in StelApp::init(), unfortunately for th e moment we need to init the gui before the
// plugins, because the gui creates the QActions needed by some plug ins. // plugins, because the gui creates the QActions needed by some plug ins.
StelApp::getInstance().initPlugIns(); stelApp->initPlugIns();
// activate DE430/431
StelApp::getInstance().getCore()->initEphemeridesFunctions();
// The script manager can only be fully initialized after the plugin s have loaded. // The script manager can only be fully initialized after the plugin s have loaded.
StelApp::getInstance().initScriptMgr(); stelApp->initScriptMgr();
// Set the global stylesheet, this is only useful for the tooltips. // Set the global stylesheet, this is only useful for the tooltips.
StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui( )); StelGui* gui = dynamic_cast<StelGui*>(stelApp->getGui());
if (gui!=NULL) if (gui!=NULL)
setStyleSheet(gui->getStelStyle().qtStyleSheet); setStyleSheet(gui->getStelStyle().qtStyleSheet);
connect(&StelApp::getInstance(), SIGNAL(visionNightModeChanged(bool) ), this, SLOT(updateNightModeProperty(bool))); connect(stelApp, SIGNAL(visionNightModeChanged(bool)), this, SLOT(up dateNightModeProperty(bool)));
// I doubt this will have any effect on framerate, but may cause pro blems elsewhere?
QThread::currentThread()->setPriority(QThread::HighestPriority); QThread::currentThread()->setPriority(QThread::HighestPriority);
#ifndef NDEBUG #ifndef NDEBUG
// Get an overview of module callOrders // Get an overview of module callOrders
if (qApp->property("verbose")==true) if (qApp->property("verbose")==true)
{ {
StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionDraw); StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionDraw);
StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionUpdate); StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionUpdate);
StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionHandleMouseClicks); StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionHandleMouseClicks);
StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionHandleMouseMoves); StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionHandleMouseMoves);
StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionHandleKeys); StelApp::getInstance().dumpModuleActionPriorities(StelModule ::ActionHandleKeys);
} }
#endif #endif
startMainLoop();
} }
void StelMainView::updateNightModeProperty(bool b) void StelMainView::updateNightModeProperty(bool b)
{ {
// So that the bottom bar tooltips get properly rendered in night mo de. // So that the bottom bar tooltips get properly rendered in night mo de.
setProperty("nightMode", b); setProperty("nightMode", b);
nightModeEffect->setEnabled(b); nightModeEffect->setEnabled(b);
} }
// This is a series of various diagnostics based on "bugs" reported for 0.1 3.0 and 0.13.1. // This is a series of various diagnostics based on "bugs" reported for 0.1 3.0 and 0.13.1.
// Almost all can be traced to insufficient driver level. // Almost all can be traced to insufficient driver level.
// No changes of OpenGL state is done here. // No changes of OpenGL state is done here.
// If problems are detected, warn the user one time, but continue. Warning panel will be suppressed on next start. // If problems are detected, warn the user one time, but continue. Warning panel will be suppressed on next start.
// Work in progress, as long as we get reports about bad systems or until O penGL startup is finalized and safe. // Work in progress, as long as we get reports about bad systems or until O penGL startup is finalized and safe.
// Several tests do not apply to MacOS X. // Several tests do not apply to MacOS X.
#if STEL_USE_NEW_OPENGL_WIDGETS void StelMainView::processOpenGLdiagnosticsAndWarnings(QSettings *conf, QOp
void StelMainView::processOpenGLdiagnosticsAndWarnings(QSettings *co enGLContext *context) const
nf, StelQOpenGLWidget* glWidget) const
#else
void StelMainView::processOpenGLdiagnosticsAndWarnings(QSettings *co
nf, StelQGLWidget* glWidget) const
#endif
{ {
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
Q_UNUSED(conf); Q_UNUSED(conf);
#endif #endif
QOpenGLContext* context=glWidget->context()->contextHandle();
QSurfaceFormat format=context->format(); QSurfaceFormat format=context->format();
// These tests are not required on MacOS X // These tests are not required on MacOS X
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
bool openGLerror=false; bool openGLerror=false;
if (format.renderableType()==QSurfaceFormat::OpenGL || format.render ableType()==QSurfaceFormat::OpenGLES) if (format.renderableType()==QSurfaceFormat::OpenGL || format.render ableType()==QSurfaceFormat::OpenGLES)
{ {
qDebug() << "Detected:" << (format.renderableType()==QSurfac eFormat::OpenGL ? "OpenGL" : "OpenGL ES" ) << QString("%1.%2").arg(format. majorVersion()).arg(format.minorVersion()); qDebug() << "Detected:" << (format.renderableType()==QSurfac eFormat::OpenGL ? "OpenGL" : "OpenGL ES" ) << QString("%1.%2").arg(format. majorVersion()).arg(format.minorVersion());
} }
else else
{ {
openGLerror=true; openGLerror=true;
qDebug() << "Neither OpenGL nor OpenGL ES detected: Unsuppor ted Format!"; qDebug() << "Neither OpenGL nor OpenGL ES detected: Unsuppor ted Format!";
} }
#endif #endif
QOpenGLFunctions* gl = context->functions();
QString glDriver(reinterpret_cast<const char*>(glGetString(GL_VERSIO N))); QString glDriver(reinterpret_cast<const char*>(gl->glGetString(GL_VE RSION)));
qDebug() << "Driver version string:" << glDriver; qDebug() << "Driver version string:" << glDriver;
qDebug() << "GL vendor is" << QString(reinterpret_cast<const char*>( qDebug() << "GL vendor is" << QString(reinterpret_cast<const char*>(
glGetString(GL_VENDOR))); gl->glGetString(GL_VENDOR)));
QString glRenderer(reinterpret_cast<const char*>(glGetString(GL_REND QString glRenderer(reinterpret_cast<const char*>(gl->glGetString(GL_
ERER))); RENDERER)));
qDebug() << "GL renderer is" << glRenderer; qDebug() << "GL renderer is" << glRenderer;
// Minimal required version of OpenGL for Qt5 is 2.1 and OpenGL Shad ing Language may be 1.20 (or OpenGL ES is 2.0 and GLSL ES is 1.0). // Minimal required version of OpenGL for Qt5 is 2.1 and OpenGL Shad ing Language may be 1.20 (or OpenGL ES is 2.0 and GLSL ES is 1.0).
// As of V0.13.0..1, we use GLSL 1.10/GLSL ES 1.00 (implicitly, by o mitting a #version line), but in case of using ANGLE we need hardware // As of V0.13.0..1, we use GLSL 1.10/GLSL ES 1.00 (implicitly, by o mitting a #version line), but in case of using ANGLE we need hardware
// detected as providing ps_3_0. // detected as providing ps_3_0.
// This means, usually systems with OpenGL3 support reported in the driver will work, those with reported 2.1 only will almost certainly fail. // This means, usually systems with OpenGL3 support reported in the driver will work, those with reported 2.1 only will almost certainly fail.
// If platform does not even support minimal OpenGL version for Qt5, then tell the user about troubles and quit from application. // If platform does not even support minimal OpenGL version for Qt5, then tell the user about troubles and quit from application.
// This test is apparently not applicable on MacOS X due to its beha ving differently from all other known OSes. // This test is apparently not applicable on MacOS X due to its beha ving differently from all other known OSes.
// The correct way to handle driver issues on MacOS X remains howeve r unclear for now. // The correct way to handle driver issues on MacOS X remains howeve r unclear for now.
#ifndef Q_OS_MAC #ifndef Q_OS_MAC
skipping to change at line 746 skipping to change at line 917
QMessageBox::critical(0, "Stellarium", q_("Insufficient Open GL version. Please update drivers, graphics hardware, or use --angle-mode ( or --mesa-mode) option."), QMessageBox::Abort, QMessageBox::Abort); QMessageBox::critical(0, "Stellarium", q_("Insufficient Open GL version. Please update drivers, graphics hardware, or use --angle-mode ( or --mesa-mode) option."), QMessageBox::Abort, QMessageBox::Abort);
#else #else
qWarning() << "Oops... Insufficient OpenGL version. Please u pdate drivers, or graphics hardware."; qWarning() << "Oops... Insufficient OpenGL version. Please u pdate drivers, or graphics hardware.";
QMessageBox::critical(0, "Stellarium", q_("Insufficient Open GL version. Please update drivers, or graphics hardware."), QMessageBox::Ab ort, QMessageBox::Abort); QMessageBox::critical(0, "Stellarium", q_("Insufficient Open GL version. Please update drivers, or graphics hardware."), QMessageBox::Ab ort, QMessageBox::Abort);
#endif #endif
exit(1); exit(1);
} }
#endif #endif
// This call requires OpenGL2+. // This call requires OpenGL2+.
QString glslString(reinterpret_cast<const char*>(glGetString(GL_SHAD ING_LANGUAGE_VERSION))); QString glslString(reinterpret_cast<const char*>(gl->glGetString(GL_ SHADING_LANGUAGE_VERSION)));
qDebug() << "GL Shading Language version is" << glslString; qDebug() << "GL Shading Language version is" << glslString;
// Only give extended info if called on command line, for diagnostic . // Only give extended info if called on command line, for diagnostic .
if (qApp->property("dump_OpenGL_details").toBool()) if (qApp->property("dump_OpenGL_details").toBool())
dumpOpenGLdiagnostics(); dumpOpenGLdiagnostics();
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// If we have ANGLE, check esp. for insufficient ps_2 level. // If we have ANGLE, check esp. for insufficient ps_2 level.
if (isANGLE) if (isANGLE)
{ {
skipping to change at line 1031 skipping to change at line 1202
} }
else else
{ {
qDebug() << "dumpOpenGLdiagnostics(): No OpenGL context"; qDebug() << "dumpOpenGLdiagnostics(): No OpenGL context";
} }
} }
void StelMainView::deinit() void StelMainView::deinit()
{ {
glContextMakeCurrent();
deinitGL(); deinitGL();
delete stelApp; delete stelApp;
stelApp = NULL; stelApp = NULL;
} }
// Update the translated title // Update the translated title
void StelMainView::initTitleI18n() void StelMainView::initTitleI18n()
{ {
QString appNameI18n = q_("Stellarium %1").arg(StelUtils::getApplicat ionVersion()); QString appNameI18n = q_("Stellarium %1").arg(StelUtils::getApplicat ionVersion());
setWindowTitle(appNameI18n); setWindowTitle(appNameI18n);
skipping to change at line 1054 skipping to change at line 1226
{ {
if (b) if (b)
showFullScreen(); showFullScreen();
else else
{ {
showNormal(); showNormal();
// Not enough. If we had started in fullscreen, the inner pa rt of the window is at 0/0, with the frame extending to top/left off screen . // Not enough. If we had started in fullscreen, the inner pa rt of the window is at 0/0, with the frame extending to top/left off screen .
// Therefore moving is not possible. We must move to the sto red position or at least defaults. // Therefore moving is not possible. We must move to the sto red position or at least defaults.
if ( (x()<0) && (y()<0)) if ( (x()<0) && (y()<0))
{ {
QSettings *conf = StelApp::getInstance().getSettings (); QSettings *conf = stelApp->getSettings();
QDesktopWidget *desktop = QApplication::desktop(); QDesktopWidget *desktop = QApplication::desktop();
int screen = conf->value("video/screen_number", 0).t oInt(); int screen = conf->value("video/screen_number", 0).t oInt();
if (screen < 0 || screen >= desktop->screenCount()) if (screen < 0 || screen >= desktop->screenCount())
{ {
qWarning() << "WARNING: screen" << screen << "not found"; qWarning() << "WARNING: screen" << screen << "not found";
screen = 0; screen = 0;
} }
QRect screenGeom = desktop->screenGeometry(screen); QRect screenGeom = desktop->screenGeometry(screen);
int x = conf->value("video/screen_x", 0).toInt(); int x = conf->value("video/screen_x", 0).toInt();
int y = conf->value("video/screen_y", 0).toInt(); int y = conf->value("video/screen_y", 0).toInt();
move(x + screenGeom.x(), y + screenGeom.y()); move(x + screenGeom.x(), y + screenGeom.y());
} }
} }
emit fullScreenChanged(b); emit fullScreenChanged(b);
} }
void StelMainView::updateScene() { void StelMainView::drawEnded()
// For some reason the skyItem is not updated when the night mode sh
ader is on.
// To fix this we manually do it here.
skyItem->update();
scene()->update();
}
void StelMainView::thereWasAnEvent()
{
lastEventTimeSec = StelApp::getTotalRunTime();
}
void StelMainView::maxFpsSceneUpdate()
{ {
updateScene(); updateQueued = false;
flagMaxFpsUpdatePending = false;
}
void StelMainView::drawBackground(QPainter*, const QRectF&) //requeue the next draw
{ if(needsMaxFPS())
const double now = StelApp::getTotalRunTime();
const double JD_SECOND=0.000011574074074074074074;
// Determines when the next display will need to be triggered
// The current policy is that after an event, the FPS is maximum for
2.5 seconds
// after that, it switches back to the default minfps value to save
power.
// The fps is also kept to max if the timerate is higher than normal
speed.
const float timeRate = StelApp::getInstance().getCore()->getTimeRate
();
const bool needMaxFps = (now - lastEventTimeSec < 2.5) || fabs(timeR
ate) > JD_SECOND;
if (needMaxFps)
{ {
if (!flagMaxFpsUpdatePending) updateQueued = true;
{ minFpsTimer->stop();
double duration = 1./getMaxFps(); glWidget->update();
int dur = (int)(duration*1000);
if (minFpsTimer!=NULL)
{
disconnect(minFpsTimer, SIGNAL(timeout()), 0
, 0);
delete minFpsTimer;
minFpsTimer = NULL;
}
flagMaxFpsUpdatePending = true;
QTimer::singleShot(dur<5 ? 5 : dur, this, SLOT(maxFp
sSceneUpdate()));
}
} else if (minFpsTimer == NULL) {
// Restart the minfps timer
minFpsChanged();
}
// Manage cursor timeout
if (cursorTimeout>0.f && (now-lastEventTimeSec>cursorTimeout) && fla
gCursorTimeout)
{
if (QGuiApplication::overrideCursor()==0)
QGuiApplication::setOverrideCursor(Qt::BlankCursor);
} }
else else
{ {
if (QGuiApplication::overrideCursor()!=0) if(!minFpsTimer->isActive())
QGuiApplication::restoreOverrideCursor(); minFpsTimer->start();
} }
} }
void StelMainView::startMainLoop() void StelMainView::minFPSUpdate()
{
// Set a timer refreshing for every minfps frames
minFpsChanged();
}
void StelMainView::minFpsChanged()
{ {
if (minFpsTimer!=NULL) if(!updateQueued)
{ {
disconnect(minFpsTimer, SIGNAL(timeout()), 0, 0); updateQueued = true;
delete minFpsTimer; //qDebug()<<"minFPSUpdate";
minFpsTimer = NULL; glWidget->update();
}
else
{
//qDebug()<<"double update";
} }
minFpsTimer = new QTimer(this);
connect(minFpsTimer, SIGNAL(timeout()), this, SLOT(updateScene()));
minFpsTimer->start((int)(1./getMinFps()*1000.));
} }
void StelMainView::mouseMoveEvent(QMouseEvent* event) #ifdef OPENGL_DEBUG_LOGGING
void StelMainView::logGLMessage(const QOpenGLDebugMessage &debugMessage)
{ {
// We notify the application to increase the fps if a button has bee qDebug()<<debugMessage;
n
// clicked, but also if the cursor is currently hidden, so that it g
ets
// restored.
if (event->buttons() || QGuiApplication::overrideCursor()!=0)
thereWasAnEvent(); // Refresh screen ASAP
QGraphicsView::mouseMoveEvent(event);
} }
void StelMainView::mousePressEvent(QMouseEvent* event) void StelMainView::contextDestroyed()
{ {
thereWasAnEvent(); // Refresh screen ASAP qDebug()<<"Main OpenGL context destroyed";
QGraphicsView::mousePressEvent(event);
} }
#endif
void StelMainView::mouseReleaseEvent(QMouseEvent* event) void StelMainView::thereWasAnEvent()
{ {
thereWasAnEvent(); // Refresh screen ASAP //qDebug()<<"event";
QGraphicsView::mouseReleaseEvent(event); lastEventTimeSec = StelApp::getTotalRunTime();
} }
void StelMainView::wheelEvent(QWheelEvent* event) bool StelMainView::needsMaxFPS() const
{ {
thereWasAnEvent(); // Refresh screen ASAP const double now = StelApp::getTotalRunTime();
QGraphicsView::wheelEvent(event);
// Determines when the next display will need to be triggered
// The current policy is that after an event, the FPS is maximum for
2.5 seconds
// after that, it switches back to the default minfps value to save
power.
// The fps is also kept to max if the timerate is higher than normal
speed.
const float timeRate = stelApp->getCore()->getTimeRate();
return (now - lastEventTimeSec < 2.5) || fabs(timeRate) > StelCore::
JD_SECOND;
} }
void StelMainView::moveEvent(QMoveEvent * event) void StelMainView::moveEvent(QMoveEvent * event)
{ {
Q_UNUSED(event); Q_UNUSED(event);
// We use the glWidget instead of the event, as we want the screen t hat shows most of the widget. // We use the glWidget instead of the event, as we want the screen t hat shows most of the widget.
StelApp::getInstance().setDevicePixelsPerPixel(glWidget->windowHandl QWindow* win = glWidget->windowHandle();
e()->devicePixelRatio()); if(win)
stelApp->setDevicePixelsPerPixel(win->devicePixelRatio());
} }
void StelMainView::closeEvent(QCloseEvent* event) void StelMainView::closeEvent(QCloseEvent* event)
{ {
Q_UNUSED(event); Q_UNUSED(event);
StelApp::getInstance().quit(); stelApp->quit();
}
void StelMainView::keyPressEvent(QKeyEvent* event)
{
thereWasAnEvent(); // Refresh screen ASAP
// Try to trigger a gobal shortcut.
StelActionMgr* actionMgr = StelApp::getInstance().getStelActionManag
er();
if (actionMgr->pushKey(event->key() + event->modifiers(), true)) {
event->setAccepted(true);
return;
}
QGraphicsView::keyPressEvent(event);
}
void StelMainView::keyReleaseEvent(QKeyEvent* event)
{
thereWasAnEvent(); // Refresh screen ASAP
QGraphicsView::keyReleaseEvent(event);
} }
//! Delete openGL textures (to call before the GLContext disappears) //! Delete openGL textures (to call before the GLContext disappears)
void StelMainView::deinitGL() void StelMainView::deinitGL()
{ {
StelApp::getInstance().deinit(); //fix for bug 1628072 caused by QTBUG-56798
#ifndef QT_NO_DEBUG
StelOpenGL::clearGLErrors();
#endif
stelApp->deinit();
delete gui; delete gui;
gui = NULL; gui = NULL;
} }
void StelMainView::saveScreenShot(const QString& filePrefix, const QString& saveDir, const bool overwrite) void StelMainView::saveScreenShot(const QString& filePrefix, const QString& saveDir, const bool overwrite)
{ {
screenShotPrefix = filePrefix; screenShotPrefix = filePrefix;
screenShotDir = saveDir; screenShotDir = saveDir;
flagOverwriteScreenshots=overwrite; flagOverwriteScreenshots=overwrite;
emit(screenshotRequested()); emit(screenshotRequested());
} }
void StelMainView::doScreenshot(void) void StelMainView::doScreenshot(void)
{ {
QFileInfo shotDir; QFileInfo shotDir;
#if STEL_USE_NEW_OPENGL_WIDGETS #ifdef USE_OLD_QGLWIDGET
QImage im = glWidget->grabFramebuffer();
#else
QImage im = glWidget->grabFrameBuffer(); QImage im = glWidget->grabFrameBuffer();
#else
glWidget->makeCurrent();
QOpenGLFramebufferObjectFormat fbFormat;
fbFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStenci
l);
QOpenGLFramebufferObject * fbObj = new QOpenGLFramebufferObject(stel
Scene->width(), stelScene->height(), fbFormat);
fbObj->bind();
QOpenGLPaintDevice fbObjPaintDev(stelScene->width(), stelScene->heig
ht());
QPainter painter(&fbObjPaintDev);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntial
iasing);
stelScene->render(&painter);
painter.end();
QImage im = fbObj->toImage();
fbObj->release();
delete fbObj;
#endif #endif
if (flagInvertScreenShotColors) if (flagInvertScreenShotColors)
im.invertPixels(); im.invertPixels();
if (screenShotDir == "") if (screenShotDir == "")
shotDir = QFileInfo(StelFileMgr::getScreenshotDir()); shotDir = QFileInfo(StelFileMgr::getScreenshotDir());
else else
shotDir = QFileInfo(screenShotDir); shotDir = QFileInfo(screenShotDir);
if (!shotDir.isDir()) if (!shotDir.isDir())
{ {
skipping to change at line 1283 skipping to change at line 1407
if (!im.save(shotPath.filePath())) { if (!im.save(shotPath.filePath())) {
qWarning() << "WARNING failed to write screenshot to: " << Q Dir::toNativeSeparators(shotPath.filePath()); qWarning() << "WARNING failed to write screenshot to: " << Q Dir::toNativeSeparators(shotPath.filePath());
} }
} }
QPoint StelMainView::getMousePos() QPoint StelMainView::getMousePos()
{ {
return glWidget->mapFromGlobal(QCursor::pos()); return glWidget->mapFromGlobal(QCursor::pos());
} }
void StelMainView::setFocusOnSky() QOpenGLContext* StelMainView::glContext() const
{
#ifdef USE_OLD_QGLWIDGET
return glWidget->context()->contextHandle();
#else
return glWidget->context();
#endif
}
void StelMainView::glContextMakeCurrent()
{
glWidget->makeCurrent();
}
void StelMainView::glContextDoneCurrent()
{ {
skyItem->setFocus(); glWidget->doneCurrent();
} }
 End of changes. 129 change blocks. 
588 lines changed or deleted 736 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/