diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c38acdab..b9eedc84b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,178 +1,178 @@ PROJECT(kstars CXX C) set (KStars_VERSION_MAJOR 2) set (KStars_VERSION_MINOR 7) set (KStars_VERSION_REVISION 0) set (CMAKE_CXX_STANDARD 11) #Build KStars Lite with -DKSTARS_LITE=ON option(BUILD_KSTARS_LITE "Build KStars Lite" OFF) if(BUILD_KSTARS_LITE) add_definitions(-DKSTARS_LITE) endif(BUILD_KSTARS_LITE) # minimal requirements cmake_minimum_required (VERSION 2.8.12 FATAL_ERROR) if(BUILD_KSTARS_LITE) set (QT_MIN_VERSION "5.7.0") #QtQuickControls 2 is available only in the Qt 5.7.0 else() set (QT_MIN_VERSION "5.4.0") endif() # Find includes in corresponding build directories set(CMAKE_INCLUDE_CURRENT_DIR ON) # Instruct CMake to run moc automatically when needed. set(CMAKE_AUTOMOC ON) if(CMAKE_SYSTEM_NAME STREQUAL Android) add_definitions(-DANDROID ) set(ANDROID TRUE) endif() find_package(ECM 1.7.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" ${CMAKE_MODULE_PATH}) if(BUILD_KSTARS_LITE) find_package(Qt5 5.7 REQUIRED COMPONENTS Gui Qml Quick QuickControls2 Xml Svg Sql Network Positioning) else() find_package(Qt5 5.4 REQUIRED COMPONENTS Gui Qml Quick Xml Sql Svg Network PrintSupport Concurrent) endif() include(ECMInstallIcons) include(ECMAddAppIcon) include(KDEInstallDirs) if(NOT ANDROID) #We get error "could not find main method" with this module include(KDECompilerSettings NO_POLICY_SCOPE) endif() include(KDECMakeSettings) include(FeatureSummary) # Load the frameworks we need if(BUILD_KSTARS_LITE) find_package(KF5 REQUIRED COMPONENTS Config I18n Plotting ) if(ANDROID) find_package(OpenMP REQUIRED) #Needed for LibRaw if(OPENMP_FOUND) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") endif() include_directories(SYSTEM ${OpenMP_INCLUDE_PATH}) endif() else(BUILD_KSTARS_LITE) find_package(KF5 REQUIRED COMPONENTS Config Crash DocTools WidgetsAddons NewStuff I18n KIO XmlGui Plotting Notifications #IconThemes ) endif(BUILD_KSTARS_LITE) find_package(Eigen3 REQUIRED) add_definitions(${EIGEN_DEFINITIONS}) include_directories(${EIGEN3_INCLUDE_DIR}) if(BUILD_KSTARS_LITE) - find_package(CFitsio) #REQUIRED) + find_package(CFitsio REQUIRED) else() find_package(CFitsio) endif() if (CFITSIO_FOUND) set(HAVE_CFITSIO 1) else(CFITSIO_FOUND) set(HAVE_CFITSIO 0) endif(CFITSIO_FOUND) set_package_properties(CFitsio PROPERTIES DESCRIPTION "FITS IO Library" URL "http://heasarc.gsfc.nasa.gov/fitsio/fitsio.html" TYPE OPTIONAL PURPOSE "Support for the FITS (Flexible Image Transport System) data format in KStars.") find_package(INDI 1.2.0) #FIXME is there a better way to do this? if (INDI_FOUND) SET(HAVE_INDI 1) else(INDI_FOUND) SET(HAVE_INDI 0) endif(INDI_FOUND) set_package_properties(INDI PROPERTIES DESCRIPTION "Astronomical instrumentation control" URL "http://www.indilib.org" TYPE OPTIONAL PURPOSE "Support for controlling astronomical devices on Linux with KStars.") find_package(LibRaw) if (LibRaw_FOUND) SET(HAVE_LIBRAW 1) else (LibRaw_FOUND) SET(HAVE_LIBRAW 0) endif(LibRaw_FOUND) set_package_properties(LibRaw PROPERTIES DESCRIPTION "Library for reading RAW files" URL "http://www.libraw.org" TYPE OPTIONAL PURPOSE "Support for reading and displaying RAW files in KStars.") find_package(WCSLIB) if (WCSLIB_FOUND) set(HAVE_WCSLIB 1) else(WCSLIB_FOUND) set(HAVE_WCSLIB 0) endif(WCSLIB_FOUND) set_package_properties(WCSLIB PROPERTIES DESCRIPTION "World Coordinate System library" URL "http://www.atnf.csiro.au/people/mcalabre/WCS" TYPE OPTIONAL PURPOSE "WCS enables KStars to read and process world coordinate systems in FITS header.") find_package(Xplanet) if (XPLANET_FOUND) set(HAVE_XPLANET 1) else(XPLANET_FOUND) set(HAVE_XPLANET 0) endif(XPLANET_FOUND) set_package_properties(Xplanet PROPERTIES DESCRIPTION "Renders an image of all the major planets and most satellites" URL "http://xplanet.sourceforge.net" TYPE OPTIONAL PURPOSE "Gives KStars support for xplanet.") find_package(AstrometryNet) if (ASTROMETRYNET_FOUND) set(HAVE_ASTROMETRYNET 1) else(ASTROMETRYNET_FOUND) set(HAVE_ASTROMETRYNET 0) endif(ASTROMETRYNET_FOUND) set_package_properties(AstrometryNet PROPERTIES DESCRIPTION "Astrometrics Library" URL "http://www.astrometry.net" TYPE OPTIONAL PURPOSE "Support for plate solving in KStars.") find_package(OpenGL) set_package_properties(OpenGL PROPERTIES DESCRIPTION "Open Graphics Library" URL "http://www.opengl.org" TYPE OPTIONAL PURPOSE "Support for hardware rendering in KStars.") if (${KF5_VERSION} VERSION_EQUAL 5.18.0 OR ${KF5_VERSION} VERSION_GREATER 5.18.0) SET(HAVE_KF5WIT 1) else() SET(HAVE_KF5WIT 0) endif() add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS) add_definitions(-DQT_NO_URL_CAST_FROM_STRING) if (UNIX) add_definitions(-Dfexceptions) endif(UNIX) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config-kstars.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kstars.h ) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/kstars/version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kstars/version.h ) # let our config.h be found first in any case include_directories (BEFORE ${CMAKE_CURRENT_BINARY_DIR}) add_subdirectory(doc) add_subdirectory(kstars) add_subdirectory(datahandlers) if(NOT BUILD_KSTARS_LITE) enable_testing(true) add_subdirectory(Tests) endif(NOT BUILD_KSTARS_LITE) install(FILES org.kde.kstars.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/kstars/fitsviewer/fitsviewlite.cpp b/kstars/fitsviewer/fitsviewlite.cpp index dc5f556ed..fc5d95ee9 100644 --- a/kstars/fitsviewer/fitsviewlite.cpp +++ b/kstars/fitsviewer/fitsviewlite.cpp @@ -1,254 +1,252 @@ /*************************************************************************** FITSViewLite.cpp - FITS Image ------------------- begin : Fri Jul 22 2016 copyright : (C) 2016 by Jasem Mutlaq and Artem Fedoskin email : mutlaqja@ikarustech.com, afedoskin3@gmail.com ***************************************************************************/ /*************************************************************************** * * * This program 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; either version 2 of the License, or * * (at your option) any later version. * * * * Some code fragments were adapted from Peter Kirchgessner's FITS plugin* * See http://members.aol.com/pkirchg for more details. * ***************************************************************************/ #include #include #include #include #include "fitsviewlite.h" #include "kstarsdata.h" #include "ksutils.h" #include "Options.h" -#ifdef HAVE_INDI #include #include "indi/indilistener.h" #include "indi/indistd.h" #include "indi/driverinfo.h" -#endif #include #define ZOOM_DEFAULT 100.0 #define ZOOM_MIN 10 #define ZOOM_MAX 400 #define ZOOM_LOW_INCR 10 #define ZOOM_HIGH_INCR 50 #define DECAY_CONSTANT -0.04 FITSViewLite::FITSViewLite(FITSMode fitsMode, FITSScale filterType) :zoomFactor(1.2) { image_data = NULL; display_image = NULL; firstLoad = true; gammaValue=0; filter = filterType; mode = fitsMode; markerCrosshair.setX(0); markerCrosshair.setY(0); currentZoom = 0.0; markStars = false; } FITSViewLite::~FITSViewLite() { delete(image_data); delete(display_image); } QImage *FITSViewLite::loadFITS (const QString &inFilename , bool silent) { bool setBayerParams=false; BayerParams param; if (image_data && image_data->hasDebayer()) { setBayerParams=true; image_data->getBayerParams(¶m); } delete (image_data); image_data = NULL; image_data = new FITSDataLite(mode); if (setBayerParams) image_data->setBayerParams(¶m); if (mode == FITS_NORMAL) { /*fitsProg.setWindowModality(Qt::WindowModal); fitsProg.setLabelText(i18n("Please hold while loading FITS file...")); fitsProg.setWindowTitle(i18n("Loading FITS")); fitsProg.setValue(10); qApp->processEvents();*/ } if (image_data->loadFITS(inFilename, silent) == false) return false; image_data->getDimensions(¤tWidth, ¤tHeight); image_width = currentWidth; image_height = currentHeight; hasWCS = image_data->hasWCS(); maxPixel = image_data->getMax(); minPixel = image_data->getMin(); if (gammaValue != 0 && (filter== FITS_NONE || filter >= FITS_FLIP_H)) { double maxGammaPixel = maxPixel* (100 * exp(DECAY_CONSTANT * gammaValue))/100.0; // If calculated maxPixel after gamma is different from image data max pixel, then we apply filter immediately. image_data->applyFilter(FITS_LINEAR, NULL, minPixel, maxGammaPixel); } initDisplayImage(); if(rescale()) { return display_image; } return NULL; } int FITSViewLite::saveFITS( const QString &newFilename ) { return image_data->saveFITS(newFilename); } bool FITSViewLite::rescale() { double val=0; double bscale, bzero; double min, max; unsigned int size = image_data->getSize(); image_data->getMinMax(&min, &max); calculateMaxPixel(min, max); min = minPixel; max = maxGammaPixel; if (min == max) { display_image->fill(Qt::white); //emit newStatus(i18n("Image is saturated!"), FITS_MESSAGE); } else { bscale = 255. / (max - min); bzero = (-min) * (255. / (max - min)); if (image_height != image_data->getHeight() || image_width != image_data->getWidth()) { image_width = image_data->getWidth(); image_height = image_data->getHeight(); initDisplayImage(); //if (isVisible()) //emit newStatus(QString("%1x%2").arg(image_width).arg(image_height), FITS_RESOLUTION); } currentWidth = display_image->width(); currentHeight = display_image->height(); float *image_buffer = image_data->getImageBuffer(); if (image_data->getNumOfChannels() == 1) { /* Fill in pixel values using indexed map, linear scale */ for (int j = 0; j < image_height; j++) { unsigned char *scanLine = display_image->scanLine(j); for (int i = 0; i < image_width; i++) { val = image_buffer[j * image_width + i]; if (gammaValue > 0) val = qBound(minPixel, val, maxGammaPixel); scanLine[i]= (val * bscale + bzero); } } return true; } else { double rval=0,gval=0,bval=0; QRgb value; /* Fill in pixel values using indexed map, linear scale */ for (int j = 0; j < image_height; j++) { QRgb *scanLine = reinterpret_cast((display_image->scanLine(j))); for (int i = 0; i < image_width; i++) { rval = image_buffer[j * image_width + i]; gval = image_buffer[j * image_width + i + size]; bval = image_buffer[j * image_width + i + size * 2]; if (gammaValue > 0) { rval = qBound(minPixel, rval, maxGammaPixel); gval = qBound(minPixel, gval, maxGammaPixel); gval = qBound(minPixel, gval, maxGammaPixel); } value = qRgb(rval* bscale + bzero, gval* bscale + bzero, bval* bscale + bzero); //display_image->setPixel(i, j, value); scanLine[i] = value; } } return true; } } //if (type != ZOOM_KEEP_LEVEL) //emit newStatus(QString("%1%").arg(currentZoom), FITS_ZOOM); return false; } void FITSViewLite::calculateMaxPixel(double min, double max) { minPixel=min; maxPixel=max; if (gammaValue == 0) maxGammaPixel = maxPixel; else maxGammaPixel = maxPixel* (100 * exp(DECAY_CONSTANT * gammaValue))/100.0; } void FITSViewLite::initDisplayImage() { delete (display_image); display_image = NULL; if (image_data->getNumOfChannels() == 1) { display_image = new QImage(image_width, image_height, QImage::Format_Indexed8); display_image->setColorCount(256); for (int i=0; i < 256; i++) display_image->setColor(i, qRgb(i,i,i)); } else { display_image = new QImage(image_width, image_height, QImage::Format_RGB32); } } diff --git a/kstars/kstarslite.cpp b/kstars/kstarslite.cpp index f1afcb702..0e3e4195e 100644 --- a/kstars/kstarslite.cpp +++ b/kstars/kstarslite.cpp @@ -1,463 +1,459 @@ /** ************************************************************************* kstarslite.cpp - K Desktop Planetarium ------------------- begin : 30/04/2016 copyright : (C) 2016 by Artem Fedoskin email : afedoskin3@gmail.com ***************************************************************************/ /** ************************************************************************* * * * This program 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; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "kstarslite.h" #include "skymaplite.h" #include "kstarsdata.h" #include #include #include #include #include #include "kstarslite/imageprovider.h" #include "klocalizedcontext.h" #include "ksplanetbase.h" #include -#ifdef HAVE_INDI #include "indi/clientmanagerlite.h" -#endif #include "kspaths.h" //Dialogs #include "kstarslite/dialogs/finddialoglite.h" #include "kstarslite/dialogs/detaildialoglite.h" #include "kstarslite/dialogs/locationdialoglite.h" #include "Options.h" #include "ksutils.h" KStarsLite *KStarsLite::pinstance = 0; KStarsLite::KStarsLite( bool doSplash, bool startClock, const QString &startDateString) { // Initialize logging settings /*if (Options::disableLogging()) KSUtils::Logging::Disable(); else if (Options::logToFile() && Options::verboseLogFile().isEmpty() == false) KSUtils::Logging::UseFile(Options::verboseLogFile()); else KSUtils::Logging::UseDefault();*/ // Set pinstance to yourself // Unlike KStars class we set pinstance at the beginning because SkyMapLite needs access to ClientManagerLite pinstance = this; m_KStarsData = KStarsData::Create(); Q_ASSERT( m_KStarsData ); -#ifdef HAVE_INDI //INDI Android Client m_clientManager = new ClientManagerLite; m_Engine.rootContext()->setContextProperty("ClientManagerLite", m_clientManager); -#endif //Make instance of KStarsLite and KStarsData available to QML m_Engine.rootContext()->setContextProperty("KStarsLite", this); m_Engine.rootContext()->setContextProperty("KStarsData", m_KStarsData); m_Engine.rootContext()->setContextProperty("Options", Options::self()); m_Engine.rootContext()->setContextProperty("SimClock", m_KStarsData->clock()); m_Engine.rootContext()->setContextObject(new KLocalizedContext(this)); qmlRegisterUncreatableType("KStarsLiteEnums", 1, 0, "Projection", "Provides Projection enum"); qmlRegisterUncreatableType("KStarsLiteEnums", 1, 0, "ObjectsToToggle", "Enum for togglint the visibility of sky objects"); //Dialogs m_findDialogLite = new FindDialogLite; m_detailDialogLite = new DetailDialogLite; m_locationDialogLite = new LocationDialogLite; m_Engine.rootContext()->setContextProperty("FindDialogLite", m_findDialogLite); m_Engine.rootContext()->setContextProperty("DetailDialogLite", m_detailDialogLite); m_Engine.rootContext()->setContextProperty("LocationDialogLite", m_locationDialogLite); //Set Geographic Location from Options m_KStarsData->setLocationFromOptions(); //Set style - default is Material QQuickStyle::setStyle("Material"); #ifdef Q_OS_ANDROID QString main = KSPaths::locate(QStandardPaths::AppDataLocation, "kstarslite/qml/main.qml"); #else QString main = QString(QML_IMPORT) + QString("/kstarslite/qml/main.qml"); #endif /*SkyMapLite has to be loaded before KStarsData is initialized because SkyComponents derived classes have to add SkyItems to the SkyMapLite*/ m_SkyMapLite = SkyMapLite::createInstance(); m_Engine.rootContext()->setContextProperty("SkyMapLite", m_SkyMapLite); m_Engine.load(QUrl(main)); Q_ASSERT_X(m_Engine.rootObjects().size(),"loading root object of main.qml", "QML file was not loaded. Probably syntax error or failed module import."); m_RootObject = m_Engine.rootObjects()[0]; QQuickItem *skyMapLiteWrapper = m_RootObject->findChild("skyMapLiteWrapper"); m_SkyMapLite->initialize(skyMapLiteWrapper); m_detailDialogLite->initialize(); m_imgProvider = new ImageProvider; m_Engine.addImageProvider(QLatin1String("images"), m_imgProvider); QQuickWindow *mainWindow = static_cast(m_Engine.rootObjects()[0]); QSurfaceFormat format = mainWindow->format(); format.setSamples(4); format.setSwapBehavior(QSurfaceFormat::TripleBuffer); mainWindow->setFormat(format); connect( qApp, SIGNAL( aboutToQuit() ), this, SLOT( slotAboutToQuit() ) ); //Initialize Time and Date if (startDateString.isEmpty() == false) { KStarsDateTime startDate = KStarsDateTime::fromString( startDateString ); if (startDate.isValid() ) data()->changeDateTime( data()->geo()->LTtoUT( startDate ) ); else data()->changeDateTime( KStarsDateTime::currentDateTimeUtc() ); } else data()->changeDateTime( KStarsDateTime::currentDateTimeUtc() ); // Initialize clock. If --paused is not in the comand line, look in options if ( startClock ) StartClockRunning = Options::runClock(); // Setup splash screen if ( doSplash ) { showSplash(); } else { connect( m_KStarsData, SIGNAL( progressText(QString) ), m_KStarsData, SLOT( slotConsoleMessage(QString) ) ); } //set up Dark color scheme for application windows DarkPalette = QPalette(QColor("darkred"), QColor("darkred")); DarkPalette.setColor( QPalette::Normal, QPalette::Base, QColor( "black" ) ); DarkPalette.setColor( QPalette::Normal, QPalette::Text, QColor( 238, 0, 0 ) ); DarkPalette.setColor( QPalette::Normal, QPalette::Highlight, QColor( 238, 0, 0 ) ); DarkPalette.setColor( QPalette::Normal, QPalette::HighlightedText, QColor( "black" ) ); DarkPalette.setColor( QPalette::Inactive, QPalette::Text, QColor( 238, 0, 0 ) ); DarkPalette.setColor( QPalette::Inactive, QPalette::Base, QColor( 30, 10, 10 ) ); //store original color scheme OriginalPalette = QGuiApplication::palette(); if( !m_KStarsData->initialize() ) return; datainitFinished(); #if ( __GLIBC__ >= 2 &&__GLIBC_MINOR__ >= 1 && !defined(__UCLIBC__) ) qDebug() << "glibc >= 2.1 detected. Using GNU extension sincos()"; #else qDebug() << "Did not find glibc >= 2.1. Will use ANSI-compliant sin()/cos() functions."; #endif } void KStarsLite::slotTrack() { if ( Options::isTracking() ) { Options::setIsTracking( false ); /*actionCollection()->action("track_object")->setText( i18n( "Engage &Tracking" ) ); actionCollection()->action("track_object")->setIcon( QIcon::fromTheme("document-decrypt") ); KSPlanetBase* planet = dynamic_cast( map()->focusObject() ); if( planet && data()->temporaryTrail ) { planet->clearTrail(); data()->temporaryTrail = false; }*/ // No trail support yet map()->setClickedObject( NULL ); map()->setFocusObject( NULL );//no longer tracking focusObject map()->setFocusPoint( NULL ); } else { map()->setClickedPoint( map()->focus() ); map()->setClickedObject( NULL ); map()->setFocusObject( NULL );//no longer tracking focusObject map()->setFocusPoint( map()->clickedPoint() ); Options::setIsTracking( true ); /*actionCollection()->action("track_object")->setText( i18n( "Stop &Tracking" ) ); actionCollection()->action("track_object")->setIcon( QIcon::fromTheme("document-encrypt") );*/ } map()->forceUpdate(); } KStarsLite *KStarsLite::createInstance( bool doSplash, bool clockrunning, const QString &startDateString) { delete pinstance; // pinstance is set directly in constructor. new KStarsLite( doSplash, clockrunning, startDateString ); Q_ASSERT( pinstance && "pinstance must be non NULL"); return nullptr; } KStarsLite::~KStarsLite() { delete m_imgProvider; } void KStarsLite::fullUpdate() { m_KStarsData->setFullTimeUpdate(); updateTime(); m_SkyMapLite->forceUpdate(); } void KStarsLite::updateTime( const bool automaticDSTchange ) { // Due to frequently use of this function save data and map pointers for speedup. // Save options and geo() to a pointer would not speedup because most of time options // and geo will accessed only one time. KStarsData *Data = data(); // dms oldLST( Data->lst()->Degrees() ); Data->updateTime( Data->geo(), automaticDSTchange ); //We do this outside of kstarsdata just to get the coordinates //displayed in the infobox to update every second. // if ( !Options::isTracking() && LST()->Degrees() > oldLST.Degrees() ) { // int nSec = int( 3600.*( LST()->Hours() - oldLST.Hours() ) ); // Map->focus()->setRA( Map->focus()->ra().Hours() + double( nSec )/3600. ); // if ( Options::useAltAz() ) Map->focus()->EquatorialToHorizontal( LST(), geo()->lat() ); // Map->showFocusCoords(); // } //If time is accelerated beyond slewTimescale, then the clock's timer is stopped, //so that it can be ticked manually after each update, in order to make each time //step exactly equal to the timeScale setting. //Wrap the call to manualTick() in a singleshot timer so that it doesn't get called until //the skymap has been completely updated. if ( Data->clock()->isManualMode() && Data->clock()->isActive() ) { QTimer::singleShot( 0, Data->clock(), SLOT( manualTick() ) ); } } void KStarsLite::writeConfig() { Options::self()->save(); //Store current simulation time //Refer to // FIXME: Used in kstarsdcop.cpp only in kstarsdata.cpp //data()->StoredDate = data()->lt(); } void KStarsLite::slotAboutToQuit() { // Delete skymaplite. This required to run destructors and save // current state in the option. delete m_SkyMapLite; //Store Window geometry in Options object //Options::setWindowWidth( m_RootObject->width() ); //Options::setWindowHeight( m_RootObject->height() ); //explicitly save the colorscheme data to the config file data()->colorScheme()->saveToConfig(); //synch the config file with the Config object writeConfig(); } void KStarsLite::loadColorScheme( const QString &name ) { bool ok = data()->colorScheme()->load( name ); QString filename = data()->colorScheme()->fileName(); if ( ok ) { //set the application colors for the Night Vision scheme if ( Options::darkAppColors() == false && filename == "night.colors" ) { Options::setDarkAppColors( true ); OriginalPalette = QGuiApplication::palette(); QGuiApplication::setPalette( DarkPalette ); } if ( Options::darkAppColors() && filename != "night.colors" ) { Options::setDarkAppColors( false ); QGuiApplication::setPalette( OriginalPalette ); } Options::setColorSchemeFile( name ); //Reinitialize stars textures map()->initStarImages(); map()->forceUpdate(); } } void KStarsLite::slotSetTime(QDateTime time) { KStarsDateTime selectedDateTime( time ); data()->changeDateTime( data()->geo()->LTtoUT( selectedDateTime ) ); if ( Options::useAltAz() ) { if ( map()->focusObject() ) { map()->focusObject()->EquatorialToHorizontal( data()->lst(), data()->geo()->lat() ); map()->setFocus( map()->focusObject() ); } else map()->focus()->HorizontalToEquatorial( data()->lst(), data()->geo()->lat() ); } map()->forceUpdateNow(); //If focusObject has a Planet Trail, clear it and start anew. /*KSPlanetBase* planet = dynamic_cast( map()->focusObject() ); if( planet && planet->hasTrail() ) { planet->clearTrail(); planet->addToTrail(); }*/ } void KStarsLite::slotToggleTimer() { if ( data()->clock()->isActive() ) { data()->clock()->stop(); updateTime(); } else { if ( fabs( data()->clock()->scale() ) > Options::slewTimeScale() ) data()->clock()->setManualMode( true ); data()->clock()->start(); if ( data()->clock()->isManualMode() ) map()->forceUpdate(); } // Update clock state in options Options::setRunClock( data()->clock()->isActive() ); } void KStarsLite::slotStepForward() { if ( data()->clock()->isActive() ) data()->clock()->stop(); data()->clock()->manualTick( true ); map()->forceUpdate(); } void KStarsLite::slotStepBackward() { if ( data()->clock()->isActive() ) data()->clock()->stop(); data()->clock()->setClockScale( -1.0 * data()->clock()->scale() ); //temporarily need negative time step data()->clock()->manualTick( true ); data()->clock()->setClockScale( -1.0 * data()->clock()->scale() ); //reset original sign of time step map()->forceUpdate(); } void KStarsLite::applyConfig(bool doApplyFocus) { Q_UNUSED(doApplyFocus); //color scheme m_KStarsData->colorScheme()->loadFromConfig(); QGuiApplication::setPalette( Options::darkAppColors() ? DarkPalette : OriginalPalette ); } void KStarsLite::setProjection(uint proj) { Options::setProjection(proj); //We update SkyMapLite 2 times because of the bug in Projector::updateClipPoly() SkyMapLite::Instance()->forceUpdate(); } QColor KStarsLite::getColor(QString schemeColor) { return KStarsData::Instance()->colorScheme()->colorNamed(schemeColor); } QString KStarsLite::getConfigCScheme() { return Options::colorSchemeFile(); } void KStarsLite::toggleObjects(ObjectsToToggle toToggle, bool toggle) { switch(toToggle) { case ObjectsToToggle::Stars: Options::setShowStars(toggle); break; case ObjectsToToggle::DeepSky: Options::setShowDeepSky(toggle); break; case ObjectsToToggle::Planets: Options::setShowSolarSystem(toggle); break; case ObjectsToToggle::CLines: Options::setShowCLines(toggle); break; case ObjectsToToggle::CBounds: Options::setShowCBounds(toggle); break; case ObjectsToToggle::ConstellationArt: Options::setShowConstellationArt(toggle); break; case ObjectsToToggle::MilkyWay: Options::setShowMilkyWay(toggle); break; case ObjectsToToggle::CNames: Options::setShowCNames(toggle); break; case ObjectsToToggle::EquatorialGrid: Options::setShowEquatorialGrid(toggle); break; case ObjectsToToggle::HorizontalGrid: Options::setShowHorizontalGrid(toggle); break; case ObjectsToToggle::Ground: Options::setShowGround(toggle); break; case ObjectsToToggle::Flags: Options::setShowFlags(toggle); break; case ObjectsToToggle::Satellites: Options::setShowSatellites(toggle); break; case ObjectsToToggle::Supernovae: Options::setShowSupernovae(toggle); break; }; // update time for all objects because they might be not initialized // it's needed when using horizontal coordinates data()->setFullTimeUpdate(); updateTime(); map()->forceUpdate(); } bool KStarsLite::isToggled(ObjectsToToggle toToggle) { switch(toToggle) { case ObjectsToToggle::Stars: return Options::showStars(); case ObjectsToToggle::DeepSky: return Options::showDeepSky(); case ObjectsToToggle::Planets: return Options::showSolarSystem(); case ObjectsToToggle::CLines: return Options::showCLines(); case ObjectsToToggle::CBounds: return Options::showCBounds(); case ObjectsToToggle::ConstellationArt: return Options::showConstellationArt(); case ObjectsToToggle::MilkyWay: return Options::showMilkyWay(); case ObjectsToToggle::CNames: return Options::showCNames(); case ObjectsToToggle::EquatorialGrid: return Options::showEquatorialGrid(); case ObjectsToToggle::HorizontalGrid: return Options::showHorizontalGrid(); case ObjectsToToggle::Ground: return Options::showGround(); case ObjectsToToggle::Flags: return Options::showFlags(); case ObjectsToToggle::Satellites: return Options::showSatellites(); case ObjectsToToggle::Supernovae: return Options::showSupernovae(); default: return false; }; } void KStarsLite::setRunTutorial(bool runTutorial) { if(Options::runStartupWizard() != runTutorial) { Options::setRunStartupWizard(runTutorial); emit runTutorialChanged(); } } bool KStarsLite::getRunTutorial() { return Options::runStartupWizard(); } diff --git a/kstars/kstarslite.h b/kstars/kstarslite.h index b1ffbf5d7..0424f3d7d 100644 --- a/kstars/kstarslite.h +++ b/kstars/kstarslite.h @@ -1,250 +1,244 @@ /** ************************************************************************* kstarslite.h - K Desktop Planetarium ------------------- begin : 30/04/2016 copyright : (C) 2016 by Artem Fedoskin email : afedoskin3@gmail.com ***************************************************************************/ /** ************************************************************************* * * * This program 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; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef KSTARSLITE_H_ #define KSTARSLITE_H_ #include #include #include #include //Needed for Projection enum #include "projections/projector.h" // forward declaration is enough. We only need pointers class KStarsData; class SkyMapLite; class SkyPoint; class GeoLocation; class ImageProvider; class FindDialogLite; class DetailDialogLite; class LocationDialogLite; -#ifdef HAVE_INDI class ClientManagerLite; -#endif class QQuickItem; /** *@class KStarsLite *@short This class loads QML files and connects SkyMapLite and KStarsData * Unlike KStars class it is not a main window (see KStarsLite::m_Engine) but a root object that contains the program clock and * holds pointers to SkyMapLite and KStarsData objects. * KStarsLite is a singleton, use KStarsLite::createInstance() to create an instance and KStarsLite::Instance() to get a pointer to the instance *@author Artem Fedoskin *@version 1.0 */ class KStarsLite : public QObject { Q_OBJECT //runTutorial is a wrapper for Options::RunStartupWizard() Q_PROPERTY(bool runTutorial WRITE setRunTutorial READ getRunTutorial NOTIFY runTutorialChanged) private: /** * @short Constructor. * @param doSplash should the splash panel be displayed during * initialization. * @param startClockRunning should the clock be running on startup? * @param startDateString date (in string representation) to start running from. */ explicit KStarsLite( bool doSplash, bool startClockRunning = true, const QString &startDateString = QString() ); static KStarsLite *pinstance; // Pointer to an instance of KStarsLite public: /** * @short Create an instance of this class. Destroy any previous instance * @param doSplash * @param clockrunning * @param startDateString * @note See KStarsLite::KStarsLite for details on parameters * @return a pointer to the instance */ static KStarsLite *createInstance( bool doSplash, bool clockrunning = true, const QString &startDateString = QString() ); /** @return a pointer to the instance of this class */ inline static KStarsLite *Instance() { return pinstance; } /** Destructor. Does nothing yet*/ virtual ~KStarsLite(); /** @return pointer to SkyMapLite object which draws SkyMap. */ inline SkyMapLite* map() const { return m_SkyMapLite; } /** @return pointer to KStarsData object which contains application data. */ inline KStarsData* data() const { return m_KStarsData; } /** @return pointer to ImageProvider that is used in QML to display image fetched from CCD **/ inline ImageProvider *imageProvider() const { return m_imgProvider; } /** @return pointer to QQmlApplicationEngine that runs QML **/ inline QQmlApplicationEngine *qmlEngine() { return &m_Engine; } /** @short used from QML to update positions of sky objects and update SkyMapLite */ Q_INVOKABLE void fullUpdate(); /** @short currently sets color scheme from config **/ void applyConfig( bool doApplyFocus = true ); /** @short set whether tutorial should be shown on next startup **/ void setRunTutorial(bool runTutorial); /** @return true if tutorial should be shown **/ bool getRunTutorial(); -#ifdef HAVE_INDI /** @return pointer to KStarsData object which handles connection to INDI server. */ inline ClientManagerLite *clientManagerLite() const { return m_clientManager; } -#endif /** @defgroup kconfigwrappers QML wrappers around KConfig * @{ */ enum ObjectsToToggle { Stars, DeepSky, Planets, CLines, CBounds, ConstellationArt, MilkyWay, CNames, EquatorialGrid, HorizontalGrid, Ground, Flags, Satellites, Supernovae }; Q_ENUMS(ObjectsToToggle) /** * @short setProjection calls Options::setProjection(proj) and updates SkyMapLite */ /*Having projection as uint is not good but it will go away once KConfig is fixed The reason for this is that you can't use Enums of another in class in Q_INVOKABLE function*/ Q_INVOKABLE void setProjection(uint proj); /** These functions are just convenient getters to access internals of KStars from QML **/ /** * @short returns color with key name from current color scheme * @param schemeColor name the key name of the color to be retrieved from current color scheme * @return color from name */ Q_INVOKABLE QColor getColor(QString name); Q_INVOKABLE QString getConfigCScheme(); /** * @short toggles on/off objects of group toToggle * @see ObjectsToToggle */ Q_INVOKABLE void toggleObjects(ObjectsToToggle toToggle, bool toggle); /** * @return true if objects from group toToggle are currently toggled on **/ Q_INVOKABLE bool isToggled(ObjectsToToggle toToggle); /** @} */ // end of kconfigwrappers group signals: /** Sent when KStarsData finishes loading data */ void dataLoadFinished(); /** Makes splash (Splash.qml) visible on startup */ void showSplash(); /** Emitted whenever TimeSpinBox in QML changes the scale **/ void scaleChanged(float); void runTutorialChanged(); /** Once this signal is emitted, notification with text msg will appear on the screen. Use this signal to output messages to user (warnings, info etc.) **/ void notificationMessage(QString msg); public Q_SLOTS: /** * Update time-dependent data and (possibly) repaint the sky map. * @param automaticDSTchange change DST status automatically? */ void updateTime( const bool automaticDSTchange = true ); /** Write current settings to config file. Used to save config file upon exit */ void writeConfig(); /** Load a color scheme. * @param name the name of the color scheme to load (e.g., "Moonless Night") */ void loadColorScheme( const QString &name ); /** sets time and date according to parameter time*/ void slotSetTime(QDateTime time); /** action slot: toggle whether kstars clock is running or not */ void slotToggleTimer(); /** action slot: advance one step forward in time */ void slotStepForward(); /** action slot: advance one step backward in time */ void slotStepBackward(); /** @short start tracking clickedPoint or stop tracking if we are already tracking some object **/ void slotTrack(); private slots: /** finish setting up after the KStarsData has finished */ void datainitFinished(); /** Save data to config file before exiting.*/ void slotAboutToQuit(); private: /** Initialize focus position */ void initFocus(); QQmlApplicationEngine m_Engine; SkyMapLite *m_SkyMapLite; QPalette OriginalPalette, DarkPalette; QObject *m_RootObject; bool StartClockRunning; KStarsData *m_KStarsData; ImageProvider *m_imgProvider; //Dialogs FindDialogLite *m_findDialogLite; DetailDialogLite *m_detailDialogLite; LocationDialogLite *m_locationDialogLite; -#ifdef HAVE_INDI ClientManagerLite *m_clientManager; -#endif }; #endif diff --git a/kstars/kstarslite/qml/indi/INDIControlPanel.qml b/kstars/kstarslite/qml/indi/INDIControlPanel.qml index e092050a7..045a1a644 100644 --- a/kstars/kstarslite/qml/indi/INDIControlPanel.qml +++ b/kstars/kstarslite/qml/indi/INDIControlPanel.qml @@ -1,162 +1,163 @@ // Copyright (C) 2016 Artem Fedoskin /*************************************************************************** * * * This program 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; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ import QtQuick 2.6 import QtQuick.Window 2.2 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.2 import "../modules" import "../constants" 1.0 KSPage { id: indiPage objectName: "indiControlPanel" title: "INDI Control Panel" property bool connected: ClientManagerLite.connected // Component.onCompleted: { // if(Qt.platform.os != "android") { // ClientManagerLite.setHost("localhost", parseInt(7624)) // } // } onConnectedChanged: { if(!indiPage.connected) { for(var i = 0; i < devicesModel.count; ++i) { devicesModel.get(i).panel.destroy() stackView.pop(indiPage) } devicesModel.clear() notification.showNotification("Disconnected from the server") } } contentItem: cPanelColumn ColumnLayout { id: cPanelColumn spacing: 5 * num.dp ColumnLayout { visible: !indiPage.connected anchors { left: parent.left right: parent.right } KSLabel { text: xi18n("INDI Host") } RowLayout { anchors { left: parent.left right: parent.right } KSTextField { id:ipHost placeholderText: xi18n("IP") Layout.alignment: Qt.AlignHCenter Layout.maximumWidth: parent.width*0.8 Layout.fillWidth: true text: ClientManagerLite.lastUsedServer } KSTextField { id:portHost placeholderText: xi18n("Port") Layout.alignment: Qt.AlignHCenter Layout.maximumWidth: parent.width*0.2 Layout.fillWidth: true text: ClientManagerLite.lastUsedPort } } } KSLabel { id: connectedTo visible: indiPage.connected text: xi18n("Connected to ") + ClientManagerLite.connectedHost } Button { text: indiPage.connected ? xi18n("Disconnect") : xi18n("Connect ") onClicked: { if(!indiPage.connected) { if(ClientManagerLite.setHost(ipHost.text, parseInt(portHost.text))) { notification.showNotification(xi18n("Successfully connected to the server")) } else { notification.showNotification(xi18n("Couldn't connect to the server")) } } else { + ClientManagerLite.disconnectHost() } Qt.inputMethod.hide() } } ColumnLayout { Layout.fillHeight: true Layout.fillWidth: true visible : indiPage.connected Rectangle { Layout.fillWidth: true height: 1 * num.dp color: "gray" } KSLabel { id: devicesLabel text: xi18n("Available Devices") } ListModel { id: devicesModel } Connections { target: ClientManagerLite onNewINDIDevice: { var component = Qt.createComponent(Qt.resolvedUrl("./DevicePanel.qml")); var devicePanel = component.createObject(window); devicePanel.deviceName = deviceName devicesModel.append({ name: deviceName, panel: devicePanel }) } onRemoveINDIDevice: { for(i = 0; i < devicesModel.count; ++i) { if(devicesModel.get(i).name == deviceName) { devicesModel.panel.destroy() devicesModel.remove(i) } } } onNewINDIMessage: { notification.showNotification(message) } } } KSListView { id: devicesPage Layout.fillHeight: true Layout.fillWidth: true model: devicesModel textRole: "name" onClicked: { stackView.push(devicesModel.get(currentIndex).panel) } } } } diff --git a/kstars/kstarslite/skyitems/rootnode.cpp b/kstars/kstarslite/skyitems/rootnode.cpp index b3e1ab1d5..9e7f8d09a 100644 --- a/kstars/kstarslite/skyitems/rootnode.cpp +++ b/kstars/kstarslite/skyitems/rootnode.cpp @@ -1,287 +1,281 @@ #include #include #include "rootnode.h" #include "skymaplite.h" #include "projections/projector.h" #include "skymapcomposite.h" #include "solarsystemcomposite.h" #include "Options.h" #include "constellationboundarylines.h" #include "constellationlines.h" #include "starcomponent.h" #include "horizontalcoordinategrid.h" #include "equatorialcoordinategrid.h" #include "ecliptic.h" #include "equator.h" //SkyItems #include "kstarslite/skyitems/staritem.h" #include "kstarslite/skyitems/deepskyitem.h" #include "kstarslite/skyitems/planetsitem.h" #include "kstarslite/skyitems/asteroidsitem.h" #include "kstarslite/skyitems/cometsitem.h" #include "kstarslite/skyitems/horizonitem.h" #include "kstarslite/skyitems/lines/linesitem.h" #include "kstarslite/skyitems/labelsitem.h" #include "kstarslite/skyitems/constellationnamesitem.h" #include "kstarslite/skyitems/constellationartitem.h" #include "kstarslite/skyitems/satellitesitem.h" #include "kstarslite/skyitems/supernovaeitem.h" #include "kstarslite/skyitems/syncedcatalogitem.h" //Lines #include "kstarslite/skyitems/lines/equatoritem.h" #include "kstarslite/skyitems/lines/eclipticitem.h" #include "kstarslite/skyitems/lines/milkywayitem.h" -#ifdef HAVE_INDI //Symbols #include "kstarslite/skyitems/telescopesymbolsitem.h" -#endif #include "kstarslite/skyitems/fovitem.h" #include RootNode::RootNode() :m_skyMapLite(SkyMapLite::Instance()), m_clipGeometry(0) { SkyMapLite::setRootNode(this); genCachedTextures(); m_skyComposite = KStarsData::Instance()->skyComposite(); // LabelsItem needs to be created first so that other items could insert their labels in labelsList m_labelsItem = new LabelsItem(); m_MWItem = new MilkyWayItem(m_skyComposite->milkyWay(), this); m_linesItem = new LinesItem(this); m_linesItem->addLinesComponent( m_skyComposite->equatorialCoordGrid(), "EquatorialGridColor", 1, Qt::DotLine ); m_linesItem->addLinesComponent( m_skyComposite->horizontalCoordGrid(), "HorizontalGridColor", 2, Qt::DotLine ); if ( m_skyComposite->currentCulture() == "Western" ) { m_linesItem->addLinesComponent( m_skyComposite->constellationBoundary(), "CBoundColor", 1, Qt::SolidLine ); } m_artItem = new ConstellationArtItem(m_skyComposite->constellationArt(), this); m_linesItem->addLinesComponent( m_skyComposite->constellationLines(), "CLineColor", 1, Qt::SolidLine ); m_equator = new EquatorItem(m_skyComposite->equator(),this); m_ecliptic = new EclipticItem(m_skyComposite->ecliptic(),this); m_dsoItem = new DeepSkyItem( m_skyComposite->deepSkyComponent(), this ); m_starItem = new StarItem(StarComponent::Instance(), this); m_solarSystem = m_skyComposite->solarSystemComposite(); m_planetsItem = new PlanetsItem(m_solarSystem->planets(), m_solarSystem->planetMoonsComponent(), this); m_asteroidsItem = new AsteroidsItem(m_solarSystem->asteroids(), this); m_cometsItem = new CometsItem(m_solarSystem->comets(), this); m_constelNamesItem = new ConstellationNamesItem(m_skyComposite->constellationNamesComponent(), this); m_satItem = new SatellitesItem( m_skyComposite->satellites(), this); m_snovaItem = new SupernovaeItem(m_skyComposite->supernovaeComponent(), this); m_horizonItem = new HorizonItem(m_skyComposite->horizon(), this); m_FOVItem = new FOVItem(this); m_internedResolvedCatalogItem = new SyncedCatalogItem(m_skyComposite->internetResolvedComponent(), this); m_manualAdditionsCatalogItem = new SyncedCatalogItem(m_skyComposite->manualAdditionsComponent(), this); -#ifdef HAVE_INDI m_telescopeSymbols = new TelescopeSymbolsItem(this); -#endif setIsRectangular(false); updateClipPoly(); m_labelsItem->setRootNode(this); } void RootNode::testLeakAdd() { /* m_linesItem = new LinesItem(this); m_linesItem->addLinesComponent( m_skyComposite->equatorialCoordGrid(), "EquatorialGridColor", 1, Qt::DotLine ); m_linesItem->addLinesComponent( m_skyComposite->horizontalCoordGrid(), "HorizontalGridColor", 2, Qt::DotLine ); m_linesItem->addLinesComponent( m_skyComposite->constellationBoundary(), "CBoundColor", 1, Qt::SolidLine ); m_linesItem->addLinesComponent( m_skyComposite->constellationLines(), "CLineColor", 1, Qt::SolidLine ); m_starItem = new StarItem(m_skyComposite->starComponent(), this); m_solarSystem = m_skyComposite->solarSystemComposite(); m_equator = new EquatorItem(m_skyComposite->equator(),this); m_ecliptic = new EclipticItem(m_skyComposite->ecliptic(),this); m_planetsItem = new PlanetsItem(m_solarSystem->planets(), m_solarSystem->planetMoonsComponent(), this); m_asteroidsItem = new AsteroidsItem(m_solarSystem->asteroids(), this); m_cometsItem = new CometsItem(m_solarSystem->comets(), this); m_constelNamesItem = new ConstellationNamesItem(m_skyComposite->constellationNamesComponent(), this); m_horizonItem = new HorizonItem(m_skyComposite->horizon(), this);*/ } void RootNode::testLeakDelete() { /*removeChildNode(m_linesItem); delete m_linesItem; removeChildNode(m_starItem); delete m_starItem; removeChildNode(m_equator); delete m_equator; removeChildNode(m_ecliptic); delete m_ecliptic; removeChildNode(m_planetsItem); delete m_planetsItem; removeChildNode(m_asteroidsItem); delete m_asteroidsItem; removeChildNode(m_cometsItem); delete m_cometsItem; removeChildNode(m_constelNamesItem); delete m_constelNamesItem; removeChildNode(m_horizonItem); delete m_horizonItem;*/ } RootNode::~RootNode() { for(int i = 0; i < m_textureCache.length(); ++i) { for(int c = 0; c < m_textureCache[i].size(); ++c) { delete m_textureCache[i][c]; } } } void RootNode::genCachedTextures() { QVector> images = m_skyMapLite->getImageCache(); QQuickWindow *win = m_skyMapLite->window(); m_textureCache = QVector> (images.length()); for(int i = 0; i < m_textureCache.length(); ++i) { int length = images[i].length(); m_textureCache[i] = QVector(length); for(int c = 1; c < length; ++c) { m_textureCache[i][c] = win->createTextureFromImage(images[i][c]->toImage(), QQuickWindow::TextureCanUseAtlas); } } } QSGTexture* RootNode::getCachedTexture(int size, char spType) { return m_textureCache[SkyMapLite::Instance()->harvardToIndex(spType)][size]; } void RootNode::updateClipPoly() { QPolygonF newClip = m_skyMapLite->projector()->clipPoly(); m_clipPoly = newClip; const int size = m_clipPoly.size(); if(!m_clipGeometry) { m_clipGeometry = new QSGGeometry (QSGGeometry::defaultAttributes_Point2D (), size); m_clipGeometry->setDrawingMode(GL_TRIANGLE_FAN); setGeometry(m_clipGeometry); setFlag(QSGNode::OwnsGeometry); } m_clipGeometry->allocate(size); QSGGeometry::Point2D * vertex = m_clipGeometry->vertexDataAsPoint2D (); for (int i = 0; i < size; i++) { vertex[i].x = m_clipPoly[i].x(); vertex[i].y = m_clipPoly[i].y(); } m_clipGeometry->markIndexDataDirty(); m_clipGeometry->markVertexDataDirty(); markDirty(QSGNode::DirtyGeometry); } void RootNode::update(bool clearTextures) { updateClipPoly(); if(clearTextures) { //First we need to create new textures and only after all PointNodes changed their textures we //can delete old textures genCachedTextures(); } m_MWItem->update(); m_artItem->update(); m_linesItem->update(); m_equator->update(); m_ecliptic->update(); m_dsoItem->update(); m_starItem->update(); //TODO: Move this check somewhere else (create a separate function) if(Options::showSolarSystem()) { m_planetsItem->update(); if (!Options::showAsteroids() ) { if (m_asteroidsItem) delete m_asteroidsItem; } else { if(!m_asteroidsItem) m_asteroidsItem = new AsteroidsItem(m_solarSystem->asteroids(), this); m_asteroidsItem->update(); } if (!Options::showComets() ) { if (m_cometsItem) delete m_cometsItem; } else { if(!m_cometsItem) m_cometsItem = new CometsItem(m_solarSystem->comets(), this); m_cometsItem->update(); } } else { m_planetsItem->hide(); if(m_asteroidsItem) { delete m_asteroidsItem; m_asteroidsItem = 0; } if(m_cometsItem) { delete m_cometsItem; m_cometsItem = 0; } } m_constelNamesItem->update(); m_satItem->update(); m_snovaItem->update(); m_horizonItem->update(); m_internedResolvedCatalogItem->update(); m_manualAdditionsCatalogItem->update(); -#ifdef HAVE_INDI m_telescopeSymbols->update(); -#endif m_labelsItem->update(); m_FOVItem->update(); if(clearTextures) { //Delete old textures if(m_oldTextureCache.length()) { foreach(QVector textures, m_oldTextureCache) { qDeleteAll(textures.begin(), textures.end()); } } } } diff --git a/kstars/kstarslite/skyitems/rootnode.h b/kstars/kstarslite/skyitems/rootnode.h index 93be1f95d..2deb588dd 100644 --- a/kstars/kstarslite/skyitems/rootnode.h +++ b/kstars/kstarslite/skyitems/rootnode.h @@ -1,152 +1,146 @@ /** ************************************************************************* rootnode.h - K Desktop Planetarium ------------------- begin : 14/05/2016 copyright : (C) 2016 by Artem Fedoskin email : afedoskin3@gmail.com ***************************************************************************/ /** ************************************************************************* * * * This program 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; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef ROOTNODE_H_ #define ROOTNODE_H_ #include #include #include "kstarslite.h" class QSGTexture; class SkyMapLite; class StarItem; class DeepSkyItem; class PlanetsItem; class AsteroidsItem; class CometsItem; class ConstellationNamesItem; class LabelsItem; class ConstellationArtItem; class SatellitesItem; class SupernovaeItem; class LinesItem; class HorizonItem; class EquatorItem; class EclipticItem; class MilkyWayItem; class SkyMapComposite; class SolarSystemComposite; class SyncedCatalogItem; class FOVItem; -#ifdef HAVE_INDI class TelescopeSymbolsItem; -#endif /** @class RootNode * * A QSGClipNode derived class used as a container for holding pointers to nodes and for clipping. * Upon construction RootNode generates all textures that are used by PointNode. * * KStars Lite has the following hierarchy: * 1. RootNode - the parent of all nodes that also acts as a clipping node * 2. SkyItem derived nodes that acts like SkyComponent in regular KStars * 3. SkyNode derived nodes that represent SkyObjects (similar to SkyComponent::draw()) * 4. Simple nodes like EllipseNode or PointNode that draw basic geometry and stars * * @short A container for nodes that holds collection of textures for stars and provides clipping * @author Artem Fedoskin * @version 1.0 */ class RootNode : public QSGClipNode { public: RootNode(); virtual ~RootNode(); /** * @short returns cached texture from textureCache * @param size size of the star * @param spType spectral class * @return cached QSGTexture from textureCache */ QSGTexture* getCachedTexture(int size, char spType); /** * @short triangulates and sets new clipping polygon provided by Projection system */ void updateClipPoly(); /** * @short update positions of all child SkyItems * @param clearTextures true if textures for PointNodes should recreated (required when color scheme * is changed) */ void update(bool clearTextures = false); /** Debug functions **/ void testLeakDelete(); void testLeakAdd(); inline CometsItem *cometsItem() { return m_cometsItem; } inline LabelsItem *labelsItem() { return m_labelsItem; } inline StarItem *starItem() { return m_starItem; } /** * @short initializes textureCache with cached images of stars from SkyMapLite */ void genCachedTextures(); -#ifdef HAVE_INDI inline TelescopeSymbolsItem *telescopeSymbolsItem() { return m_telescopeSymbols; } -#endif private: QVector> m_textureCache; QVector> m_oldTextureCache; SkyMapLite *m_skyMapLite; QPolygonF m_clipPoly; QSGGeometry *m_clipGeometry; StarItem *m_starItem; DeepSkyItem *m_dsoItem; PlanetsItem *m_planetsItem; AsteroidsItem *m_asteroidsItem; CometsItem *m_cometsItem; ConstellationNamesItem *m_constelNamesItem; LabelsItem *m_labelsItem; ConstellationArtItem *m_artItem; SatellitesItem *m_satItem; SupernovaeItem *m_snovaItem; SyncedCatalogItem *m_internedResolvedCatalogItem; SyncedCatalogItem *m_manualAdditionsCatalogItem; HorizonItem *m_horizonItem; LinesItem *m_linesItem; EquatorItem *m_equator; EclipticItem *m_ecliptic; MilkyWayItem *m_MWItem; SkyMapComposite *m_skyComposite; SolarSystemComposite *m_solarSystem; QSGGeometryNode *m_visualizeClipping; FOVItem *m_FOVItem; -#ifdef HAVE_INDI TelescopeSymbolsItem *m_telescopeSymbols; -#endif }; #endif diff --git a/kstars/skymaplite.cpp b/kstars/skymaplite.cpp index 7a65dc20f..405c5d9c0 100644 --- a/kstars/skymaplite.cpp +++ b/kstars/skymaplite.cpp @@ -1,902 +1,896 @@ /** ************************************************************************* skymaplite.cpp - K Desktop Planetarium ------------------- begin : 30/04/2016 copyright : (C) 2016 by Artem Fedoskin email : afedoskin3@gmail.com ***************************************************************************/ /** ************************************************************************* * * * This program 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; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "skymaplite.h" #include "kstarsdata.h" #include "kstarslite.h" -#ifdef HAVE_INDI #include "indi/inditelescopelite.h" #include "indi/clientmanagerlite.h" #include "kstarslite/skyitems/telescopesymbolsitem.h" -#endif #include "projections/projector.h" #include "projections/lambertprojector.h" #include "projections/gnomonicprojector.h" #include "projections/stereographicprojector.h" #include "projections/orthographicprojector.h" #include "projections/azimuthalequidistantprojector.h" #include "projections/equirectangularprojector.h" #include "kstarslite/skypointlite.h" #include "kstarslite/skyobjectlite.h" #include "skylabeler.h" #include "Options.h" #include "skymesh.h" #include "kstarslite/skyitems/rootnode.h" #include "kstarslite/skyitems/skynodes/skynode.h" #include "ksplanetbase.h" #include "ksutils.h" #include //#include #include #include #include #include #include #include namespace { // Draw bitmap for zoom cursor. Width is size of pen to draw with. QBitmap zoomCursorBitmap(int width) { QBitmap b(32, 32); b.fill(Qt::color0); int mx = 16, my = 16; // Begin drawing QPainter p; p.begin( &b ); p.setPen( QPen( Qt::color1, width ) ); p.drawEllipse( mx - 7, my - 7, 14, 14 ); p.drawLine( mx + 5, my + 5, mx + 11, my + 11 ); p.end(); return b; } // Draw bitmap for default cursor. Width is size of pen to draw with. QBitmap defaultCursorBitmap(int width) { QBitmap b(32, 32); b.fill(Qt::color0); int mx = 16, my = 16; // Begin drawing QPainter p; p.begin( &b ); p.setPen( QPen( Qt::color1, width ) ); // 1. diagonal p.drawLine (mx - 2, my - 2, mx - 8, mx - 8); p.drawLine (mx + 2, my + 2, mx + 8, mx + 8); // 2. diagonal p.drawLine (mx - 2, my + 2, mx - 8, mx + 8); p.drawLine (mx + 2, my - 2, mx + 8, mx - 8); p.end(); return b; } } SkyMapLite *SkyMapLite::pinstance = 0; RootNode *SkyMapLite::m_rootNode = nullptr; int SkyMapLite::starColorMode = 0; SkyMapLite::SkyMapLite() :m_proj(0), count(0), data(KStarsData::Instance()), nStarSizes(15), nSPclasses(7), pinch(false), m_loadingFinished(false), m_sizeMagLim(10.0), isInitialized(false), clearTextures(false), m_centerLocked(false) { setAcceptHoverEvents(true); setAcceptedMouseButtons(Qt::AllButtons); setFlag(ItemHasContents, true); m_rootNode = 0; m_magLim = 2.222 * log10(static_cast( Options::starDensity() )) + 0.35; midMouseButtonDown = false; mouseButtonDown = false; setSlewing(false); clockSlewing = false; ClickedObject = NULL; FocusObject = NULL; m_ClickedObjectLite = new SkyObjectLite; m_ClickedPointLite = new SkyPointLite; qmlRegisterType("KStarsLite",1,0,"SkyObjectLite"); qmlRegisterType("KStarsLite",1,0,"SkyPointLite"); m_tapBeganTimer.setSingleShot(true); setupProjector(); // Set pinstance to yourself pinstance = this; connect( this, SIGNAL( destinationChanged() ), this, SLOT( slewFocus() ) ); connect( KStarsData::Instance(), SIGNAL( skyUpdate( bool ) ), this, SLOT( slotUpdateSky( bool ) ) ); -#ifdef HAVE_INDI ClientManagerLite *clientMng = KStarsLite::Instance()->clientManagerLite(); connect(clientMng, &ClientManagerLite::telescopeAdded, [this](TelescopeLite *newTelescope){ this->m_newTelescopes.append(newTelescope->getDevice()); }); connect(clientMng, &ClientManagerLite::telescopeRemoved, [this](TelescopeLite *newTelescope){ this->m_delTelescopes.append(newTelescope->getDevice()); }); -#endif } QSGNode* SkyMapLite::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) { Q_UNUSED(updatePaintNodeData); RootNode *n = static_cast(oldNode); /* This code deletes all nodes that are representing dynamic stars and not needed anymore (under construction) */ //qDeleteAll(m_deleteNodes); //m_deleteNodes.clear(); if(m_loadingFinished && isInitialized) { if(!n) { n = new RootNode(); m_rootNode = n; } /** Add or delete telescope crosshairs **/ -#ifdef HAVE_INDI if(m_newTelescopes.count() > 0) { foreach(INDI::BaseDevice *telescope, m_newTelescopes) { n->telescopeSymbolsItem()->addTelescope(telescope); } m_newTelescopes.clear(); } if(m_delTelescopes.count() > 0) { foreach(INDI::BaseDevice *telescope, m_delTelescopes) { n->telescopeSymbolsItem()->removeTelescope(telescope); } m_delTelescopes.clear(); } -#endif //Notify RootNode that textures for point node should be recreated n->update(clearTextures); clearTextures = false; } //Memory Leaks test /*if(m_loadingFinished) { if(!n) { n = new RootNode(); } n->testLeakAdd(); n->update(); m_loadingFinished = false; } else { if (n) { n->testLeakDelete(); } m_loadingFinished = true; }*/ return n; } double SkyMapLite::deleteLimit() { double lim = (MAXZOOM/MINZOOM)/sqrt(Options::zoomFactor())/3;//(MAXZOOM/MINZOOM - Options::zoomFactor())/130; return lim; } void SkyMapLite::deleteSkyNode(SkyNode *skyNode) { m_deleteNodes.append(skyNode); } QSGTexture* SkyMapLite::getCachedTexture(int size, char spType) { return textureCache[harvardToIndex(spType)][size]; } SkyMapLite* SkyMapLite::createInstance() { delete pinstance; pinstance = new SkyMapLite(); return pinstance; } void SkyMapLite::initialize(QQuickItem *parent) { if(parent) { setParentItem(parent); // Whenever the wrapper's(parent) dimensions changed, change SkyMapLite too connect(parent, &QQuickItem::widthChanged, this, &SkyMapLite::resizeItem); connect(parent, &QQuickItem::heightChanged, this, &SkyMapLite::resizeItem); isInitialized = true; } resizeItem(); /* Set initial size pf SkyMapLite. Without it on Android SkyMapLite is not displayed until screen orientation is not changed*/ //Initialize images for stars initStarImages(); } SkyMapLite::~SkyMapLite() { // Delete image cache foreach(QVector imgCache, imageCache) { foreach(QPixmap* img, imgCache) delete img; } // Delete textures generated from image cache foreach(QVector tCache, textureCache) { foreach(QSGTexture* t, tCache) delete t; } } void SkyMapLite::setFocus( SkyPoint *p ) { setFocus( p->ra(), p->dec() ); } void SkyMapLite::setFocus( const dms &ra, const dms &dec ) { Options::setFocusRA( ra.Hours() ); Options::setFocusDec( dec.Degrees() ); focus()->set( ra, dec ); focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); } void SkyMapLite::setFocusAltAz( const dms &alt, const dms &az) { Options::setFocusRA( focus()->ra().Hours() ); Options::setFocusDec( focus()->dec().Degrees() ); focus()->setAlt(alt); focus()->setAz(az); focus()->HorizontalToEquatorial( data->lst(), data->geo()->lat() ); setSlewing(false); forceUpdate(); //need a total update, or slewing with the arrow keys doesn't work. } void SkyMapLite::setDestination( const SkyPoint& p ) { setDestination( p.ra(), p.dec() ); } void SkyMapLite::setDestination( const dms &ra, const dms &dec ) { destination()->set( ra, dec ); destination()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); emit destinationChanged(); } void SkyMapLite::setDestinationAltAz( const dms &alt, const dms &az) { destination()->setAlt(alt); destination()->setAz(az); destination()->HorizontalToEquatorial( data->lst(), data->geo()->lat() ); emit destinationChanged(); } void SkyMapLite::setClickedPoint( SkyPoint *f ) { ClickedPoint = *f; m_ClickedPointLite->setPoint(f); } void SkyMapLite::setClickedObject( SkyObject *o ) { ClickedObject = o; m_ClickedObjectLite->setObject(o); } void SkyMapLite::setFocusObject( SkyObject *o ) { FocusObject = o; if ( FocusObject ) Options::setFocusObject( FocusObject->name() ); else Options::setFocusObject( i18n( "nothing" ) ); } void SkyMapLite::slotCenter() { /*KStars* kstars = KStars::Instance(); TrailObject* trailObj = dynamic_cast( focusObject() );*/ setFocusPoint( clickedPoint() ); if ( Options::useAltAz() ) { focusPoint()->updateCoords( data->updateNum(), true, data->geo()->lat(), data->lst(), false ); focusPoint()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); } else { focusPoint()->updateCoords( data->updateNum(), true, data->geo()->lat(), data->lst(), false ); } qDebug() << "Centering on " << focusPoint()->ra().toHMSString() << " " << focusPoint()->dec().toDMSString(); //clear the planet trail of old focusObject, if it was temporary /*if( trailObj && data->temporaryTrail ) { trailObj->clearTrail(); data->temporaryTrail = false; }*/ //If the requested object is below the opaque horizon, issue a warning message //(unless user is already pointed below the horizon) if ( Options::useAltAz() && Options::showGround() && focus()->alt().Degrees() > -1.0 && focusPoint()->alt().Degrees() < -1.0 ) { QString caption = i18n( "Requested Position Below Horizon" ); QString message = i18n( "The requested position is below the horizon.\nWould you like to go there anyway?" ); /*if ( KMessageBox::warningYesNo( this, message, caption, KGuiItem(i18n("Go Anyway")), KGuiItem(i18n("Keep Position")), "dag_focus_below_horiz" )==KMessageBox::No ) { setClickedObject( NULL ); setFocusObject( NULL ); Options::setIsTracking( false ); return; }*/ } //set FocusObject before slewing. Otherwise, KStarsData::updateTime() can reset //destination to previous object... setFocusObject( ClickedObject ); Options::setIsTracking( true ); /*if ( kstars ) { kstars->actionCollection()->action("track_object")->setIcon( QIcon::fromTheme("document-encrypt") ); kstars->actionCollection()->action("track_object")->setText( i18n( "Stop &Tracking" ) ); }*/ //If focusObject is a SS body and doesn't already have a trail, set the temporaryTrail /*if( Options::useAutoTrail() && trailObj && trailObj->hasTrail() ) { trailObj->addToTrail(); data->temporaryTrail = true; }*/ //update the destination to the selected coordinates if ( Options::useAltAz() ) { setDestinationAltAz( focusPoint()->altRefracted(), focusPoint()->az() ); } else { setDestination( *focusPoint() ); } focusPoint()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); //display coordinates in statusBar emit mousePointChanged( focusPoint() ); //showFocusCoords(); //update FocusBox //Lock center so that user could only zoom on touch-enabled devices } void SkyMapLite::slewFocus() { //Don't slew if the mouse button is pressed //Also, no animated slews if the Manual Clock is active //08/2002: added possibility for one-time skipping of slew with snapNextFocus if ( !mouseButtonDown ) { bool goSlew = ( Options::useAnimatedSlewing() && ! data->snapNextFocus() ) && !( data->clock()->isManualMode() && data->clock()->isActive() ); if ( goSlew ) { double dX, dY; double maxstep = 10.0; if ( Options::useAltAz() ) { dX = destination()->az().Degrees() - focus()->az().Degrees(); dY = destination()->alt().Degrees() - focus()->alt().Degrees(); } else { dX = destination()->ra().Degrees() - focus()->ra().Degrees(); dY = destination()->dec().Degrees() - focus()->dec().Degrees(); } //switch directions to go the short way around the celestial sphere, if necessary. dX = KSUtils::reduceAngle(dX, -180.0, 180.0); double r0 = sqrt( dX*dX + dY*dY ); if ( r0 < 20.0 ) { //smaller slews have smaller maxstep maxstep *= (10.0 + 0.5*r0)/20.0; } double step = 0.1; double r = r0; while ( r > step ) { //DEBUG //qDebug() << step << ": " << r << ": " << r0 << endl; double fX = dX / r; double fY = dY / r; if ( Options::useAltAz() ) { focus()->setAlt( focus()->alt().Degrees() + fY*step ); focus()->setAz( dms( focus()->az().Degrees() + fX*step ).reduce() ); focus()->HorizontalToEquatorial( data->lst(), data->geo()->lat() ); } else { fX = fX/15.; //convert RA degrees to hours SkyPoint newFocus( focus()->ra().Hours() + fX*step, focus()->dec().Degrees() + fY*step ); setFocus( &newFocus ); focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); } setSlewing(true); forceUpdate(); qApp->processEvents(); //keep up with other stuff if ( Options::useAltAz() ) { dX = destination()->az().Degrees() - focus()->az().Degrees(); dY = destination()->alt().Degrees() - focus()->alt().Degrees(); } else { dX = destination()->ra().Degrees() - focus()->ra().Degrees(); dY = destination()->dec().Degrees() - focus()->dec().Degrees(); } //switch directions to go the short way around the celestial sphere, if necessary. dX = KSUtils::reduceAngle(dX, -180.0, 180.0); r = sqrt( dX*dX + dY*dY ); //Modify step according to a cosine-shaped profile //centered on the midpoint of the slew //NOTE: don't allow the full range from -PI/2 to PI/2 //because the slew will never reach the destination as //the speed approaches zero at the end! double t = dms::PI*(r - 0.5*r0)/(1.05*r0); step = cos(t)*maxstep; } } //Either useAnimatedSlewing==false, or we have slewed, and are within one step of destination //set focus=destination. if ( Options::useAltAz() ) { setFocusAltAz( destination()->alt(), destination()->az() ); focus()->HorizontalToEquatorial( data->lst(), data->geo()->lat() ); } else { setFocus( destination() ); focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); } setSlewing(false); //Turn off snapNextFocus, we only want it to happen once if ( data->snapNextFocus() ) { data->setSnapNextFocus(false); } //Start the HoverTimer. if the user leaves the mouse in place after a slew, //we want to attach a label to the nearest object. if ( Options::useHoverLabel() ) m_HoverTimer.start( HOVER_INTERVAL ); forceUpdate(); } } void SkyMapLite::slotClockSlewing() { //If the current timescale exceeds slewTimeScale, set clockSlewing=true, and stop the clock. if( (fabs( data->clock()->scale() ) > Options::slewTimeScale()) ^ clockSlewing ) { data->clock()->setManualMode( !clockSlewing ); clockSlewing = !clockSlewing; // don't change automatically the DST status KStarsLite* kstars = KStarsLite::Instance(); if( kstars ) kstars->updateTime( false ); } } /*void SkyMapLite::updateFocus() { if( slewing ) return; //Tracking on an object if ( Options::isTracking() && focusObject() != NULL ) { if ( Options::useAltAz() ) { //Tracking any object in Alt/Az mode requires focus updates focusObject()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); setFocusAltAz( focusObject()->altRefracted(), focusObject()->az() ); focus()->HorizontalToEquatorial( data->lst(), data->geo()->lat() ); setDestination( *focus() ); } else { //Tracking in equatorial coords setFocus( focusObject() ); focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); setDestination( *focus() ); } //Tracking on empty sky } else if ( Options::isTracking() && focusPoint() != NULL ) { if ( Options::useAltAz() ) { //Tracking on empty sky in Alt/Az mode setFocus( focusPoint() ); focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); setDestination( *focus() ); } // Not tracking and not slewing, let sky drift by // This means that horizontal coordinates are constant. } else { focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat() ); } }*/ void SkyMapLite::resizeItem() { if(parentItem()) { setWidth(parentItem()->width()); setHeight(parentItem()->height()); } forceUpdate(); } void SkyMapLite::slotZoomIn() { setZoomFactor( Options::zoomFactor() * DZOOM ); } void SkyMapLite::slotZoomOut() { setZoomFactor( Options::zoomFactor() / DZOOM ); } void SkyMapLite::slotZoomDefault() { setZoomFactor( DEFAULTZOOM ); } void SkyMapLite::slotSelectObject(SkyObject *skyObj) { ClickedPoint = *skyObj; ClickedObject = skyObj; /*if ( Options::useAltAz() ) { setDestinationAltAz( skyObj->altRefracted(), skyObj->az() ); } else { setDestination( *skyObj ); }*/ //Update selected SkyObject (used in FindDialog, DetailDialog) m_ClickedObjectLite->setObject(skyObj); emit objectLiteChanged(); slotCenter(); } void SkyMapLite::setZoomFactor(double factor) { Options::setZoomFactor( KSUtils::clamp(factor, MINZOOM, MAXZOOM) ); forceUpdate(); emit zoomChanged(); } void SkyMapLite::forceUpdate() { setupProjector(); // We delay one draw cycle before re-indexing // we MUST ensure CLines do not get re-indexed while we use DRAW_BUF // so we do it here. //m_CLines->reindex( &m_reindexNum ); // This queues re-indexing for the next draw cycle //m_reindexNum = KSNumbers( data->updateNum()->julianDay() ); // This ensures that the JIT updates are synchronized for the entire draw // cycle so the sky moves as a single sheet. May not be needed. data->syncUpdateIDs(); SkyMesh *m_skyMesh = SkyMesh::Instance(3); if(m_skyMesh) { // prepare the aperture // FIXME_FOV: We may want to rejigger this to allow // wide-angle views --hdevalence double radius = m_proj->fov(); if ( radius > 180.0 ) radius = 180.0; if ( m_skyMesh->inDraw() ) { printf("Warning: aborting concurrent SkyMapComposite::draw()\n"); return; } //m_skyMesh->inDraw( true ); m_skyMesh->aperture( &Focus, radius + 1.0, DRAW_BUF ); // divide by 2 for testing // create the no-precess aperture if needed if ( Options::showEquatorialGrid() || Options::showHorizontalGrid() || Options::showCBounds() || Options::showEquator() ) { m_skyMesh->index( &Focus, radius + 1.0, NO_PRECESS_BUF ); } } update(); } void SkyMapLite::slotUpdateSky( bool now ) { Q_UNUSED(now); updateFocus(); forceUpdate(); } void SkyMapLite::updateFocus() { if( getSlewing() ) return; //Tracking on an object if ( Options::isTracking() && focusObject() != NULL ) { if ( Options::useAltAz() ) { //Tracking any object in Alt/Az mode requires focus updates focusObject()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); setFocusAltAz( focusObject()->altRefracted(), focusObject()->az() ); focus()->HorizontalToEquatorial( data->lst(), data->geo()->lat() ); setDestination( *focus() ); } else { //Tracking in equatorial coords setFocus( focusObject() ); focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); setDestination( *focus() ); } //Tracking on empty sky } else if ( Options::isTracking() && focusPoint() != NULL ) { if ( Options::useAltAz() ) { //Tracking on empty sky in Alt/Az mode setFocus( focusPoint() ); focus()->EquatorialToHorizontal( data->lst(), data->geo()->lat() ); setDestination( *focus() ); } // Not tracking and not slewing, let sky drift by // This means that horizontal coordinates are constant. } else { focus()->HorizontalToEquatorial(data->lst(), data->geo()->lat() ); } } void SkyMapLite::setupProjector() { //Update View Parameters for projection ViewParams p; p.focus = focus(); p.height = height(); p.width = width(); p.useAltAz = Options::useAltAz(); p.useRefraction = Options::useRefraction(); p.zoomFactor = Options::zoomFactor(); p.fillGround = Options::showGround(); //Check if we need a new projector if( m_proj && Options::projection() == m_proj->type() ) m_proj->setViewParams(p); else { delete m_proj; switch( Options::projection() ) { case Projector::Gnomonic: m_proj = new GnomonicProjector(p); break; case Projector::Stereographic: m_proj = new StereographicProjector(p); break; case Projector::Orthographic: m_proj = new OrthographicProjector(p); break; case Projector::AzimuthalEquidistant: m_proj = new AzimuthalEquidistantProjector(p); break; case Projector::Equirectangular: m_proj = new EquirectangularProjector(p); break; case Projector::Lambert: default: //TODO: implement other projection classes m_proj = new LambertProjector(p); break; } } } void SkyMapLite::setZoomMouseCursor() { mouseMoveCursor = false; // no mousemove cursor QBitmap cursor = zoomCursorBitmap(2); QBitmap mask = zoomCursorBitmap(4); setCursor( QCursor(cursor, mask) ); } void SkyMapLite::setDefaultMouseCursor() { mouseMoveCursor = false; // no mousemove cursor QBitmap cursor = defaultCursorBitmap(2); QBitmap mask = defaultCursorBitmap(3); setCursor( QCursor(cursor, mask) ); } void SkyMapLite::setMouseMoveCursor() { if (mouseButtonDown) { setCursor(Qt::SizeAllCursor); // cursor shape defined in qt mouseMoveCursor = true; } } bool SkyMapLite::isSlewing() const { return (getSlewing() || ( clockSlewing && data->clock()->isActive() ) ); } int SkyMapLite::harvardToIndex(char c) { // Convert spectral class to numerical index. // If spectral class is invalid return index for white star (A class) switch( c ) { case 'o': case 'O': return 0; case 'b': case 'B': return 1; case 'a': case 'A': return 2; case 'f': case 'F': return 3; case 'g': case 'G': return 4; case 'k': case 'K': return 5; case 'm': case 'M': return 6; // For unknown spectral class assume A class (white star) default: return 2; } } QVector> SkyMapLite::getImageCache() { return imageCache; } QSGTexture *SkyMapLite::textToTexture(QString text, QColor color, bool zoomFont) { if(isInitialized) { QFont f; if(zoomFont) { f = SkyLabeler::Instance()->drawFont(); } else { f = SkyLabeler::Instance()->stdFont(); } qreal ratio = window()->effectiveDevicePixelRatio(); QFontMetrics fm(f); int width = fm.width(text); int height = fm.height(); f.setPointSizeF(f.pointSizeF()*ratio); QImage label(width*ratio, height*ratio, QImage::Format_ARGB32_Premultiplied); label.fill(Qt::transparent); m_painter.begin(&label); m_painter.setFont(f); m_painter.setPen( color ); m_painter.drawText(0,(height - fm.descent())*ratio,text); m_painter.end(); QSGTexture *texture = window()->createTextureFromImage(label, QQuickWindow::TextureCanUseAtlas); return texture; } else { return nullptr; } } void SkyMapLite::addFOVSymbol(const QString &FOVName, bool initialState) { m_FOVSymbols.append(FOVName); //Emit signal whenever new value was added emit symbolsFOVChanged(m_FOVSymbols); m_FOVSymVisible.append(initialState); } bool SkyMapLite::isFOVVisible(int index) { return m_FOVSymVisible.value(index); } void SkyMapLite::setFOVVisible(int index, bool visible) { if(index >= 0 && index < m_FOVSymVisible.size()) { m_FOVSymVisible[index] = visible; forceUpdate(); } } void SkyMapLite::setSlewing(bool newSlewing) { if(m_slewing != newSlewing) { m_slewing = newSlewing; emit slewingChanged(newSlewing); } } void SkyMapLite::setCenterLocked(bool centerLocked) { m_centerLocked = centerLocked; emit centerLockedChanged(centerLocked); } void SkyMapLite::initStarImages() { if(isInitialized) { //Delete all existing pixmaps if(imageCache.length() != 0) { foreach(QVector vec, imageCache) { qDeleteAll(vec.begin(), vec.end()); } clearTextures = true; } imageCache = QVector>(nSPclasses); QMap ColorMap; const int starColorIntensity = Options::starColorIntensity(); //On high-dpi screens star will look pixelized if don't multiply scaling factor by this ratio //Check PointNode::setNode() to see how it works qreal ratio = window()->effectiveDevicePixelRatio(); switch( Options::starColorMode() ) { case 1: // Red stars. ColorMap.insert( 'O', QColor::fromRgb( 255, 0, 0 ) ); ColorMap.insert( 'B', QColor::fromRgb( 255, 0, 0 ) ); ColorMap.insert( 'A', QColor::fromRgb( 255, 0, 0 ) ); ColorMap.insert( 'F', QColor::fromRgb( 255, 0, 0 ) ); ColorMap.insert( 'G', QColor::fromRgb( 255, 0, 0 ) ); ColorMap.insert( 'K', QColor::fromRgb( 255, 0, 0 ) ); ColorMap.insert( 'M', QColor::fromRgb( 255, 0, 0 ) ); break; case 2: // Black stars. ColorMap.insert( 'O', QColor::fromRgb( 0, 0, 0 ) ); ColorMap.insert( 'B', QColor::fromRgb( 0, 0, 0 ) ); ColorMap.insert( 'A', QColor::fromRgb( 0, 0, 0 ) ); ColorMap.insert( 'F', QColor::fromRgb( 0, 0, 0 ) ); ColorMap.insert( 'G', QColor::fromRgb( 0, 0, 0 ) ); ColorMap.insert( 'K', QColor::fromRgb( 0, 0, 0 ) ); ColorMap.insert( 'M', QColor::fromRgb( 0, 0, 0 ) ); break; case 3: // White stars ColorMap.insert( 'O', QColor::fromRgb( 255, 255, 255 ) ); ColorMap.insert( 'B', QColor::fromRgb( 255, 255, 255 ) ); ColorMap.insert( 'A', QColor::fromRgb( 255, 255, 255 ) ); ColorMap.insert( 'F', QColor::fromRgb( 255, 255, 255 ) ); ColorMap.insert( 'G', QColor::fromRgb( 255, 255, 255 ) ); ColorMap.insert( 'K', QColor::fromRgb( 255, 255, 255 ) ); ColorMap.insert( 'M', QColor::fromRgb( 255, 255, 255 ) ); case 0: // Real color default: // And use real color for everything else ColorMap.insert( 'O', QColor::fromRgb( 0, 0, 255 ) ); ColorMap.insert( 'B', QColor::fromRgb( 0, 200, 255 ) ); ColorMap.insert( 'A', QColor::fromRgb( 0, 255, 255 ) ); ColorMap.insert( 'F', QColor::fromRgb( 200, 255, 100 ) ); ColorMap.insert( 'G', QColor::fromRgb( 255, 255, 0 ) ); ColorMap.insert( 'K', QColor::fromRgb( 255, 100, 0 ) ); ColorMap.insert( 'M', QColor::fromRgb( 255, 0, 0 ) ); } foreach( char color, ColorMap.keys() ) { //Add new spectral class QPixmap BigImage( 15, 15 ); BigImage.fill( Qt::transparent ); QPainter p; p.begin( &BigImage ); if ( Options::starColorMode() == 0 ) { qreal h, s, v, a; p.setRenderHint( QPainter::Antialiasing, false ); QColor starColor = ColorMap[color]; starColor.getHsvF(&h, &s, &v, &a); for (int i = 0; i < 8; i++ ) { for (int j = 0; j < 8; j++ ) { qreal x = i - 7; qreal y = j - 7; qreal dist = sqrt( x*x + y*y ) / 7.0; starColor.setHsvF(h, qMin( qreal(1), dist < (10-starColorIntensity)/10.0 ? 0 : dist ), v, qMax( qreal(0), dist < (10-starColorIntensity)/20.0 ? 1 : 1-dist ) ); p.setPen( starColor ); p.drawPoint( i, j ); p.drawPoint( (14-i), j ); p.drawPoint( i, (14-j) ); p.drawPoint ((14-i), (14-j)); } } } else { p.setRenderHint(QPainter::Antialiasing, true ); p.setPen( QPen(ColorMap[color], 2.0 ) ); p.setBrush( p.pen().color() ); p.drawEllipse( QRectF( 2, 2, 10, 10 ) ); } p.end(); //[nSPclasses][nStarSizes]; // Cache array slice QVector *pmap = &imageCache[ harvardToIndex(color) ]; pmap->append(new QPixmap(BigImage)); for( int size = 1; size < nStarSizes; size++ ) { pmap->append(new QPixmap(BigImage.scaled( size*ratio, size*ratio, Qt::KeepAspectRatio, Qt::SmoothTransformation ))); } } //} starColorMode = Options::starColorMode(); } } diff --git a/kstars/skymaplite.h b/kstars/skymaplite.h index 05f62945f..b9a05e626 100644 --- a/kstars/skymaplite.h +++ b/kstars/skymaplite.h @@ -1,693 +1,689 @@ /** ************************************************************************* skymaplite.h - K Desktop Planetarium ------------------- begin : 30/04/2016 copyright : (C) 2016 by Artem Fedoskin email : afedoskin3@gmail.com ***************************************************************************/ /** ************************************************************************* * * * This program 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; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef SKYMAPLITE_H_ #define SKYMAPLITE_H_ #include "skyobjects/skypoint.h" #include "skyobjects/skyline.h" #include #include #include #include #include #include #include "kstarsdata.h" #include "kstarslite/skyitems/rootnode.h" -#ifdef HAVE_INDI #include "basedevice.h" -#endif class dms; class KStarsData; class SkyObject; class Projector; class SolarSystemSingleComponent; class PlanetsItem; class AsteroidsItem; class CometsItem; class PlanetMoonsComponent; class HorizonItem; class LinesItem; class SkyNode; class RootNode; class TelescopeLite; class SkyObjectLite; class SkyPointLite; /*class QTapSensor; class QMagnetometer; class QCompass; class QRotationSensor;*/ class QSGTexture; /** @class SkyMapLite * *This is the main item that displays all SkyItems. After its instantiation it is reparanted *to an object with objectName SkyMapLiteWrapper in main.qml. To display SkyItems they are reparanted *to instance of SkyMapLite. * *SkyMapLite handles most user interaction events (both mouse and keyboard). * *@short Item for displaying sky objects; also handles user interaction events. *@author Artem Fedoskin *@version 1.0 */ class SkyMapLite : public QQuickItem { Q_OBJECT /** magnitude limit. Used in QML **/ Q_PROPERTY(double magLim READ getMagLim WRITE setMagLim NOTIFY magLimChanged) /** wrappers for clickedPoint and clickedObject. Used to set clicked object and point from QML **/ Q_PROPERTY(SkyPointLite *clickedPointLite READ getClickedPointLite NOTIFY pointLiteChanged) Q_PROPERTY(SkyObjectLite *clickedObjectLite READ getClickedObjectLite NOTIFY objectLiteChanged) /** list of FOVSymbols that are currently available **/ Q_PROPERTY(QStringList FOVSymbols READ getFOVSymbols NOTIFY symbolsFOVChanged) /** true if SkyMapLite is being panned **/ Q_PROPERTY(bool slewing READ getSlewing WRITE setSlewing NOTIFY slewingChanged) /** * @short true if SkyMapLite is centered on an object and only pinch-to-zoom needs to be available **/ Q_PROPERTY(bool centerLocked READ getCenterLocked WRITE setCenterLocked NOTIFY centerLockedChanged) protected: /** Constructor. **/ explicit SkyMapLite(); /** Updates SkyMapLite by calling RootNode::update(), which in turn initiates update of all child nodes. **/ virtual QSGNode* updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData); /** pointer to RootNode. Use it to universally access RootNode * @warning RootNode should be used solely during updatePaintNode! See Qt Quick Scene Graph documentation. **/ static RootNode *m_rootNode; public: /** Creates instance of SkyMapLite (delete the old one if any) **/ static SkyMapLite* createInstance(); /** Bind size to parent's size and initialize star images **/ void initialize(QQuickItem *parent); static SkyMapLite* Instance() { return pinstance; } static bool IsSlewing() { return pinstance->isSlewing(); } /** Destructor. Clear star images.*/ ~SkyMapLite(); /** * @short skyNode will be deleted on the next call to updatePaintNode (currently used only in * StarNode(struct in StarBlock)) */ void deleteSkyNode(SkyNode *skyNode); /** @short Update the focus position according to current options. */ void updateFocus(); /** @short Retrieve the Focus point; the position on the sky at the *center of the skymap. *@return a pointer to the central focus point of the sky map */ SkyPoint* focus() { return &Focus; } /** @short retrieve the Destination position. * *The Destination is the point on the sky to which the focus will be moved. *@return a pointer to the destination point of the sky map */ SkyPoint* destination() { return &Destination; } /** @short retrieve the FocusPoint position. * *The FocusPoint stores the position on the sky that is to be *focused next. This is not exactly the same as the Destination *point, because when the Destination is set, it will begin slewing *immediately. * *@return a pointer to the sky point which is to be focused next. */ SkyPoint* focusPoint() { return &FocusPoint; } /** @short sets the central focus point of the sky map. *@param f a pointer to the SkyPoint the map should be centered on */ void setFocus( SkyPoint *f ); /** @short sets the focus point of the skymap, using ra/dec coordinates * *@note This function behaves essentially like the above function. *It differs only in the data types of its arguments. * *@param ra the new right ascension *@param dec the new declination */ void setFocus( const dms &ra, const dms &dec ); /** @short sets the focus point of the sky map, using its alt/az coordinates *@param alt the new altitude *@param az the new azimuth */ void setFocusAltAz( const dms &alt, const dms & az); /** @short sets the destination point of the sky map. *@note setDestination() emits the destinationChanged() SIGNAL, *which triggers the SLOT function SkyMap::slewFocus(). This *function iteratively steps the Focus point toward Destination, *repainting the sky at each step (if Options::useAnimatedSlewing()==true). *@param f a pointer to the SkyPoint the map should slew to */ void setDestination( const SkyPoint& f ); /** @short sets the destination point of the skymap, using ra/dec coordinates. * *@note This function behaves essentially like the above function. *It differs only in the data types of its arguments. * *@param ra the new right ascension *@param dec the new declination */ void setDestination( const dms &ra, const dms &dec ); /** @short sets the destination point of the sky map, using its alt/az coordinates. *@param alt the new altitude *@param az the new azimuth */ void setDestinationAltAz( const dms &alt, const dms & az); /** @short set the FocusPoint; the position that is to be the next Destination. *@param f a pointer to the FocusPoint SkyPoint. */ void setFocusPoint( SkyPoint *f ) { if ( f ) FocusPoint = *f; } /** @short Retrieve the ClickedPoint position. * *When the user clicks on a point in the sky map, the sky coordinates of the mouse *cursor are stored in the private member ClickedPoint. This function retrieves *a pointer to ClickedPoint. *@return a pointer to ClickedPoint, the sky coordinates where the user clicked. */ SkyPoint* clickedPoint() { return &ClickedPoint; } /** @short Set the ClickedPoint to the skypoint given as an argument. *@param f pointer to the new ClickedPoint. */ void setClickedPoint( SkyPoint *f ); /** @short Retrieve the object nearest to a mouse click event. * *If the user clicks on the sky map, a pointer to the nearest SkyObject is stored in *the private member ClickedObject. This function returns the ClickedObject pointer, *or NULL if there is no CLickedObject. *@return a pointer to the object nearest to a user mouse click. */ SkyObject* clickedObject() const { return ClickedObject; } /** @short Set the ClickedObject pointer to the argument. *@param o pointer to the SkyObject to be assigned as the ClickedObject */ void setClickedObject( SkyObject *o ); /** @short Retrieve the object which is centered in the sky map. * *If the user centers the sky map on an object (by double-clicking or using the *Find Object dialog), a pointer to the "focused" object is stored in *the private member FocusObject. This function returns a pointer to the *FocusObject, or NULL if there is not FocusObject. *@return a pointer to the object at the center of the sky map. */ SkyObject* focusObject() const { return FocusObject; } /** @short Set the FocusObject pointer to the argument. *@param o pointer to the SkyObject to be assigned as the FocusObject */ void setFocusObject( SkyObject *o ); /** @ Set zoom factor. *@param factor zoom factor */ void setZoomFactor(double factor); /** @short Call to set up the projector before update of SkyItems positions begins. */ void setupProjector(); /** @short Returns index for a Harvard spectral classification */ int harvardToIndex(char c); /** @short returns cache of star images * @return star images cache */ QVector> getImageCache(); /** * @short creates QImage from text and converts it to QSGTexture * @param color text color * @param zoomFont if true zoom-dependent font from SkyLabeler will be used else standart * font is used * @return QSGTexture with text * @note font size is set in SkyLabeler::SkyLabeler() by initializing m_stdFont with default font */ QSGTexture *textToTexture(QString text, QColor color = QColor(255,255,255), bool zoomFont = false); /** * @short returns cached texture from textureCache. * * Use outside of scene graph rendering thread (e.g. not during call to updatePaintNode) * is prohibited! * @param size size of the star * @param spType spectral class * @return cached QSGTexture from textureCache */ QSGTexture* getCachedTexture(int size, char spType); /** @short called when SkyMapComposite finished loading all SkyComponents */ inline void loadingFinished() { m_loadingFinished = true; } /** @return true if the map is in slewing mode or clock is active **/ bool isSlewing() const; /** @return current magnitude limit **/ inline double getMagLim() { return m_magLim; } /** @short set magnitude limit **/ void setMagLim(double magLim); /** @short Convenience function for shutting off tracking mode. Just calls KStars::slotTrack() **/ void stopTracking(); /** Get the current projector. @return a pointer to the current projector. */ inline const Projector * projector() const { return m_proj; } /** * @short used in QML * @return type of current projection system */ Q_INVOKABLE uint projType() const; /** Set magnitude limit for size of stars. Used in StarItem **/ inline void setSizeMagLim(float sizeMagLim) { m_sizeMagLim = sizeMagLim; } /** Used in PointSourceNode **/ inline float sizeMagLim() const { return m_sizeMagLim; } static inline RootNode *rootNode() { return m_rootNode; } static inline void setRootNode(RootNode *root) { m_rootNode = root; } /** return limit of hides for the node to delete it **/ static double deleteLimit(); /** * @short adds FOV symbol to m_FOVSymbols * @param FOVName name of a FOV symbol */ Q_INVOKABLE void addFOVSymbol(const QString& FOVName, bool initialState = false); /** * @param index of FOVSymbol in m_FOVSymbols * @return true if FOV symbol with name FOVName should be drawn. */ bool isFOVVisible(int index); /** * @param index of FOVSymbol in m_FOVSymbols * @short updates visibility of FOV symbol according to visible */ Q_INVOKABLE void setFOVVisible(int index, bool visible); /** * @short this QList should be used as a model in QML to switch on/off FOV symbols **/ Q_INVOKABLE inline QStringList getFOVSymbols() { return m_FOVSymbols; } /** @short Initializes images of Stars and puts them in cache (copied from SkyQPainter)*/ void initStarImages(); /** * @short getter for clickedPointLite */ SkyPointLite *getClickedPointLite() { return m_ClickedPointLite; } /** * @short getter for clickedObjectLite */ SkyObjectLite *getClickedObjectLite() { return m_ClickedObjectLite; } /** * @short getter for centerLocked */ bool getCenterLocked() { return m_centerLocked; } /** * @short Proxy method for SkyMapDrawAbstract::drawObjectLabels() */ //inline void drawObjectLabels( QList< SkyObject* >& labelObjects ) { dynamic_cast(m_SkyMapDraw)->drawObjectLabels( labelObjects ); } /** * @return true if SkyMapLite is being slewed */ bool getSlewing() const { return m_slewing; } /** * @short sets whether SkyMapLite is being slewed */ void setSlewing(bool newSlewing); /** * @short sets whether SkyMapLite is centered on an object and locked(olny pinch-to-zoom is available) */ void setCenterLocked(bool centerLocked); public slots: /** Called whenever wrappers' width or height are changed. Probably will be used to * update positions of items. */ void resizeItem(); /** Recalculates the positions of objects in the sky, and then repaints the sky map. */ void forceUpdate(); /** @short Left for compatibility reasons * @see forceUpdate() */ void forceUpdateNow() { forceUpdate(); } /** * @short Update the focus point and call forceUpdate() * @param now is saved for compatibility reasons */ void slotUpdateSky( bool now ); /** Step the Focus point toward the Destination point. Do this iteratively, redrawing the Sky * Map after each step, until the Focus point is within 1 step of the Destination point. * For the final step, snap directly to Destination, and redraw the map. */ void slewFocus(); /** @short Center the display at the point ClickedPoint. * * The essential part of the function is to simply set the Destination point, which will emit * the destinationChanged() SIGNAL, which triggers the slewFocus() SLOT. Additionally, this * function performs some bookkeeping tasks, such updating whether we are tracking the new * object/position, adding a Planet Trail if required, etc. * * @see destinationChanged() * @see slewFocus() */ void slotCenter(); /** Checks whether the timestep exceeds a threshold value. If so, sets * ClockSlewing=true and sets the SimClock to ManualMode. */ void slotClockSlewing(); /** Zoom in one step. */ void slotZoomIn(); /** Zoom out one step. */ void slotZoomOut(); /** Set default zoom. */ void slotZoomDefault(); /** * @short centres skyObj in SkyMap and opens context drawer with skyObj * Used in FindDialogLite */ void slotSelectObject(SkyObject *skyObj); /** * @short slotGyroMove called when m_gyroSensor got new reading. Moves focus of SkyMapLite according * to coordinates received from gyroscope */ //void slotCompassMove(); signals: /** Emitted by setDestination(), and connected to slewFocus(). Whenever the Destination * point is changed, slewFocus() will iteratively step the Focus toward Destination * until it is reached. * @see SkyMap::setDestination() * @see SkyMap::slewFocus() */ void destinationChanged(); /** Emitted when zoom level is changed. */ void zoomChanged(); /** Emitted when current object changed. */ void objectChanged(); /** Wrapper of ClickedObject for QML **/ void objectLiteChanged(); /** Wrapper of ClickedPoint for QML **/ void pointLiteChanged(); /** Emitted when pointing changed. (At least should) */ void positionChanged(); /** Emitted when position under mouse changed. */ void mousePointChanged(SkyPoint*); /** Emitted when a position is clicked */ void positionClicked(SkyPoint*); /** Emitted when user clicks on SkyMapLite (analogous to positionClicked but sends QPoint) */ void posClicked(QPointF pos); /** Emitted when magnitude limit is changed */ void magLimChanged(double magLim); /** Emitted when FOVSymbols list was changed (new value appended) **/ void symbolsFOVChanged(QStringList); /** Emitted when SkyMapLite is being slewed or slewing is finished **/ void slewingChanged(bool); void centerLockedChanged(bool); protected: /** Process keystrokes: * @li arrow keys Slew the map * @li +/- keys Zoom in and out * @li Space Toggle between Horizontal and Equatorial coordinate systems * @li 0-9 Go to a major Solar System body (0=Sun; 1-9 are the major planets, except 3=Moon) * @li [ Place starting point for measuring an angular distance * @li ] End point for Angular Distance; display measurement. * @li Escape Cancel Angular measurement * @li ,/< Step backward one time step * @li ./> Step forward one time step */ //virtual void keyPressEvent( QKeyEvent *e ); /** When keyRelease is triggered, just set the "slewing" flag to false, * and update the display (to draw objects that are hidden when slewing==true). */ //virtual void keyReleaseEvent( QKeyEvent *e ); /** Determine RA, Dec coordinates of clicked location. Find the SkyObject * which is nearest to the clicked location. * * If left-clicked: Set set mouseButtonDown==true, slewing==true; display * nearest object name in status bar. * If right-clicked: display popup menu appropriate for nearest object. */ virtual void mousePressEvent( QMouseEvent *e ); /** set mouseButtonDown==false, slewing==false */ virtual void mouseReleaseEvent( QMouseEvent *e ); /** Center SkyMap at double-clicked location */ virtual void mouseDoubleClickEvent( QMouseEvent *e ); /** This function does several different things depending on the state of the program: * @li If Angle-measurement mode is active, update the end-ruler point to the mouse cursor, * and continue this function. * @li If we are defining a ZoomBox, update the ZoomBox rectangle, redraw the screen, * and return. * @li If dragging the mouse in the map, update focus such that RA, Dec under the mouse * cursor remains constant. * @li If just moving the mouse, simply update the curso coordinates in the status bar. */ virtual void mouseMoveEvent( QMouseEvent *e ); /** Zoom in and out with the mouse wheel. */ virtual void wheelEvent( QWheelEvent *e ); /** * @short this function handles zooming in and out using "pinch to zoom" gesture */ virtual void touchEvent( QTouchEvent *e); private slots: /** @short display tooltip for object under cursor. It's called by m_HoverTimer. * if mouse didn't moved for last HOVER_INTERVAL milliseconds. */ //void slotTransientLabel(); /** Set the shape of mouse cursor to a cross with 4 arrows. */ void setMouseMoveCursor(); private: /** @short Sets the shape of the default mouse cursor to a cross. */ void setDefaultMouseCursor(); /** @short Sets the shape of the mouse cursor to a magnifying glass. */ void setZoomMouseCursor(); /** Calculate the zoom factor for the given keyboard modifier */ double zoomFactor( const int modifier ); /** calculate the magnitude factor (1, .5, .2, or .1) for the given * keyboard modifier. */ double magFactor( const int modifier ); /** Decrease the magnitude limit by a step size determined by the * keyboard modifier. * @param modifier */ void decMagLimit( const int modifier ); /** Increase the magnitude limit by a step size determined by the * keyboard modifier. * @param modifier */ void incMagLimit( const int modifier ); /** Convenience routine to either zoom in or increase mag limit * depending on the Alt modifier. The Shift and Control modiifers * will adjust the size of the zoom or the mag step. * @param modifier */ void zoomInOrMagStep( const int modifier ); /** Convenience routine to either zoom out or decraase mag limit * depending on the Alt modifier. The Shift and Control modiifers * will adjust the size of the zoom or the mag step. * @param modifier */ void zoomOutOrMagStep( const int modifier ); //True if SkyMapLite was initialized (star images were initialized etc.) bool isInitialized; bool mouseButtonDown, midMouseButtonDown; // true if mouseMoveEvent; needed by setMouseMoveCursor bool mouseMoveCursor; bool m_slewing; bool clockSlewing; // true if pinch to zoom or pinch to rotate is performed bool pinch; //if false only old pixmap will repainted with bitBlt(), this // saves a lot of cpu usage bool computeSkymap; // True if we are either looking for angular distance or star hopping directions //bool rulerMode; // True only if we are looking for star hopping directions. If // false while rulerMode is true, it means we are measuring angular // distance. FIXME: Find a better way to do this //bool starHopDefineMode; double y0; //double m_Scale; int count; KStarsData *data; //True if SkyMapComposite has finished loading of SkyComponents bool m_loadingFinished; /** @short Coordinates of point under cursor. It's update in * function mouseMoveEvent */ SkyPoint m_MousePoint; SkyPoint Focus, ClickedPoint, FocusPoint, Destination; SkyObject *ClickedObject, *FocusObject; SkyPointLite *m_ClickedPointLite; SkyObjectLite *m_ClickedObjectLite; bool m_centerLocked; //SkyLine AngularRuler; //The line for measuring angles in the map QRect ZoomRect; //The manual-focus circle. // Mouse should not move for that interval to display tooltip static const int HOVER_INTERVAL = 500; // Timer for tooltips QTimer m_HoverTimer; bool m_objPointingMode; bool m_fovCaptureMode; Projector* m_proj; static SkyMapLite *pinstance; QQuickItem *m_SkyMapLiteWrapper; ///Holds SkyNodes that need to be deleted QLinkedList m_deleteNodes; float m_sizeMagLim; //Used in PointSourceNode double m_magLim; //Mag limit for all objects /// Used to notify zoom-dependent labels about font size change bool m_fontSizeChanged; /// Used for drawing labels QPainter m_painter; /** This timer is triggered every time user touches the screen with one finger. If touch was released within 500 milliseconds than it is a tap, otherwise we pan. **/ QTimer m_tapBeganTimer; static int starColorMode; const SkyPoint *m_rulerStartPoint; // Good to keep the original ruler start-point for purposes of dynamic_cast QStringList m_FOVSymbols; QList m_FOVSymVisible; // This can be later changed // Total number of sizes of stars. const int nStarSizes; // Total number of specatral classes // N.B. Must be in sync with harvardToIndex const int nSPclasses; //This can be later changed // Cache for star images. QVector> imageCache; //Textures created from cached star images QVector> textureCache; bool clearTextures; bool tapBegan; -#ifdef HAVE_INDI QList m_newTelescopes; QList m_delTelescopes; -#endif }; #endif