1 /* 2 * Stellarium 3 * Copyright (C) 2007 Fabien Chereau 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. 18 */ 19 20 #ifndef STELMAINVIEW_HPP 21 #define STELMAINVIEW_HPP 22 23 #include <QCoreApplication> 24 #include <QGraphicsView> 25 #include <QEventLoop> 26 #include <QOpenGLContext> 27 #include <QTimer> 28 #ifdef OPENGL_DEBUG_LOGGING 29 #include <QOpenGLDebugMessage> 30 #endif 31 #include "StelUtils.hpp" 32 33 class StelGLWidget; 34 class StelGraphicsScene; 35 class QMoveEvent; 36 class QResizeEvent; 37 class StelGuiBase; 38 class QMoveEvent; 39 class QSettings; 40 41 //! @class StelMainView 42 //! Reimplement a QGraphicsView for Stellarium. 43 //! It is the class creating the singleton GL Widget, the main StelApp instance as well as the main GUI. 44 class StelMainView : public QGraphicsView 45 { 46 friend class StelGuiItem; 47 friend class StelRootItem; 48 friend class StelGraphicsScene; 49 friend class NightModeGraphicsEffect; 50 Q_OBJECT 51 Q_PROPERTY(bool fullScreen READ isFullScreen WRITE setFullScreen NOTIFY fullScreenChanged) 52 Q_PROPERTY(bool flagInvertScreenShotColors READ getFlagInvertScreenShotColors WRITE setFlagInvertScreenShotColors NOTIFY flagInvertScreenShotColorsChanged) 53 Q_PROPERTY(bool flagOverwriteScreenshots READ getFlagOverwriteScreenShots WRITE setFlagOverwriteScreenShots NOTIFY flagOverwriteScreenshotsChanged) 54 Q_PROPERTY(bool flagUseCustomScreenshotSize READ getFlagUseCustomScreenshotSize WRITE setFlagUseCustomScreenshotSize NOTIFY flagUseCustomScreenshotSizeChanged) 55 Q_PROPERTY(int customScreenshotWidth READ getCustomScreenshotWidth WRITE setCustomScreenshotWidth NOTIFY customScreenshotWidthChanged) 56 Q_PROPERTY(int customScreenshotHeight READ getCustomScreenshotHeight WRITE setCustomScreenshotHeight NOTIFY customScreenshotHeightChanged) 57 Q_PROPERTY(QString screenShotFormat READ getScreenshotFormat WRITE setScreenshotFormat NOTIFY screenshotFormatChanged) 58 Q_PROPERTY(bool flagCursorTimeout READ getFlagCursorTimeout WRITE setFlagCursorTimeout NOTIFY flagCursorTimeoutChanged) 59 Q_PROPERTY(double cursorTimeout READ getCursorTimeout WRITE setCursorTimeout NOTIFY cursorTimeoutChanged) 60 Q_PROPERTY(Vec3f skyBackgroundColor READ getSkyBackgroundColor WRITE setSkyBackgroundColor NOTIFY skyBackgroundColorChanged) 61 62 public: 63 //! Contains some basic info about the OpenGL context used 64 struct GLInfo 65 { 66 QString vendor; 67 QString renderer; 68 QOpenGLContext* mainContext; 69 QOpenGLFunctions* functions; 70 }; 71 72 StelMainView(QSettings* settings); 73 virtual ~StelMainView() Q_DECL_OVERRIDE; 74 75 //! Start the main initialization of Stellarium 76 void init(); 77 void deinit(); 78 79 //! Set the application title for the current language. 80 //! This is useful for e.g. chinese. 81 void initTitleI18n(); 82 83 //! Get the StelMainView singleton instance. getInstance()84 static StelMainView& getInstance() {Q_ASSERT(singleton); return *singleton;} 85 86 //! Delete openGL textures (to call before the GLContext disappears) 87 void deinitGL(); 88 89 //! Return the parent gui widget, this should be used as parent to all 90 //! the StelDialog instances. getGuiWidget() const91 QGraphicsWidget* getGuiWidget() const {return guiItem;} 92 //! Return mouse position coordinates 93 QPoint getMousePos() const; 94 95 //! Returns the main application OpenGL context, 96 //! which should be used for all drawing Stellarium does 97 //! @sa glContextMakeCurrent() 98 //! @sa glContextDoneCurrent() 99 QOpenGLContext* glContext() const; 100 //! Make the main GL context (the one returned from glContext()) current 101 //! on the main view surface 102 void glContextMakeCurrent(); 103 //! Releases the main GL context 104 void glContextDoneCurrent(); 105 106 //! Returns the information about the GL context, this does not require the context to be active. getGLInformation() const107 GLInfo getGLInformation() const { return glInfo; } 108 public slots: 109 110 //! Set whether fullscreen is activated or not 111 void setFullScreen(bool); 112 113 //! Return focus to the sky item. To be used when we close a dialog. 114 void focusSky(); 115 116 /////////////////////////////////////////////////////////////////////////// 117 // Specific methods 118 //! Save a screen shot. 119 //! The format of the file, and hence the filename extension 120 //! depends on the architecture and build type. 121 //! @arg filePrefix changes the beginning of the file name 122 //! @arg saveDir changes the directory where the screenshot is saved 123 //! If saveDir is "" then StelFileMgr::getScreenshotDir() will be used 124 //! @arg overwrite if true, @arg filePrefix is used as filename, and existing file will be overwritten. 125 //! @note To set file type, use setScreenshotFormat() first. 126 void saveScreenShot(const QString& filePrefix="stellarium-", const QString& saveDir="", const bool overwrite=false); 127 //! @arg filetype is the preferred file type (ending) like "png", "jpg", "bmp" etc. 128 //! The supported filetypes depend on the underlying Qt version. 129 //! The most popular may be PNG, JPG/JPEG, BMP, TIF (LZW compressed), TIFF (uncompressed), WEBP, 130 //! but as of Qt5.12, we also have ICO (for thumbnails), PBM (Portable Bitmap), PGM (Portable Graymap), PPM (Portable Pixmap), 131 //! XBM (X Bitmap) and XPM (X Pixmap). 132 void setScreenshotFormat(const QString filetype); getScreenshotFormat() const133 QString getScreenshotFormat() const {return screenShotFormat;} 134 135 //! Get whether colors are inverted when saving screenshot getFlagInvertScreenShotColors() const136 bool getFlagInvertScreenShotColors() const {return flagInvertScreenShotColors;} 137 //! Set whether colors should be inverted when saving screenshot setFlagInvertScreenShotColors(bool b)138 void setFlagInvertScreenShotColors(bool b) {flagInvertScreenShotColors=b; emit flagInvertScreenShotColorsChanged(b);} 139 140 //! Get whether existing files are overwritten when saving screenshot getFlagOverwriteScreenShots() const141 bool getFlagOverwriteScreenShots() const {return flagOverwriteScreenshots;} 142 //! Set whether existing files are overwritten when saving screenshot setFlagOverwriteScreenShots(bool b)143 void setFlagOverwriteScreenShots(bool b) {flagOverwriteScreenshots=b; emit flagOverwriteScreenshotsChanged(b);} 144 145 //! Get whether custom size should be used for screenshots getFlagUseCustomScreenshotSize() const146 bool getFlagUseCustomScreenshotSize() const {return flagUseCustomScreenshotSize;} 147 //! Set whether custom size should be used for screenshots setFlagUseCustomScreenshotSize(bool b)148 void setFlagUseCustomScreenshotSize(bool b) {flagUseCustomScreenshotSize=b; emit flagUseCustomScreenshotSizeChanged(b);} 149 //! Get custom screenshot width getCustomScreenshotWidth() const150 int getCustomScreenshotWidth() const {return customScreenshotWidth;} 151 //! Set whether custom size should be used for screenshots setCustomScreenshotWidth(int width)152 void setCustomScreenshotWidth(int width) {customScreenshotWidth=width; emit customScreenshotWidthChanged(width);} 153 //! Get custom screenshot height getCustomScreenshotHeight() const154 int getCustomScreenshotHeight() const {return customScreenshotHeight;} 155 //! Set whether custom size should be used for screenshots setCustomScreenshotHeight(int height)156 void setCustomScreenshotHeight(int height) {customScreenshotHeight=height; emit customScreenshotHeightChanged(height);} 157 //! Get screenshot magnification. This should be used by StarMgr, text drawing and other elements which may 158 //! want to enlarge their output in screenshots to keep them visible. getCustomScreenshotMagnification() const159 float getCustomScreenshotMagnification() const {return customScreenshotMagnification;} 160 //! Get the state of the mouse cursor timeout flag getFlagCursorTimeout() const161 bool getFlagCursorTimeout() const {return flagCursorTimeout;} 162 //! Set the state of the mouse cursor timeout flag 163 void setFlagCursorTimeout(bool b); 164 //! Get the mouse cursor timeout in seconds getCursorTimeout() const165 double getCursorTimeout() const {return cursorTimeoutTimer->interval() / 1000.0;} 166 //! Set the mouse cursor timeout in seconds setCursorTimeout(double t)167 void setCursorTimeout(double t) {cursorTimeoutTimer->setInterval(static_cast<int>(t * 1000)); emit cursorTimeoutChanged(t);} 168 169 //! Set the minimum frames per second. Usually this minimum will be switched to after there are no 170 //! user events for some seconds to save power. However, if can be useful to set this to a high 171 //! value to improve playing smoothness in scripts. 172 //! @param m the new minimum fps setting. setMinFps(float m)173 void setMinFps(float m) {minfps=m;} 174 //! Get the current minimum frames per second. getMinFps() const175 float getMinFps() const {return minfps;} 176 //! Set the maximum frames per second. 177 //! @param m the new maximum fps setting. 178 //! @todo this setting currently does nothing setMaxFps(float m)179 void setMaxFps(float m) {maxfps = m;} 180 //! Get the current maximum frames per second. getMaxFps() const181 float getMaxFps() const {return maxfps;} 182 183 //! Notify that an event was handled by the program and therefore the 184 //! FPS should be maximized for a couple of seconds. 185 void thereWasAnEvent(); 186 187 //! Determines if we should render as fast as possible, 188 //! or limit the FPS. This depends on the time the last user event 189 //! happened. 190 bool needsMaxFPS() const; 191 192 //! Set the sky background color. (Actually forwards to the StelRootItem.) Everything else than black creates a work of art! 193 void setSkyBackgroundColor(Vec3f color); 194 //! Get the sky background color. (Actually retrieves from the StelRootItem.) Everything else than black creates a work of art! 195 Vec3f getSkyBackgroundColor() const; 196 197 protected: 198 //! Hack to determine current monitor pixel ratio 199 //! @todo Find a better way to handle this 200 virtual void moveEvent(QMoveEvent* event) Q_DECL_OVERRIDE; 201 //! Handle window closed event, calling StelApp::quit() 202 virtual void closeEvent(QCloseEvent* event) Q_DECL_OVERRIDE; 203 //! Handle window resized events, and change the size of the underlying 204 //! QGraphicsScene to be the same 205 virtual void resizeEvent(QResizeEvent* event) Q_DECL_OVERRIDE; 206 //! Wake up mouse cursor (if it was hidden) 207 virtual void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; 208 209 bool eventFilter(QObject *obj, QEvent *event) override; 210 signals: 211 //! emitted when saveScreenShot is requested with saveScreenShot(). 212 //! doScreenshot() does the actual work (it has to do it in the main 213 //! thread, where as saveScreenShot() might get called from another one. 214 //! 215 //! @remark FS: is threaded access here even a possibility anymore, or a remnant of older code? 216 void screenshotRequested(void); 217 void fullScreenChanged(bool b); 218 //! Emitted when the "Reload shaders" action is perfomed 219 //! Interested objects should subscribe to this signal and reload their shaders 220 //! when this is emitted 221 void reloadShadersRequested(); 222 223 void updateIconsRequested(); 224 void flagInvertScreenShotColorsChanged(bool b); 225 void flagOverwriteScreenshotsChanged(bool b); 226 void flagUseCustomScreenshotSizeChanged(bool use); 227 void customScreenshotWidthChanged(int width); 228 void customScreenshotHeightChanged(int height); 229 void screenshotFormatChanged(QString format); 230 231 void skyBackgroundColorChanged(Vec3f color); 232 233 void flagCursorTimeoutChanged(bool b); 234 void cursorTimeoutChanged(double t); 235 236 private slots: 237 // Do the actual screenshot generation in the main thread with this method. 238 void doScreenshot(void); 239 240 void fpsTimerUpdate(); 241 void hideCursor(); 242 243 #ifdef OPENGL_DEBUG_LOGGING 244 void logGLMessage(const QOpenGLDebugMessage& debugMessage); 245 void contextDestroyed(); 246 #endif 247 void updateNightModeProperty(bool b); 248 249 void reloadShaders(); 250 251 private: 252 //! The graphics scene notifies us when a draw finished, so that we can queue the next one 253 void drawEnded(); 254 //! Returns the desired OpenGL format settings, 255 //! on desktop this corresponds to a GL 2.1 context, 256 //! with 32bit RGBA buffer and 24/8 depth/stencil buffer 257 QSurfaceFormat getDesiredGLFormat() const; 258 //! provide extended OpenGL diagnostics in logfile. 259 void dumpOpenGLdiagnostics() const; 260 //! Startup diagnostics, providing test for various circumstances of bad OS/OpenGL driver combinations 261 //! to provide feedback to the user about bad OpenGL drivers. 262 void processOpenGLdiagnosticsAndWarnings(QSettings *conf, QOpenGLContext* context) const; 263 264 //! The StelMainView singleton 265 static StelMainView* singleton; 266 267 GLInfo glInfo; 268 269 QSettings* configuration; 270 271 class StelRootItem* rootItem; 272 QGraphicsWidget* guiItem; 273 QGraphicsEffect* nightModeEffect; 274 275 //! The openGL viewport of the graphics scene 276 //! Responsible for main GL setup, rendering is done in the scene background 277 StelGLWidget* glWidget; 278 //! Custom QGraphicsScene, this renders our scene background 279 StelGraphicsScene* stelScene; 280 281 StelGuiBase* gui; 282 class StelApp* stelApp; 283 284 bool updateQueued; 285 bool flagInvertScreenShotColors; 286 bool flagOverwriteScreenshots; //! if set to true, screenshot is named exactly screenShotPrefix.png and overwrites existing file 287 bool flagUseCustomScreenshotSize; //! if true, the next 2 values are observed for screenshots. 288 int customScreenshotWidth; //! used when flagCustomResolutionScreenshots==true 289 int customScreenshotHeight; //! used when flagCustomResolutionScreenshots==true 290 float customScreenshotMagnification; //! tracks the magnification factor customScreenshotHeight/NormalWindowHeight 291 QString screenShotPrefix; 292 QString screenShotFormat; //! file type like "png" or "jpg". 293 QString screenShotDir; 294 295 bool flagCursorTimeout; 296 //! Timer that triggers with the cursor timeout. 297 QTimer* cursorTimeoutTimer; 298 299 double lastEventTimeSec; 300 301 //! The minimum desired frame rate in frame per second. 302 float minfps; 303 //! The maximum desired frame rate in frame per second. 304 float maxfps; 305 QTimer* fpsTimer; 306 307 #ifdef OPENGL_DEBUG_LOGGING 308 QOpenGLDebugLogger* glLogger; 309 #endif 310 }; 311 312 313 #endif // STELMAINVIEW_HPP 314