diff --git a/CMakeLists.txt b/CMakeLists.txt index fa038da9e..dda478483 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,440 +1,439 @@ PROJECT(kstars CXX C) set (KStars_VERSION_MAJOR 2) set (KStars_VERSION_MINOR 9) set (KStars_VERSION_REVISION 5) 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) string(TIMESTAMP KSTARS_BUILD_TS UTC) 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) # Ccache support IF (ANDROID OR UNIX OR APPLE) FIND_PROGRAM(CCACHE_FOUND ccache) SET(CCACHE_SUPPORT OFF CACHE BOOL "Enable ccache support") IF ((CCACHE_FOUND OR ANDROID) AND CCACHE_SUPPORT MATCHES ON) SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) SET_PROPERTY(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) ENDIF () ENDIF () if(CMAKE_SYSTEM_NAME STREQUAL Android) add_definitions(-DANDROID -D__STDC_LIMIT_MACROS) set(ANDROID TRUE) endif() if(CMAKE_TOOLCHAIN_FILE STREQUAL ${CMAKE_SOURCE_DIR}/android/toolchain-android.cmake) include(${CMAKE_BINARY_DIR}/kf5/kde/install/share/ECM/cmake/ECMConfig.cmake) 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) if(CMAKE_TOOLCHAIN_FILE STREQUAL ${CMAKE_SOURCE_DIR}/android/toolchain-android.cmake) set(QT_ANDROID $ENV{QT_ANDROID}) include(${QT_ANDROID}/lib/cmake/Qt5/Qt5Config.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Core/Qt5CoreConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Gui/Qt5GuiConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Qml/Qt5QmlConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Quick/Qt5QuickConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5QuickControls2/Qt5QuickControls2Config.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Xml/Qt5XmlConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Svg/Qt5SvgConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Sql/Qt5SqlConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Network/Qt5NetworkConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Positioning/Qt5PositioningConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5Concurrent/Qt5ConcurrentConfig.cmake) include(${QT_ANDROID}/lib/cmake/Qt5AndroidExtras/Qt5AndroidExtrasConfig.cmake) else() if(ANDROID) list(APPEND QT_EXTRA_COMPONENTS AndroidExtras) endif() find_package(Qt5 5.7 REQUIRED COMPONENTS Gui Qml Quick QuickControls2 Xml Svg Sql Network Positioning Concurrent ${QT_EXTRA_COMPONENTS}) endif() else() #find_package(Qt5 5.4 REQUIRED COMPONENTS Gui Qml Quick Xml Sql Svg Network PrintSupport Positioning Concurrent) find_package(Qt5 5.4 REQUIRED COMPONENTS Gui Qml Quick Xml Sql Svg Network PrintSupport Concurrent) endif() include(ExternalProject) include(ECMInstallIcons) include(ECMAddAppIcon) include(KDEInstallDirs) include(MacroBoolTo01) include(ECMQtDeclareLoggingCategory) if(NOT CMAKE_TOOLCHAIN_FILE STREQUAL ${CMAKE_SOURCE_DIR}/android/toolchain-android.cmake) #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) if(CMAKE_TOOLCHAIN_FILE STREQUAL ${CMAKE_SOURCE_DIR}/android/toolchain-android.cmake) set(KF5_VERSION 5.28.0) set(KF5_HOST_TOOLING /usr/lib/x86_64-linux-gnu/cmake/) include(${CMAKE_BINARY_DIR}/kf5/kde/install/lib/cmake/KF5Config/KF5ConfigConfig.cmake) include(${CMAKE_BINARY_DIR}/kf5/kde/install/lib/cmake/KF5I18n/KF5I18nConfig.cmake) include(${CMAKE_BINARY_DIR}/kf5/kde/install/lib/cmake/KF5Plotting/KF5PlottingConfig.cmake) else() find_package(KF5 REQUIRED COMPONENTS Config I18n Plotting) endif() else(BUILD_KSTARS_LITE) # Find Optional package NotifyConfig for desktop notifications find_package(KF5 COMPONENTS NotifyConfig) MACRO_BOOL_TO_01(KF5NotifyConfig_FOUND HAVE_NOTIFYCONFIG) find_package(KF5 REQUIRED COMPONENTS Auth Config Crash DocTools WidgetsAddons NewStuff I18n KIO XmlGui Plotting Notifications ) endif(BUILD_KSTARS_LITE) ## Eigen3 Library find_package(Eigen3 REQUIRED) add_definitions(${EIGEN_DEFINITIONS}) include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR}) ## CFITSIO Library if(ANDROID) if(CMAKE_TOOLCHAIN_FILE STREQUAL ${CMAKE_SOURCE_DIR}/android/toolchain-android.cmake) set(extra_cmake "-DM_LIB=-lm") endif() externalproject_add(cfitsio SOURCE_DIR "${CMAKE_BINARY_DIR}/android/3rdparty/cfitsio" URL https://heasarc.gsfc.nasa.gov/FTP/software/fitsio/c/cfitsio3370.tar.gz PATCH_COMMAND bash -c "cd ${CMAKE_BINARY_DIR}/android/3rdparty/cfitsio && dos2unix ${CMAKE_BINARY_DIR}/android/3rdparty/cfitsio/CMakeLists.txt && patch -p1 < ${CMAKE_SOURCE_DIR}/android/3rdparty/cfitsio.patch" CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} ${extra_cmake} BUILD_COMMAND make cfitsio BUILD_IN_SOURCE 1 INSTALL_COMMAND "") set(CFITSIO_FOUND TRUE) set(CFITSIO_INCLUDE_DIR PUBLIC ${CMAKE_BINARY_DIR}/android/3rdparty/cfitsio) set(CFITSIO_LIBRARIES ${CMAKE_BINARY_DIR}/android/3rdparty/cfitsio/libcfitsio.a) else() if(BUILD_KSTARS_LITE) find_package(CFitsio REQUIRED) else() find_package(CFitsio) endif() endif() MACRO_BOOL_TO_01(CFITSIO_FOUND HAVE_CFITSIO) 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.") ## INDI Library if (ANDROID) set(QT_ANDROID $ENV{QT_ANDROID}) if(CMAKE_TOOLCHAIN_FILE STREQUAL ${CMAKE_SOURCE_DIR}/android/toolchain-android.cmake) set(extra_cmake -DCMAKE_AR=${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar) endif() externalproject_add(indi SOURCE_DIR "${CMAKE_BINARY_DIR}/android/indi" URL https://github.com/indilib/indi/archive/master.zip CONFIGURE_COMMAND cd libindi && cmake . -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \\ -DINDI_BUILD_POSIX_CLIENT=OFF -DINDI_BUILD_SERVER=OFF -DINDI_BUILD_DRIVERS=OFF -DINDI_BUILD_UNITTESTS=OFF \\ -DINDI_BUILD_DRIVERS=OFF -DINDI_BUILD_QT5_CLIENT=ON -DINDI_CALCULATE_MINMAX=ON \\ -DCFITSIO_DIR=${CMAKE_BINARY_DIR}/android/3rdparty/cfitsio -DQT_ANDROID=${QT_ANDROID} -DCMAKE_PREFIX_PATH=${QT_ANDROID} ${extra_cmake} BUILD_COMMAND make -C libindi BUILD_IN_SOURCE 1 INSTALL_COMMAND "") set(INDI_FOUND TRUE) set(INDI_INCLUDE_DIR ${CMAKE_BINARY_DIR}/android/indi/libindi/libs/indibase ${CMAKE_BINARY_DIR}/android/indi/libindi ${CMAKE_BINARY_DIR}/android/indi/libindi/libs) set(INDI_CLIENT_ANDROID_LIBRARIES ${CMAKE_BINARY_DIR}/android/indi/libindi/libindiclientqt.a) else () find_package(INDI 1.7.1) endif () MACRO_BOOL_TO_01(INDI_FOUND HAVE_INDI) 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.") ## Libraw if(BUILD_KSTARS_LITE AND ANDROID) # OpenMP needed for LibRaw set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp -DLIBRAW_USE_OPENMP") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp -DLIBRAW_USE_OPENMP") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgomp") externalproject_add(raw SOURCE_DIR "${CMAKE_BINARY_DIR}/android/3rdparty/libraw" URL https://www.libraw.org/data/LibRaw-0.17.2.tar.gz PATCH_COMMAND bash -c "cd ${CMAKE_BINARY_DIR}/android/3rdparty/libraw && wget -qO- https://github.com/LibRaw/LibRaw-cmake/archive/master.zip | jar xvf /dev/stdin && rm -rf cmake && mv -f LibRaw-cmake-master/CMakeLists.txt LibRaw-cmake-master/cmake . && patch -p1 < ${CMAKE_SOURCE_DIR}/android/3rdparty/libraw.patch" CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DBUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DENABLE_OPENMP=OFF -DENABLE_LCMS=OFF BUILD_COMMAND make raw BUILD_IN_SOURCE 1 INSTALL_COMMAND "") include_directories(${CMAKE_BINARY_DIR}/android/3rdparty/libraw) set(LIBRAW_LIBRARIES ${CMAKE_BINARY_DIR}/android/3rdparty/libraw/libraw.a) set(LibRaw_FOUND true) else() find_package(LibRaw) endif() MACRO_BOOL_TO_01(LibRaw_FOUND HAVE_LIBRAW) 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.") ## WCS Library find_package(WCSLIB) MACRO_BOOL_TO_01(WCSLIB_FOUND HAVE_WCSLIB) 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.") ## XPlanet find_package(Xplanet) -MACRO_BOOL_TO_01(XPLANET_FOUND HAVE_XPLANET) -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.") +set_package_properties(Xplanet PROPERTIES DESCRIPTION "Renders an image of all the major planets and most satellites" URL "http://xplanet.sourceforge.net" TYPE RUNTIME PURPOSE "Gives KStars support for xplanet.") # Qt5 Data Visualization find_package(Qt5DataVisualization) MACRO_BOOL_TO_01(Qt5DataVisualization_FOUND HAVE_DATAVISUALIZATION) ## Astrometry.net find_package(AstrometryNet) set_package_properties(AstrometryNet PROPERTIES DESCRIPTION "Astrometrics Library" URL "http://www.astrometry.net" TYPE RUNTIME PURPOSE "Support for plate solving in KStars.") ## OpenGL 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_GREATER 5.17.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 (CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions(-DQT_STRICT_ITERATORS) endif() add_definitions(-DQT_NO_CAST_TO_ASCII) if (UNIX) add_definitions(-Dfexceptions) # TEMPORARY: To disable QCustomPlot warning until 2.0.0 is released which fixes these warnings SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-non-virtual-dtor") # Optimize binary size by dropping unneeded symbols at linking stage if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -ffunction-sections") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") endif() endif(UNIX) # Add security (hardening flags) IF (UNIX OR APPLE OR ANDROID) SET(SEC_COMP_FLAGS "-D_FORTIFY_SOURCE=2 -fstack-protector-all -Wcast-align -fPIE") IF (NOT ANDROID AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT APPLE) SET(SEC_COMP_FLAGS "${SEC_COMP_FLAGS} -Wa,--noexecstack") ENDIF () SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SEC_COMP_FLAGS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SEC_COMP_FLAGS}") SET(SEC_LINK_FLAGS "") IF (NOT APPLE) SET(SEC_LINK_FLAGS "${SEC_LINK_FLAGS} -Wl,-z,nodump -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now") ENDIF () IF (NOT ANDROID AND NOT APPLE) SET(SEC_LINK_FLAGS "${SEC_LINK_FLAGS} -pie") ENDIF () SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SEC_LINK_FLAGS}") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SEC_LINK_FLAGS}") ENDIF () # Clang Format support IF (UNIX OR APPLE) SET(FORMAT_CODE OFF CACHE BOOL "Enable Clang Format") IF (FORMAT_CODE MATCHES ON) FILE(GLOB_RECURSE ALL_SOURCE_FILES *.c *.cpp *.h) FOREACH(SOURCE_FILE ${ALL_SOURCE_FILES}) STRING(FIND ${SOURCE_FILE} ${CMAKE_SOURCE_DIR} DIR_FOUND) IF (NOT ${DIR_FOUND} EQUAL 0) LIST(REMOVE_ITEM ALL_SOURCE_FILES ${SOURCE_FILE}) ENDIF () ENDFOREACH () FIND_PROGRAM(CLANGFORMAT_EXE NAMES clang-format-5.0) IF (CLANGFORMAT_EXE) ADD_CUSTOM_TARGET(clang-format COMMAND ${CLANGFORMAT_EXE} -style=file -i ${ALL_SOURCE_FILES}) ENDIF () ENDIF () ENDIF () SET(FIX_WARNINGS OFF CACHE BOOL "Enable strict compilation mode to turn compiler warnings to errors") # Warning, debug and linker flags IF (UNIX OR APPLE) SET(COMP_FLAGS "") SET(LINKER_FLAGS "") # Verbose warnings and turns all to errors SET(COMP_FLAGS "${COMP_FLAGS} -Wall -Wextra") IF (FIX_WARNINGS) SET(COMP_FLAGS "${COMP_FLAGS} -Werror") ENDIF () # Omit problematic warnings IF (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") SET(COMP_FLAGS "${COMP_FLAGS} -Wno-unused-but-set-variable") ENDIF () IF (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 6.9.9) SET(COMP_FLAGS "${COMP_FLAGS} -Wno-format-truncation") ENDIF () IF (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") SET(COMP_FLAGS "${COMP_FLAGS} -Wno-nonnull -Wno-deprecated-declarations") ENDIF () IF (BUILD_KSTARS_LITE AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") SET(COMP_FLAGS "${COMP_FLAGS} -Wno-overloaded-virtual") ENDIF () SET(COMP_FLAGS "${COMP_FLAGS} -g") # Note: The following flags are problematic on older systems with gcc 4.8 IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9.9)) IF (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") SET(COMP_FLAGS "${COMP_FLAGS} -Wno-unused-command-line-argument") ENDIF () FIND_PROGRAM(LDGOLD_FOUND ld.gold) SET(LDGOLD_SUPPORT OFF CACHE BOOL "Enable ld.gold support") # Optional ld.gold is 2x faster than normal ld IF (LDGOLD_FOUND AND LDGOLD_SUPPORT MATCHES ON AND NOT APPLE AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES arm) SET(LINKER_FLAGS "${LINKER_FLAGS} -fuse-ld=gold") # We have Gsl library what is a special case for linking: # The gsl library must be linked with cblas. There are two alternatives for this: libcblas or libgslcblas. # For example, CMake gets the GSL_LIBRARIES linking flags from the pkgconfig (gsl.pc) file on Ubuntu. # This file defines -lgsl -lglscblas for linking flags and if KStars is compiled with Clang, the linker # finds out magically that KStars must be linked against glscblas library, but gslcblas is omitted in linking # stage if KStars is built with gcc. The linker must be instructed explicitly to link against all libraries # passed on command line by -Wl,--no-as-needed. SET(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--no-as-needed") # Use Identical Code Folding SET(COMP_FLAGS "${COMP_FLAGS} -ffunction-sections") SET(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--icf=safe") # Compress the debug sections # Note: Before valgrind 3.12.0, patch should be applied for valgrind (https://bugs.kde.org/show_bug.cgi?id=303877) IF (NOT APPLE AND NOT ANDROID AND NOT CMAKE_SYSTEM_PROCESSOR MATCHES arm AND NOT CMAKE_CXX_CLANG_TIDY) SET(COMP_FLAGS "${COMP_FLAGS} -Wa,--compress-debug-sections") SET(LINKER_FLAGS "${LINKER_FLAGS} -Wl,--compress-debug-sections=zlib") ENDIF () ENDIF () ENDIF () # Apply the flags SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COMP_FLAGS}") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COMP_FLAGS}") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LINKER_FLAGS}") ENDIF () # Sanitizer support SET(SANITIZERS OFF CACHE BOOL "Sanitizer support for gcc and Clang") IF (SANITIZERS AND ((UNIX AND (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR CMAKE_COMPILER_IS_GNUCXX) OR (APPLE AND (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_COMPILER_IS_GNUCXX)))) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=address,undefined -fno-omit-frame-pointer") ENDIF () # Unity build support SET(UNITY_BUILD OFF CACHE BOOL "Enable Unity Build") INCLUDE(UnityBuild) 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 ANDROID) IF (BUILD_TESTING) enable_testing(true) add_subdirectory(Tests) ENDIF() # Make it possible to use the po files fetched by the fetch-translations step ki18n_install("${CMAKE_CURRENT_BINARY_DIR}/po") ENDIF () install(FILES org.kde.kstars.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) # Only build k5auth for Linux if (NOT BUILD_KSTARS_LITE AND ${CMAKE_SYSTEM_NAME} MATCHES "Linux") # This helper file is generated to download astrometry.net index files. add_executable(kauth_kstars_helper kstars/auxiliary/downloadhelper.cpp ${helper_mocs}) target_link_libraries(kauth_kstars_helper Qt5::Core) target_link_libraries(kauth_kstars_helper Qt5::Widgets) target_link_libraries(kauth_kstars_helper KF5::Auth) install(TARGETS kauth_kstars_helper DESTINATION ${KAUTH_HELPER_INSTALL_DIR}) kauth_install_helper_files(kauth_kstars_helper org.kde.kf5auth.kstars root) kauth_install_actions(org.kde.kf5auth.kstars org.kde.kf5auth.kstars.actions) ENDIF () # Final package generation if (CMAKE_TOOLCHAIN_FILE STREQUAL ${CMAKE_SOURCE_DIR}/android/toolchain-android.cmake) set(EXPORT_DIR "${CMAKE_BINARY_DIR}/android/kstars_build_apk/") set(ANDROID_APK_DIR "${CMAKE_SOURCE_DIR}/android/apk/") set(EXECUTABLE_DESTINATION_PATH "${EXPORT_DIR}/libs/armeabi-v7a/libkstars.so") set(ANDROID_NDK $ENV{ANDROID_NDK}) set(ANDROID_SDK_ROOT $ENV{ANDROID_SDK_ROOT}) set(ANDROID_API_LEVEL $ENV{ANDROID_API_LEVEL}) set(ANDROID_TOOLCHAIN arm-linux-androideabi) set(ANDROID_GCC_VERSION 4.9) set(ANDROID_ABI armeabi-v7a) set(_HOST "${CMAKE_HOST_SYSTEM_NAME}-${CMAKE_HOST_SYSTEM_PROCESSOR}") string(TOLOWER "${_HOST}" _HOST) set(ANDROID_SDK_BUILD_TOOLS_REVISION 21.1.1) set(ANDROID_KEYSTORE $ENV{ANDROID_KEYSTORE}) set(ANDROID_KEYSTORE_ALIAS $ENV{ANDROID_KEYSTORE_ALIAS}) configure_file("${CMAKE_SOURCE_DIR}/android/deployment-file.json.in" "${CMAKE_BINARY_DIR}/android/kstars-deployment.json.in") add_custom_target(create-apk-kstars COMMAND cmake -E echo "Generating $ with $/androiddeployqt" COMMAND cmake -E remove_directory "${EXPORT_DIR}" COMMAND cmake -E copy_directory "${CMAKE_SOURCE_DIR}/android/apk" "${EXPORT_DIR}" COMMAND cmake -E copy "$" "${EXECUTABLE_DESTINATION_PATH}" COMMAND cmake -DINPUT_FILE="${CMAKE_BINARY_DIR}/android/kstars-deployment.json.in" -DOUTPUT_FILE="${CMAKE_BINARY_DIR}/android/kstars-deployment.json" "-DTARGET_DIR=${CMAKE_BINARY_DIR}/kstars" "-DTARGET_NAME=kstars" "-DEXPORT_DIR=${CMAKE_INSTALL_PREFIX}" -P ${CMAKE_SOURCE_DIR}/android/specifydependencies.cmake COMMAND $/androiddeployqt --input "${CMAKE_BINARY_DIR}/android/kstars-deployment.json" --output "${EXPORT_DIR}" --android-platform android-${ANDROID_API_LEVEL} --debug --deployment bundled "\\$(ARGS)" COMMAND $/androiddeployqt --input "${CMAKE_BINARY_DIR}/android/kstars-deployment.json" --output "${EXPORT_DIR}" --android-platform android-${ANDROID_API_LEVEL} --release --deployment bundled "\\$(ARGS)" ) if (ANDROID_KEYSTORE AND ANDROID_KEYSTORE_ALIAS) add_custom_target(sign-apk-kstars COMMAND jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ${ANDROID_KEYSTORE} ${CMAKE_BINARY_DIR}/android/kstars_build_apk/bin/QtApp-release-unsigned.apk ${ANDROID_KEYSTORE_ALIAS} COMMAND rm -rf ${CMAKE_BINARY_DIR}/android/kstars_build_apk/bin/kstars-signed.apk COMMAND zipalign -v 4 ${CMAKE_BINARY_DIR}/android/kstars_build_apk/bin/QtApp-release-unsigned.apk ${CMAKE_BINARY_DIR}/android/kstars_build_apk/bin/kstars-signed.apk ) endif () endif () diff --git a/config-kstars.h.cmake b/config-kstars.h.cmake index 724abde5c..398c111a4 100644 --- a/config-kstars.h.cmake +++ b/config-kstars.h.cmake @@ -1,24 +1,21 @@ /* Define if you have fitsio.h */ #cmakedefine HAVE_CFITSIO 1 /* Define if you have indidevapi.h */ #cmakedefine HAVE_INDI 1 -/* Define if you have xplanet */ -#cmakedefine HAVE_XPLANET 1 - /* Define if you have wcslibt */ #cmakedefine HAVE_WCSLIB 1 /* Define if we have KF5 >= 5.18.0 */ #cmakedefine HAVE_KF5WIT 1 /* Define if you have libraw */ #cmakedefine HAVE_LIBRAW 1 /* Define if you have notify config */ #cmakedefine HAVE_NOTIFYCONFIG 1 /* Define if you have Qt5 Data Visualization */ #cmakedefine HAVE_DATAVISUALIZATION 1 diff --git a/kstars/CMakeLists.txt b/kstars/CMakeLists.txt index d07606616..7746fe775 100644 --- a/kstars/CMakeLists.txt +++ b/kstars/CMakeLists.txt @@ -1,1124 +1,1122 @@ add_subdirectory( data ) add_subdirectory( icons ) add_subdirectory( htmesh ) if (${KF5_VERSION} VERSION_EQUAL 5.18.0 OR ${KF5_VERSION} VERSION_GREATER 5.18.0) SET(HAVE_KF5WIT 1) # if(NOT BUILD_KSTARS_LITE) # add_subdirectory( tools/whatsinteresting/qml) # endif(NOT BUILD_KSTARS_LITE) else() SET(HAVE_KF5WIT 0) endif() if (ANDROID AND CMAKE_TOOLCHAIN_FILE) include(${CMAKE_TOOLCHAIN_FILE}) endif () if (NOT ANDROID) find_package(ZLIB REQUIRED) find_package(Threads REQUIRED) endif () if(MSVC) add_definitions(-D_USE_MATH_DEFINES=1) add_definitions(-DNOMINMAX) endif() include_directories( ${kstars_SOURCE_DIR}/kstars ${kstars_SOURCE_DIR}/kstars/skyobjects ${kstars_SOURCE_DIR}/kstars/skycomponents ${kstars_SOURCE_DIR}/kstars/auxiliary ${kstars_SOURCE_DIR}/kstars/time ) if(BUILD_KSTARS_LITE) include_directories( ${kstars_SOURCE_DIR}/kstars/triangle ) else(BUILD_KSTARS_LITE) include_directories( ${kstars_SOURCE_DIR}/kstars/tools ) endif(BUILD_KSTARS_LITE) if(NOT BUILD_KSTARS_LITE) if (CFITSIO_FOUND) set (sep_SRCS fitsviewer/sep/analyse.c fitsviewer/sep/aperture.c fitsviewer/sep/background.c fitsviewer/sep/convolve.c fitsviewer/sep/deblend.c fitsviewer/sep/extract.c fitsviewer/sep/lutz.c fitsviewer/sep/util.c ) set (fits_SRCS fitsviewer/fitslabel.cpp fitsviewer/fitsviewer.cpp fitsviewer/fitstab.cpp fitsviewer/fitsdebayer.cpp fitsviewer/opsfits.cpp ) if (Qt5DataVisualization_FOUND) set(fits_SRCS ${fits_SRCS} fitsviewer/starprofileviewer.cpp) endif() set (fits2_SRCS fitsviewer/bayer.c fitsviewer/fitshistogram.cpp fitsviewer/fitsdata.cpp fitsviewer/fitsview.cpp ) set (fitsui_SRCS fitsviewer/fitsheaderdialog.ui fitsviewer/statform.ui fitsviewer/fitsdebayer.ui indi/streamform.ui indi/recordingoptions.ui fitsviewer/fitshistogramui.ui fitsviewer/opsfits.ui ) include_directories(${CFITSIO_INCLUDE_DIR}) endif(CFITSIO_FOUND) endif(NOT BUILD_KSTARS_LITE) IF (CFITSIO_FOUND AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")) IF (SANITIZERS) SET_SOURCE_FILES_PROPERTIES(fitsviewer/bayer.c PROPERTIES COMPILE_FLAGS "-Wno-cast-align -fno-sanitize=address,undefined -fomit-frame-pointer") SET_SOURCE_FILES_PROPERTIES(fitsviewer/fitsdata.cpp PROPERTIES COMPILE_FLAGS "-fno-sanitize=address,undefined -fomit-frame-pointer") SET_SOURCE_FILES_PROPERTIES(fitsviewer/fitshistogram.cpp PROPERTIES COMPILE_FLAGS "-fno-sanitize=address,undefined -fomit-frame-pointer") SET_SOURCE_FILES_PROPERTIES(fitsviewer/fitsview.cpp PROPERTIES COMPILE_FLAGS "-fno-sanitize=address,undefined -fomit-frame-pointer") ELSE () SET_SOURCE_FILES_PROPERTIES(fitsviewer/bayer.c PROPERTIES COMPILE_FLAGS "-Wno-cast-align") ENDIF () SET_SOURCE_FILES_PROPERTIES(fitsviewer/sep/analyse.c PROPERTIES COMPILE_FLAGS "-Wno-cast-align") SET_SOURCE_FILES_PROPERTIES(fitsviewer/sep/aperture.c PROPERTIES COMPILE_FLAGS "-Wno-cast-align -Wno-pointer-arith") SET_SOURCE_FILES_PROPERTIES(fitsviewer/sep/background.c PROPERTIES COMPILE_FLAGS "-Wno-cast-align") SET_SOURCE_FILES_PROPERTIES(fitsviewer/sep/deblend.c PROPERTIES COMPILE_FLAGS "-Wno-cast-align -Wno-incompatible-pointer-types-discards-qualifiers") SET_SOURCE_FILES_PROPERTIES(fitsviewer/sep/extract.c PROPERTIES COMPILE_FLAGS "-Wno-cast-align") SET_SOURCE_FILES_PROPERTIES(fitsviewer/sep/lutz.c PROPERTIES COMPILE_FLAGS "-Wno-cast-align") SET_SOURCE_FILES_PROPERTIES(fitsviewer/sep/util.c PROPERTIES COMPILE_FLAGS "-Wno-incompatible-pointer-types-discards-qualifiers") ENDIF () if (INDI_FOUND) if(BUILD_KSTARS_LITE) set (fits_SRCS fitsviewer/fitsdata.cpp ) set (fits2_SRCS fitsviewer/bayer.c ) include_directories(${CFITSIO_INCLUDE_DIR}) include_directories(${NOVA_INCLUDE_DIR}) set (indi_SRCS indi/clientmanagerlite.cpp indi/inditelescopelite.cpp kstarslite/skyitems/skynodes/crosshairnode.cpp kstarslite/skyitems/telescopesymbolsitem.cpp ) else(BUILD_KSTARS_LITE) set(indiui_SRCS indi/streamform.ui indi/drivermanager.ui indi/opsindi.ui indi/indihostconf.ui indi/telescopewizard.ui ) set(indi_SRCS indi/drivermanager.cpp indi/servermanager.cpp indi/clientmanager.cpp indi/guimanager.cpp indi/driverinfo.cpp indi/deviceinfo.cpp indi/indidevice.cpp indi/indigroup.cpp indi/indiproperty.cpp indi/indielement.cpp indi/indistd.cpp indi/indilistener.cpp indi/inditelescope.cpp indi/indiccd.cpp indi/indifocuser.cpp indi/indifilter.cpp indi/indidome.cpp indi/indiweather.cpp indi/indicap.cpp indi/indilightbox.cpp indi/indidbus.cpp indi/opsindi.cpp indi/telescopewizardprocess.cpp indi/streamwg.cpp indi/videowg.cpp indi/indiwebmanager.cpp ) if (CFITSIO_FOUND) set(ekosui_SRCS ekos/opsekos.ui ekos/ekosmanager.ui ekos/profileeditor.ui ekos/profilewizard.ui # Scheduler ekos/scheduler/scheduler.ui ekos/scheduler/mosaic.ui # Capture ekos/capture/capture.ui ekos/capture/calibrationoptions.ui ekos/capture/dslrinfo.ui ekos/capture/rotatorsettings.ui ekos/capture/customproperties.ui # Align ekos/align/align.ui ekos/align/opsastrometry.ui ekos/align/opsalign.ui ekos/align/opsastrometrycfg.ui ekos/align/opsastrometryindexfiles.ui ekos/align/mountmodel.ui # Focus ekos/focus/focus.ui # Mount ekos/mount/mount.ui # Guide ekos/guide/guide.ui ekos/guide/opscalibration.ui ekos/guide/opsguide.ui #TODO remove from GIT #ekos/guide/guider.ui #ekos/guide/rcalibration.ui # Auxiliary ekos/auxiliary/filtersettings.ui ekos/auxiliary/opslogs.ui ) set(ekos_SRCS ekos/ekos.cpp ekos/ekosmanager.cpp ekos/profileeditor.cpp ekos/profilewizard.cpp ekos/qMDNS.cpp ekos/opsekos.cpp # Auxiliary ekos/auxiliary/dome.cpp ekos/auxiliary/weather.cpp ekos/auxiliary/dustcap.cpp ekos/auxiliary/darklibrary.cpp ekos/auxiliary/filtermanager.cpp ekos/auxiliary/filterdelegate.cpp ekos/auxiliary/opslogs.cpp # Capture ekos/capture/capture.cpp ekos/capture/sequencejob.cpp ekos/capture/dslrinfodialog.cpp ekos/capture/rotatorsettings.cpp ekos/capture/customproperties.cpp # Scheduler ekos/scheduler/schedulerjob.cpp ekos/scheduler/scheduler.cpp ekos/scheduler/mosaic.cpp # Focus ekos/focus/focus.cpp # Mount ekos/mount/mount.cpp # Align ekos/align/align.cpp ekos/align/alignview.cpp ekos/align/astrometryparser.cpp ekos/align/opsastrometry.cpp ekos/align/opsalign.cpp ekos/align/opsastrometrycfg.cpp ekos/align/opsastrometryindexfiles.cpp ekos/align/offlineastrometryparser.cpp ekos/align/onlineastrometryparser.cpp ekos/align/remoteastrometryparser.cpp # Guide ekos/guide/guide.cpp ekos/guide/guideinterface.cpp ekos/guide/opscalibration.cpp ekos/guide/opsguide.cpp # Internal Guide ekos/guide/internalguide/gmath.cpp ekos/guide/internalguide/internalguider.cpp #ekos/guide/internalguide/guider.cpp ekos/guide/internalguide/matr.cpp #ekos/guide/internalguide/rcalibration.cpp ekos/guide/internalguide/vect.cpp ekos/guide/internalguide/imageautoguiding.cpp # External Guide ekos/guide/externalguide/phd2.cpp ekos/guide/externalguide/linguider.cpp ) endif(CFITSIO_FOUND) endif(BUILD_KSTARS_LITE) include_directories(${INDI_INCLUDE_DIR}) endif (INDI_FOUND) if(NOT BUILD_KSTARS_LITE) if(WCSLIB_FOUND) include_directories( ${WCSLIB_INCLUDE_DIR} ) endif(WCSLIB_FOUND) - if(XPLANET_FOUND) - set(xplanet_SRCS - xplanet/opsxplanet.cpp - ) + set(xplanet_SRCS + xplanet/opsxplanet.cpp + ) - set(xplanetui_SRCS - xplanet/opsxplanet.ui - ) - endif(XPLANET_FOUND) + set(xplanetui_SRCS + xplanet/opsxplanet.ui + ) ########### next target ############### set(libkstarstools_SRCS tools/altvstime.cpp tools/avtplotwidget.cpp tools/calendarwidget.cpp tools/conjunctions.cpp # tools/jmoontool.cpp tools/ksconjunct.cpp tools/eqplotwidget.cpp tools/astrocalc.cpp tools/modcalcangdist.cpp tools/modcalcapcoord.cpp tools/modcalcaltaz.cpp tools/modcalcdaylength.cpp tools/modcalceclipticcoords.cpp tools/modcalcvizequinox.cpp tools/modcalcgalcoord.cpp tools/modcalcgeodcoord.cpp tools/modcalcjd.cpp tools/modcalcplanets.cpp tools/modcalcsidtime.cpp tools/modcalcvlsr.cpp tools/observinglist.cpp tools/obslistpopupmenu.cpp tools/sessionsortfilterproxymodel.cpp tools/obslistwizard.cpp tools/planetviewer.cpp tools/pvplotwidget.cpp tools/scriptargwidgets.cpp tools/scriptbuilder.cpp tools/scriptfunction.cpp tools/skycalendar.cpp tools/wutdialog.cpp tools/flagmanager.cpp tools/horizonmanager.cpp tools/nameresolver.cpp tools/polarishourangle.cpp #FIXME Port to KF5 #tools/moonphasetool.cpp tools/starhopper.cpp tools/eyepiecefield.cpp tools/exporteyepieceview.cpp tools/starhopperdialog.cpp tools/adddeepskyobject.cpp ) if(${KF5_VERSION} VERSION_EQUAL 5.18.0 OR ${KF5_VERSION} VERSION_GREATER 5.18.0) set(libkstarstools_SRCS ${libkstarstools_SRCS} tools/whatsinteresting/skyobjlistmodel.cpp tools/whatsinteresting/wiview.cpp tools/whatsinteresting/modelmanager.cpp tools/whatsinteresting/skyobjitem.cpp tools/whatsinteresting/wilpsettings.cpp tools/whatsinteresting/wiequipsettings.cpp tools/whatsinteresting/obsconditions.cpp tools/whatsinteresting/skyobjdescription.cpp ) endif() ki18n_wrap_ui(libkstarstools_ui_SRCS tools/altvstime.ui tools/argchangeviewoption.ui tools/argexportimage.ui tools/argloadcolorscheme.ui tools/arglooktoward.ui tools/argfindobject.ui tools/argprintimage.ui tools/argsetaltaz.ui tools/argsetcolor.ui tools/argsetgeolocation.ui tools/argsetlocaltime.ui tools/argsetradec.ui tools/argsettrack.ui tools/argtimescale.ui tools/argwaitfor.ui tools/argwaitforkey.ui tools/argzoom.ui tools/conjunctions.ui tools/modcalcangdist.ui tools/modcalcapcoord.ui tools/modcalcaltaz.ui tools/modcalcdaylength.ui tools/modcalceclipticcoords.ui tools/modcalcvizequinox.ui tools/modcalcgalcoord.ui tools/modcalcgeod.ui tools/modcalcjd.ui tools/modcalcplanets.ui tools/modcalcsidtime.ui tools/modcalcvlsr.ui tools/observinglist.ui tools/obslistwizard.ui tools/optionstreeview.ui tools/planetviewer.ui tools/scriptbuilder.ui tools/scriptnamedialog.ui tools/skycalendar.ui tools/wutdialog.ui tools/flagmanager.ui tools/starhopperdialog.ui tools/horizonmanager.ui tools/adddeepskyobject.ui tools/polarishourangle.ui ) if (${KF5_VERSION} VERSION_EQUAL 5.18.0 OR ${KF5_VERSION} VERSION_GREATER 5.18.0) ki18n_wrap_ui(libkstarstools_ui_SRCS tools/whatsinteresting/wilpsettings.ui tools/whatsinteresting/wiequipsettings.ui ) endif() set(libkstarswidgets_SRCS widgets/clicklabel.cpp widgets/dmsbox.cpp widgets/draglistbox.cpp widgets/fovwidget.cpp widgets/logedit.cpp widgets/magnitudespinbox.cpp widgets/mapcanvas.cpp widgets/thumbimage.cpp widgets/timespinbox.cpp widgets/timestepbox.cpp widgets/timeunitbox.cpp widgets/infoboxwidget.cpp # widgets/genericcalendarwidget.cpp # widgets/moonphasecalendarwidget.cpp widgets/kshelplabel.cpp widgets/unitspinboxwidget.cpp ) ki18n_wrap_ui(libkstarswidgets_ui_SRCS # widgets/genericcalendarwidget.ui widgets/unitspinboxwidget.ui ) set(kstars_KCFG_SRCS Options.kcfgc) set(kstars_options_SRCS options/opsadvanced.cpp options/opscatalog.cpp options/opscolors.cpp options/opsguides.cpp options/opssolarsystem.cpp options/opssatellites.cpp options/opssupernovae.cpp ) set(kstars_optionsui_SRCS options/opsadvanced.ui options/opscatalog.ui options/opscolors.ui options/opsguides.ui options/opssolarsystem.ui options/opssatellites.ui options/opssupernovae.ui ) set(kstars_dialogs_SRCS dialogs/addcatdialog.cpp dialogs/addlinkdialog.cpp dialogs/detaildialog.cpp dialogs/finddialog.cpp dialogs/focusdialog.cpp dialogs/fovdialog.cpp dialogs/locationdialog.cpp dialogs/timedialog.cpp dialogs/exportimagedialog.cpp ) set(kstars_dialogsui_SRCS dialogs/addcatdialog.ui dialogs/addlinkdialog.ui dialogs/details_database.ui dialogs/details_data.ui dialogs/details_data_comet.ui dialogs/details_links.ui dialogs/details_log.ui dialogs/details_position.ui dialogs/finddialog.ui dialogs/focusdialog.ui dialogs/fovdialog.ui dialogs/locationdialog.ui dialogs/wizwelcome.ui dialogs/wizlocation.ui dialogs/wizdownload.ui dialogs/wizdata.ui dialogs/wizastrometry.ui dialogs/newfov.ui dialogs/exportimagedialog.ui ) set(hips_SRCS hips/healpix.cpp hips/hipsrenderer.cpp hips/scanrender.cpp hips/pixcache.cpp hips/urlfiledownload.cpp hips/opships.cpp ) set(hips_manager_SRCS hips/hipsmanager.cpp ) set(oal_SRCS oal/log.cpp oal/observer.cpp oal/site.cpp oal/session.cpp oal/scope.cpp oal/eyepiece.cpp oal/filter.cpp oal/observation.cpp oal/lens.cpp oal/equipmentwriter.cpp oal/observeradd.cpp oal/execute.cpp ) set(printing_SRCS printing/detailstable.cpp printing/finderchart.cpp printing/foveditordialog.cpp printing/fovsnapshot.cpp printing/kstarsdocument.cpp printing/legend.cpp printing/loggingform.cpp printing/printingwizard.cpp printing/pwizchartconfig.cpp printing/pwizchartcontents.cpp printing/pwizfovbrowse.cpp printing/pwizfovconfig.cpp printing/pwizfovmanual.cpp printing/pwizfovsh.cpp printing/pwizfovtypeselection.cpp printing/pwizobjectselection.cpp printing/pwizprint.cpp printing/shfovexporter.cpp printing/simplefovexporter.cpp ) set(printingui_SRCS printing/foveditordialog.ui printing/pwizchartconfig.ui printing/pwizchartcontents.ui printing/pwizfovbrowse.ui printing/pwizfovconfig.ui printing/pwizfovmanual.ui printing/pwizfovsh.ui printing/pwizfovtypeselection.ui printing/pwizobjectselection.ui printing/pwizprint.ui printing/pwizwelcome.ui ) endif(NOT BUILD_KSTARS_LITE) set( kstars_KCFG_SRCS Options.kcfgc ) set(libkstarscomponents_SRCS skycomponents/skylabeler.cpp skycomponents/highpmstarlist.cpp skycomponents/skymapcomposite.cpp skycomponents/skymesh.cpp skycomponents/linelistindex.cpp skycomponents/linelistlabel.cpp skycomponents/noprecessindex.cpp skycomponents/listcomponent.cpp skycomponents/pointlistcomponent.cpp skycomponents/solarsystemsinglecomponent.cpp skycomponents/solarsystemlistcomponent.cpp skycomponents/asteroidscomponent.cpp skycomponents/cometscomponent.cpp skycomponents/planetmoonscomponent.cpp skycomponents/solarsystemcomposite.cpp skycomponents/satellitescomponent.cpp skycomponents/starcomponent.cpp skycomponents/deepstarcomponent.cpp skycomponents/deepskycomponent.cpp skycomponents/catalogcomponent.cpp skycomponents/syncedcatalogcomponent.cpp skycomponents/constellationartcomponent.cpp skycomponents/constellationboundarylines.cpp skycomponents/constellationlines.cpp skycomponents/constellationnamescomponent.cpp skycomponents/supernovaecomponent.cpp skycomponents/coordinategrid.cpp skycomponents/equatorialcoordinategrid.cpp skycomponents/horizontalcoordinategrid.cpp skycomponents/localmeridiancomponent.cpp skycomponents/ecliptic.cpp skycomponents/equator.cpp skycomponents/artificialhorizoncomponent.cpp skycomponents/hipscomponent.cpp skycomponents/horizoncomponent.cpp skycomponents/milkyway.cpp skycomponents/skycomponent.cpp skycomponents/skycomposite.cpp skycomponents/starblock.cpp skycomponents/starblocklist.cpp skycomponents/starblockfactory.cpp skycomponents/culturelist.cpp skycomponents/flagcomponent.cpp skycomponents/targetlistcomponent.cpp ) if(NOT BUILD_KSTARS_LITE) LIST(APPEND libkstarscomponents_SRCS #skycomponents/notifyupdatesui.cpp ) else(NOT BUILD_KSTARS_LITE) set(libkstarstools_ui_SRCS tools/nameresolver.cpp ) endif(NOT BUILD_KSTARS_LITE) set(kstars_skyobjects_SRCS skyobjects/constellationsart.cpp skyobjects/deepskyobject.cpp # skyobjects/jupitermoons.cpp skyobjects/planetmoons.cpp skyobjects/ksasteroid.cpp skyobjects/kscomet.cpp skyobjects/ksmoon.cpp skyobjects/ksplanetbase.cpp skyobjects/ksplanet.cpp #skyobjects/kspluto.cpp skyobjects/kssun.cpp skyobjects/skyline.cpp skyobjects/skyobject.cpp skyobjects/skypoint.cpp skyobjects/starobject.cpp skyobjects/trailobject.cpp skyobjects/satellite.cpp skyobjects/satellitegroup.cpp skyobjects/supernova.cpp ) set(kstars_projection_SRCS projections/projector.cpp projections/lambertprojector.cpp projections/gnomonicprojector.cpp projections/stereographicprojector.cpp projections/orthographicprojector.cpp projections/azimuthalequidistantprojector.cpp projections/equirectangularprojector.cpp ) set(kstars_extra_SRCS auxiliary/colorscheme.cpp auxiliary/dms.cpp auxiliary/cachingdms.cpp auxiliary/geolocation.cpp auxiliary/ksfilereader.cpp auxiliary/ksuserdb.cpp auxiliary/binfilehelper.cpp auxiliary/ksutils.cpp auxiliary/ksdssimage.cpp auxiliary/ksdssdownloader.cpp auxiliary/nonlineardoublespinbox.cpp auxiliary/profileinfo.cpp auxiliary/filedownloader.cpp auxiliary/kspaths.cpp auxiliary/QRoundProgressBar.cpp auxiliary/skyobjectlistmodel.cpp auxiliary/ksnotification.cpp auxiliary/QProgressIndicator.cpp time/simclock.cpp time/kstarsdatetime.cpp time/timezonerule.cpp ksnumbers.cpp kstarsdata.cpp texturemanager.cpp #to minimize number of indef KSTARS_LITE skypainter.cpp ) if(NOT BUILD_KSTARS_LITE) LIST(APPEND kstars_extra_SRCS auxiliary/thememanager.cpp auxiliary/schememanager.cpp auxiliary/imageviewer.cpp auxiliary/fov.cpp auxiliary/thumbnailpicker.cpp auxiliary/thumbnaileditor.cpp auxiliary/imageexporter.cpp auxiliary/kswizard.cpp auxiliary/qcustomplot.cpp kstarsdbus.cpp kspopupmenu.cpp ksalmanac.cpp kstarsactions.cpp kstarsinit.cpp kstars.cpp kstarssplash.cpp skymap.cpp skymapdrawabstract.cpp skymapqdraw.cpp skymapevents.cpp skyqpainter.cpp ) endif(NOT BUILD_KSTARS_LITE) if(BUILD_KSTARS_LITE) #Temporary solution to allow use of qml files from source dir DELETE add_definitions( -DSOURCE_DIR=\"${kstars_SOURCE_DIR}\" ) add_definitions(-DQML_IMPORT="${CMAKE_CURRENT_SOURCE_DIR}") set(kstarslite_SRCS kstarslite.cpp kstarsliteinit.cpp skymaplite.cpp skymapliteevents.cpp #Wrappers kstarslite/skypointlite.cpp kstarslite/skyobjectlite.cpp #ImageProvider kstarslite/imageprovider.cpp #Dialogs kstarslite/dialogs/detaildialoglite.cpp kstarslite/dialogs/finddialoglite.cpp kstarslite/dialogs/locationdialoglite.cpp #RootNode kstarslite/skyitems/rootnode.cpp kstarslite/skyitems/skyopacitynode.cpp kstarslite/skyitems/typedeflite.h #SkyItems kstarslite/skyitems/skyitem.cpp kstarslite/skyitems/planetsitem.cpp kstarslite/skyitems/asteroidsitem.cpp kstarslite/skyitems/cometsitem.cpp kstarslite/skyitems/horizonitem.cpp kstarslite/skyitems/labelsitem.cpp kstarslite/skyitems/constellationnamesitem.cpp kstarslite/skyitems/staritem.cpp kstarslite/skyitems/deepstaritem.cpp kstarslite/skyitems/deepskyitem.cpp kstarslite/skyitems/constellationartitem.cpp kstarslite/skyitems/satellitesitem.cpp kstarslite/skyitems/supernovaeitem.cpp kstarslite/skyitems/fovitem.cpp kstarslite/skyitems/syncedcatalogitem.cpp #Line kstarslite/skyitems/lines/linesitem.cpp kstarslite/skyitems/lines/equatoritem.cpp kstarslite/skyitems/lines/eclipticitem.cpp kstarslite/skyitems/lines/milkywayitem.cpp #SkyNodes kstarslite/skyitems/skynodes/planetnode.cpp kstarslite/skyitems/skynodes/skynode.cpp kstarslite/skyitems/skynodes/pointsourcenode.cpp kstarslite/skyitems/skynodes/planetmoonsnode.cpp kstarslite/skyitems/skynodes/horizonnode.cpp kstarslite/skyitems/skynodes/labelnode.cpp kstarslite/skyitems/skynodes/guidelabelnode.cpp kstarslite/skyitems/skynodes/deepskynode.cpp kstarslite/skyitems/skynodes/dsosymbolnode.cpp kstarslite/skyitems/skynodes/skypolygonnode.cpp kstarslite/skyitems/skynodes/constellationartnode.cpp kstarslite/skyitems/skynodes/satellitenode.cpp kstarslite/skyitems/skynodes/supernovanode.cpp kstarslite/skyitems/skynodes/trixelnode.cpp kstarslite/skyitems/skynodes/fovsymbolnode.cpp #Nodes kstarslite/skyitems/skynodes/nodes/pointnode.cpp kstarslite/skyitems/skynodes/nodes/polynode.cpp kstarslite/skyitems/skynodes/nodes/linenode.cpp kstarslite/skyitems/skynodes/nodes/ellipsenode.cpp kstarslite/skyitems/skynodes/nodes/rectnode.cpp #Other kstarslite/deviceorientation.cpp ) set(kstarslite_libtess_SRC #libtess libtess/gluos.h libtess/priorityq-sort.h libtess/sweep.c libtess/tessmono.c libtess/dict-list.h libtess/glu.h libtess/tessellate.c libtess/dict.c libtess/geom.c libtess/memalloc.c libtess/mesh.c libtess/normal.c libtess/priorityq.c libtess/priorityq-heap.c libtess/render.c libtess/tess.c ) IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") SET_SOURCE_FILES_PROPERTIES(${kstarslite_libtess_SRC} PROPERTIES COMPILE_FLAGS "-Wno-error") ENDIF () #Qml files will be probably moved to user's data dir, but for use #with QtCreator it is more convenient to have them here set(kstarsliteqml_SRCS kstarslite/qml/main.qml kstarslite/qml/constants/Constants.qml kstarslite/qml/modules/SkyMapLiteWrapper.qml kstarslite/qml/modules/BottomMenu.qml kstarslite/qml/modules/KSPage.qml kstarslite/qml/modules/KSListView.qml kstarslite/qml/modules/KSLabel.qml kstarslite/qml/modules/KSText.qml kstarslite/qml/modules/KSTabButton.qml kstarslite/qml/modules/KSTab.qml kstarslite/qml/modules/KSTabBarArrow.qml kstarslite/qml/modules/KSTextField.qml kstarslite/qml/modules/KSButton.qml kstarslite/qml/modules/TopMenu.qml kstarslite/qml/modules/helpers/TopMenuButton.qml kstarslite/qml/modules/helpers/BottomMenuButton.qml kstarslite/qml/modules/Splash.qml kstarslite/qml/modules/helpers/TimeSpinBox.qml kstarslite/qml/modules/TimePage.qml #Popups kstarslite/qml/modules/popups/ProjectionsPopup.qml kstarslite/qml/modules/popups/FOVPopup.qml kstarslite/qml/modules/popups/ColorSchemePopup.qml #Menus kstarslite/qml/modules/menus/ContextMenu.qml #Helpers kstarslite/qml/modules/helpers/PassiveNotification.qml kstarslite/qml/modules/helpers/KSMenuItem.qml kstarslite/qml/modules/helpers/TelescopeControl.qml #Dialogs kstarslite/qml/dialogs/FindDialog.qml kstarslite/qml/dialogs/LocationDialog.qml kstarslite/qml/dialogs/DetailsDialog.qml kstarslite/qml/dialogs/helpers/DetailsItem.qml kstarslite/qml/dialogs/helpers/DetailsAddLink.qml kstarslite/qml/dialogs/helpers/LocationEdit.qml kstarslite/qml/dialogs/helpers/LocationLoading.qml kstarslite/qml/dialogs/menus/DetailsLinkMenu.qml kstarslite/qml/dialogs/menus/LocationsGeoMenu.qml #INDI kstarslite/qml/indi/INDIControlPanel.qml kstarslite/qml/indi/DevicePanel.qml kstarslite/qml/indi/ImagePreview.qml kstarslite/qml/indi/modules/MotionControl.qml kstarslite/qml/indi/modules/Led.qml kstarslite/qml/indi/modules/KSLed.qml kstarslite/qml/indi/modules/Property.qml kstarslite/qml/indi/modules/KSComboBox.qml kstarslite/qml/indi/modules/KSButtonSwitch.qml kstarslite/qml/indi/modules/KSCheckBox.qml kstarslite/qml/indi/modules/KSINDIText.qml kstarslite/qml/indi/modules/KSINDITextField.qml kstarslite/qml/indi/modules/KSButtonsSwitchRow.qml #Tutorial kstarslite/qml/modules/tutorial/TutorialPopup.qml kstarslite/qml/modules/tutorial/TutorialExitPopup.qml kstarslite/qml/modules/tutorial/TutorialStep1.qml kstarslite/qml/modules/tutorial/TutorialStep2.qml kstarslite/qml/modules/tutorial/TutorialStep3.qml kstarslite/qml/modules/tutorial/TutorialStep4.qml kstarslite/qml/modules/tutorial/TutorialStep5.qml kstarslite/qml/modules/tutorial/TutorialPane.qml ) add_subdirectory(kstarslite/qml) ADD_CUSTOM_TARGET(kstarsliteqml SOURCES ${kstarsliteqml_SRCS}) if(ANDROID) add_subdirectory(kstarslite/res) endif(ANDROID) endif(BUILD_KSTARS_LITE) set(kstars_SRCS ${indi_SRCS} ${fits_SRCS} ${ekos_SRCS} ${onlineparser_SRCS} ${libkstarswidgets_SRCS} ${libkstarscomponents_SRCS} ${libkstarstools_SRCS} ${kstars_extra_SRCS} ${kstars_gl_SRCS} ${kstars_projection_SRCS} ${xplanet_SRCS} ${kstars_options_SRCS} ${kstars_skyobjects_SRCS} ${kstars_dialogs_SRCS} ${hips_SRCS} ${oal_SRCS} ${printing_SRCS} #KStars Lite ${kstarslite_SRCS} ${indi_lite_SRCS} # Generated files ${libkstarstools_ui_SRCS} ${libkstarswidgets_ui_SRCS} ) # Generate all the necessary QLoggingCategory files ecm_qt_declare_logging_category(kstars_SRCS HEADER kstars_debug.h IDENTIFIER KSTARS CATEGORY_NAME org.kde.kstars) ecm_qt_declare_logging_category(kstars_SRCS HEADER indi_debug.h IDENTIFIER KSTARS_INDI CATEGORY_NAME org.kde.kstars.indi) ecm_qt_declare_logging_category(kstars_SRCS HEADER fits_debug.h IDENTIFIER KSTARS_FITS CATEGORY_NAME org.kde.kstars.fits) ecm_qt_declare_logging_category(kstars_SRCS HEADER ekos_debug.h IDENTIFIER KSTARS_EKOS CATEGORY_NAME org.kde.kstars.ekos) ecm_qt_declare_logging_category(kstars_SRCS HEADER ekos_capture_debug.h IDENTIFIER KSTARS_EKOS_CAPTURE CATEGORY_NAME org.kde.kstars.ekos.capture) ecm_qt_declare_logging_category(kstars_SRCS HEADER ekos_focus_debug.h IDENTIFIER KSTARS_EKOS_FOCUS CATEGORY_NAME org.kde.kstars.ekos.focus) ecm_qt_declare_logging_category(kstars_SRCS HEADER ekos_align_debug.h IDENTIFIER KSTARS_EKOS_ALIGN CATEGORY_NAME org.kde.kstars.ekos.align) ecm_qt_declare_logging_category(kstars_SRCS HEADER ekos_guide_debug.h IDENTIFIER KSTARS_EKOS_GUIDE CATEGORY_NAME org.kde.kstars.ekos.guide) ecm_qt_declare_logging_category(kstars_SRCS HEADER ekos_mount_debug.h IDENTIFIER KSTARS_EKOS_MOUNT CATEGORY_NAME org.kde.kstars.ekos.mount) ecm_qt_declare_logging_category(kstars_SRCS HEADER ekos_scheduler_debug.h IDENTIFIER KSTARS_EKOS_SCHEDULER CATEGORY_NAME org.kde.kstars.ekos.scheduler) kconfig_add_kcfg_files(kstars_SRCS ${kstars_KCFG_SRCS}) IF (UNITY_BUILD) ENABLE_UNITY_BUILD(kstars kstars_SRCS 10 cpp) ENDIF () set(kstars_SRCS ${kstars_SRCS} ${fits2_SRCS} ${sep_SRCS} ${hips_manager_SRCS} ${kstarslite_libtess_SRC}) if(NOT BUILD_KSTARS_LITE) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.xml kstars.h KStars) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.SimClock.xml simclock.h SimClock) if (INDI_FOUND) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.INDI.xml indi/indidbus.h INDIDBus) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.xml ekos/ekosmanager.h EkosManager) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.Capture.xml ekos/capture/capture.h Ekos::Capture) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.Focus.xml ekos/focus/focus.h Ekos::Focus) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.Guide.xml ekos/guide/guide.h Ekos::Guide) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.Align.xml ekos/align/align.h Ekos::Align) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.Mount.xml ekos/mount/mount.h Ekos::Mount) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.Dome.xml ekos/auxiliary/dome.h Ekos::Dome) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.Weather.xml ekos/auxiliary/weather.h Ekos::Weather) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.DustCap.xml ekos/auxiliary/dustcap.h Ekos::DustCap) qt5_add_dbus_adaptor(kstars_SRCS org.kde.kstars.Ekos.Scheduler.xml ekos/scheduler/scheduler.h Ekos::Scheduler) endif(INDI_FOUND) ki18n_wrap_ui(kstars_SRCS ${indiui_SRCS} ${ui_SRCS} ${fitsui_SRCS} ${ekosui_SRCS} ${xplanetui_SRCS} ${kstars_optionsui_SRCS} ${kstars_dialogsui_SRCS} ${printingui_SRCS} auxiliary/thumbnailpicker.ui auxiliary/thumbnaileditor.ui oal/observeradd.ui oal/equipmentwriter.ui oal/execute.ui hips/opships.ui hips/opshipsdisplay.ui hips/opshipscache.ui #skycomponents/notifyupdatesui.ui ) endif(NOT BUILD_KSTARS_LITE) add_library(KStarsLib STATIC ${kstars_SRCS}) if(BUILD_KSTARS_LITE) target_link_libraries(KStarsLib LibKSDataHandlers htmesh KF5::I18n KF5::Plotting KF5::ConfigGui Qt5::Gui Qt5::Sql Qt5::Qml Qt5::Quick Qt5::QuickControls2 Qt5::Positioning Qt5::Concurrent ${ZLIB_LIBRARIES} ) if (ANDROID) target_link_libraries(KStarsLib Qt5::AndroidExtras) endif () else(BUILD_KSTARS_LITE) target_link_libraries(KStarsLib LibKSDataHandlers htmesh KF5::Crash KF5::I18n KF5::NewStuff KF5::KIOFileWidgets KF5::WidgetsAddons KF5::Plotting KF5::Notifications Qt5::Gui Qt5::PrintSupport Qt5::Sql Qt5::Svg Qt5::Qml Qt5::Quick Qt5::Network #Qt5::Positioning Qt5::Concurrent ${ZLIB_LIBRARIES} ) if (Qt5DataVisualization_FOUND) target_link_libraries(KStarsLib Qt5::DataVisualization) endif(Qt5DataVisualization_FOUND) if (KF5NotifyConfig_FOUND) target_link_libraries(KStarsLib KF5::NotifyConfig) endif(KF5NotifyConfig_FOUND) endif(BUILD_KSTARS_LITE) if(NOT WIN32) target_link_libraries(KStarsLib m) endif(NOT WIN32) if (CFITSIO_FOUND) target_include_directories(KStarsLib PUBLIC ${CFITSIO_INCLUDE_DIR}) target_link_libraries(KStarsLib ${CFITSIO_LIBRARIES}) endif(CFITSIO_FOUND) if(INDI_FOUND) if (NOT ANDROID) find_package(Nova REQUIRED) include_directories(${NOVA_INCLUDE_DIR}) endif () ## Support Multiple Platforms. All Require INDI ## WIN32 Desktop: Requires INDI Qt5 Client + GSL ## WIN32 Lite: Requires INDI Qt5 Client ## Linux + MacOS Desktop: Requires INDI Client + GSL ## Linux + MacOS Lite: Requires INDI Qt5 Client ## Android: Requires INDI Qt5 Client built for Android #if(BUILD_KSTARS_LITE) #target_link_libraries(KStarsLib ${CMAKE_THREAD_LIBS_INIT}) #else(BUILD_KSTARS_LITE) if(NOT BUILD_KSTARS_LITE) find_package(GSL REQUIRED) include_directories(${GSL_INCLUDE_DIRS}) target_link_libraries(KStarsLib ${GSL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} KF5::Notifications) endif(NOT BUILD_KSTARS_LITE) if(WIN32 OR ANDROID) if(ANDROID) add_definitions(-DUSE_QT5_INDI) target_link_libraries(KStarsLib ${INDI_CLIENT_ANDROID_LIBRARIES} ${CFITSIO_LIBRARIES} ${LIBRAW_LIBRARIES}) else(ANDROID) target_link_libraries(KStarsLib ${INDI_CLIENT_LIBRARIES} ${NOVA_LIBRARIES}) endif(ANDROID) else(WIN32 OR ANDROID) if(BUILD_KSTARS_LITE) add_definitions(-DUSE_QT5_INDI) target_link_libraries(KStarsLib ${INDI_CLIENT_QT_LIBRARIES} ${NOVA_LIBRARIES} z) else(BUILD_KSTARS_LITE) target_link_libraries(KStarsLib ${INDI_CLIENT_LIBRARIES} ${NOVA_LIBRARIES} z) endif(BUILD_KSTARS_LITE) endif(WIN32 OR ANDROID) endif(INDI_FOUND) if(WCSLIB_FOUND) target_link_libraries(KStarsLib ${WCSLIB_LIBRARIES}) endif (WCSLIB_FOUND) if(LibRaw_FOUND) target_link_libraries(KStarsLib ${LibRaw_LIBRARIES}) endif (LibRaw_FOUND) #FIXME Enable OpenGL Later #if( OPENGL_FOUND ) # target_link_libraries(KStarsLib # ${OPENGL_LIBRARIES} # ${QT_QTOPENGL_LIBRARY} # ) #endif( OPENGL_FOUND ) set (KSTARS_APP_SRCS main.cpp ) if(NOT BUILD_KSTARS_LITE) # add icon to application sources ecm_add_app_icon(KSTARS_APP_SRCS ICONS ${CMAKE_CURRENT_SOURCE_DIR}/icons/16-apps-kstars.png ${CMAKE_CURRENT_SOURCE_DIR}/icons/32-apps-kstars.png ${CMAKE_CURRENT_SOURCE_DIR}/icons/48-apps-kstars.png ${CMAKE_CURRENT_SOURCE_DIR}/icons/64-apps-kstars.png ${CMAKE_CURRENT_SOURCE_DIR}/icons/128-apps-kstars.png ) qt5_add_resources(KSTARS_APP_SRCS data/kstars.qrc) endif(NOT BUILD_KSTARS_LITE) if (CMAKE_TOOLCHAIN_FILE STREQUAL ${CMAKE_SOURCE_DIR}/android/toolchain-android.cmake) add_library(kstars SHARED ${KSTARS_APP_SRCS}) add_dependencies(KStarsLib cfitsio indi raw) set(ANDROID_NDK $ENV{ANDROID_NDK}) # This hack is needed by a strange NDK bug. Some symbols are missing in locale.o (libc.a) at linking stage. But # if we force-link with a working libc.a from android-24, there will be duplicated symbols, some symbols will # conflict with libandroid_support.a what is also needed. # Workaround: Extract the needed locale.o from libc.a of android-24 and link KStars Lite with it. ADD_CUSTOM_TARGET(extract_locale_o COMMAND ar -xv ${ANDROID_NDK}/platforms/android-24/arch-arm/usr/lib/libc.a locale.o WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) ADD_DEPENDENCIES(kstars extract_locale_o) target_link_libraries(kstars KStarsLib ${CMAKE_BINARY_DIR}/locale.o -lgnustl_static) else () if(BUILD_KSTARS_LITE) add_executable(kstars_lite ${KSTARS_APP_SRCS}) target_link_libraries(kstars_lite KStarsLib) else() add_executable(kstars ${KSTARS_APP_SRCS}) target_link_libraries(kstars KStarsLib) endif() endif () if(NOT BUILD_KSTARS_LITE) install(TARGETS kstars ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) ########### install files ############### install(PROGRAMS org.kde.kstars.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(FILES kstars.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) install(FILES kstars.notifyrc DESTINATION ${KNOTIFYRC_INSTALL_DIR}) if(INDI_FOUND) #install(FILES ekos/mount/mountbox.qml DESTINATION ${KDE_INSTALL_DATADIR}/kstars/ekos/mount/qml) #install(DIRECTORY ekos/mount/ DESTINATION ${KDE_INSTALL_DATADIR}/kstars/ekos/mount/qml # FILES_MATCHING PATTERN "*.png") endif() elseif (NOT ANDROID) install(TARGETS kstars_lite ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) endif() diff --git a/kstars/kspopupmenu.cpp b/kstars/kspopupmenu.cpp index bdae03457..d1db0f105 100644 --- a/kstars/kspopupmenu.cpp +++ b/kstars/kspopupmenu.cpp @@ -1,655 +1,653 @@ /*************************************************************************** kspopupmenu.cpp - K Desktop Planetarium ------------------- begin : Sat Feb 27 2003 copyright : (C) 2001 by Jason Harris email : jharris@30doradus.org ***************************************************************************/ /*************************************************************************** * * * 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 "kspopupmenu.h" #include "config-kstars.h" #include "kstars.h" #include "kstarsdata.h" #include "skymap.h" #include "skyobjects/skyobject.h" #include "skyobjects/starobject.h" #include "skyobjects/trailobject.h" #include "skyobjects/deepskyobject.h" #include "skyobjects/ksmoon.h" #include "skyobjects/satellite.h" #include "skyobjects/supernova.h" #include "skycomponents/constellationboundarylines.h" #include "skycomponents/flagcomponent.h" #include "skycomponents/skymapcomposite.h" #include "tools/whatsinteresting/wiview.h" #include "observinglist.h" #ifdef HAVE_INDI #include "indi/indilistener.h" #include "indi/guimanager.h" #include "indi/driverinfo.h" #include "indi/indistd.h" #include "indi/indidevice.h" #include "indi/indigroup.h" #include "indi/indiproperty.h" #include "indi/indielement.h" #include "indi/inditelescope.h" #include #endif #include #include #include namespace { // Convert magnitude to string representation for QLabel QString magToStr(double m) { if (m > -30 && m < 90) return QString("%1m").arg(m, 0, 'f', 2); else return QString(); } // Return object name QString getObjectName(SkyObject *obj) { // FIXME: make logic less convoluted. if (obj->longname() != obj->name()) // Object has proper name { return obj->translatedLongName() + ", " + obj->translatedName(); } else { if (!obj->translatedName2().isEmpty()) return obj->translatedName() + ", " + obj->translatedName2(); else return obj->translatedName(); } } // String representation for rise/set time of object. If object // doesn't rise/set returns descriptive string. // // Second parameter choose between raise and set. 'true' for // raise, 'false' for set. QString riseSetTimeLabel(SkyObject *o, bool isRaise) { KStarsData *data = KStarsData::Instance(); QTime t = o->riseSetTime(data->ut(), data->geo(), isRaise); if (t.isValid()) { //We can round to the nearest minute by simply adding 30 seconds to the time. QString time = QLocale().toString(t.addSecs(30), QLocale::ShortFormat); return isRaise ? i18n("Rise time: %1", time) : i18nc("the time at which an object falls below the horizon", "Set time: %1", time); } if (o->alt().Degrees() > 0) return isRaise ? i18n("No rise time: Circumpolar") : i18n("No set time: Circumpolar"); else return isRaise ? i18n("No rise time: Never rises") : i18n("No set time: Never rises"); } // String representation for transit time for object QString transitTimeLabel(SkyObject *o) { KStarsData *data = KStarsData::Instance(); QTime t = o->transitTime(data->ut(), data->geo()); if (t.isValid()) //We can round to the nearest minute by simply adding 30 seconds to the time. return i18n("Transit time: %1", QLocale().toString(t.addSecs(30), QLocale::ShortFormat)); else return "--:--"; } } KSPopupMenu::KSPopupMenu() : QMenu(KStars::Instance()), m_CurrentFlagIdx(-1), m_EditActionMapping(nullptr), m_DeleteActionMapping(nullptr) { } KSPopupMenu::~KSPopupMenu() { if (m_EditActionMapping) { delete m_EditActionMapping; } if (m_DeleteActionMapping) { delete m_DeleteActionMapping; } } void KSPopupMenu::createEmptyMenu(SkyPoint *nullObj) { KStars *ks = KStars::Instance(); SkyObject o(SkyObject::TYPE_UNKNOWN, nullObj->ra(), nullObj->dec()); o.setAlt(nullObj->alt()); o.setAz(nullObj->az()); initPopupMenu(&o, i18n("Empty sky"), QString(), QString(), false, false); addAction(i18nc("Sloan Digital Sky Survey", "Show SDSS Image"), ks->map(), SLOT(slotSDSS())); addAction(i18nc("Digitized Sky Survey", "Show DSS Image"), ks->map(), SLOT(slotDSS())); } void KSPopupMenu::slotEditFlag() { if (m_CurrentFlagIdx != -1) { KStars::Instance()->map()->slotEditFlag(m_CurrentFlagIdx); } } void KSPopupMenu::slotDeleteFlag() { if (m_CurrentFlagIdx != -1) { KStars::Instance()->map()->slotDeleteFlag(m_CurrentFlagIdx); } } void KSPopupMenu::slotEditFlag(QAction *action) { int idx = m_EditActionMapping->value(action, -1); if (idx == -1) { return; } else { KStars::Instance()->map()->slotEditFlag(idx); } } void KSPopupMenu::slotDeleteFlag(QAction *action) { int idx = m_DeleteActionMapping->value(action, -1); if (idx == -1) { return; } else { KStars::Instance()->map()->slotDeleteFlag(idx); } } void KSPopupMenu::createStarMenu(StarObject *star) { KStars *ks = KStars::Instance(); //Add name, rise/set time, center/track, and detail-window items QString name; if (star->name() != "star") { name = star->translatedLongName(); } else { if (star->getHDIndex()) { name = QString("HD%1").arg(QString::number(star->getHDIndex())); } else { // FIXME: this should be some catalog name too name = "Star"; } } initPopupMenu(star, name, i18n("star"), i18n("%1m, %2", star->mag(), star->sptype())); //If the star is named, add custom items to popup menu based on object's ImageList and InfoList if (star->name() != "star") { addLinksToMenu(star); } else { addAction(i18nc("Sloan Digital Sky Survey", "Show SDSS Image"), ks->map(), SLOT(slotSDSS())); addAction(i18nc("Digitized Sky Survey", "Show DSS Image"), ks->map(), SLOT(slotDSS())); } } void KSPopupMenu::createDeepSkyObjectMenu(DeepSkyObject *obj) { QString name = getObjectName(obj); QString typeName = obj->typeName(); // FIXME: information about angular sizes should be added. QString info = magToStr(obj->mag()); initPopupMenu(obj, name, typeName, info); addLinksToMenu(obj); } void KSPopupMenu::createPlanetMenu(SkyObject *p) { QString info = magToStr(p->mag()); QString type = i18n("Solar system object"); ; initPopupMenu(p, p->translatedName(), type, info); addLinksToMenu(p, false); //don't offer DSS images for planets } void KSPopupMenu::createMoonMenu(KSMoon *moon) { QString info = QString("%1, %2").arg(magToStr(moon->mag()), moon->phaseName()); initPopupMenu(moon, moon->translatedName(), QString(), info); addLinksToMenu(moon, false); //don't offer DSS images for planets } void KSPopupMenu::createSatelliteMenu(Satellite *satellite) { KStars *ks = KStars::Instance(); QString velocity, altitude, range; velocity.setNum(satellite->velocity()); altitude.setNum(satellite->altitude()); range.setNum(satellite->range()); clear(); addFancyLabel(satellite->name()); addFancyLabel(satellite->id()); addFancyLabel(i18n("satellite")); addFancyLabel(KStarsData::Instance()->skyComposite()->constellationBoundary()->constellationName(satellite)); addSeparator(); addFancyLabel(i18n("Velocity: %1 km/s", velocity), -2); addFancyLabel(i18n("Altitude: %1 km", altitude), -2); addFancyLabel(i18n("Range: %1 km", range), -2); addSeparator(); //Insert item for centering on object addAction(i18n("Center && Track"), ks->map(), SLOT(slotCenter())); //Insert item for measuring distances //FIXME: add key shortcut to menu items properly! addAction(i18n("Angular Distance To... ["), ks->map(), SLOT(slotBeginAngularDistance())); addAction(i18n("Starhop from here to... "), ks->map(), SLOT(slotBeginStarHop())); //Insert "Add/Remove Label" item if (ks->map()->isObjectLabeled(satellite)) addAction(i18n("Remove Label"), ks->map(), SLOT(slotRemoveObjectLabel())); else addAction(i18n("Attach Label"), ks->map(), SLOT(slotAddObjectLabel())); } void KSPopupMenu::createSupernovaMenu(Supernova *supernova) { QString name = supernova->name(); float mag = supernova->mag(); float z = supernova->getRedShift(); QString type = supernova->getType(); QString info; if (mag < 99) info += QString("%1m ").arg(mag); info += type; if (z < 99) info += QString(" z: %1").arg(QString::number(z, 'f', 2)); initPopupMenu(supernova, name, i18n("supernova"), info); } void KSPopupMenu::initPopupMenu(SkyObject *obj, const QString &name, const QString &type, QString info, bool showDetails, bool showObsList, bool showFlags) { KStarsData *data = KStarsData::Instance(); SkyMap *map = SkyMap::Instance(); clear(); bool showLabel = (name != i18n("star") && !name.isEmpty()); QString Name = name; if (Name.isEmpty()) Name = i18n("Empty sky"); addFancyLabel(Name); addFancyLabel(type); addFancyLabel(info); addFancyLabel(KStarsData::Instance()->skyComposite()->constellationBoundary()->constellationName(obj)); //Insert Rise/Set/Transit labels SkyObject *o = obj->clone(); addSeparator(); addFancyLabel(riseSetTimeLabel(o, true), -2); addFancyLabel(riseSetTimeLabel(o, false), -2); addFancyLabel(transitTimeLabel(o), -2); addSeparator(); delete o; // Show 'Select this object' item when in object pointing mode and when obj is not empty sky if (map->isInObjectPointingMode() && obj->type() != 21) { addAction(i18n("Select this object"), map, SLOT(slotObjectSelected())); } //Insert item for centering on object addAction(i18n("Center && Track"), map, SLOT(slotCenter())); if (showFlags) { //Insert actions for flag operations initFlagActions(obj); } //Insert item for measuring distances //FIXME: add key shortcut to menu items properly! addAction(i18n("Angular Distance To... ["), map, SLOT(slotBeginAngularDistance())); addAction(i18n("Starhop from here to... "), map, SLOT(slotBeginStarHop())); //Insert item for Showing details dialog if (showDetails) addAction(i18nc("Show Detailed Information Dialog", "Details"), map, SLOT(slotDetail())); //Insert "Add/Remove Label" item if (showLabel) { if (map->isObjectLabeled(obj)) { addAction(i18n("Remove Label"), map, SLOT(slotRemoveObjectLabel())); } else { addAction(i18n("Attach Label"), map, SLOT(slotAddObjectLabel())); } } // Should show observing list if (showObsList) { if (data->observingList()->contains(obj)) addAction(i18n("Remove From Observing WishList"), data->observingList(), SLOT(slotRemoveObject())); else addAction(i18n("Add to Observing WishList"), data->observingList(), SLOT(slotAddObject())); } // Should we show trail actions TrailObject *t = dynamic_cast(obj); if (t) { if (t->hasTrail()) addAction(i18n("Remove Trail"), map, SLOT(slotRemovePlanetTrail())); else addAction(i18n("Add Trail"), map, SLOT(slotAddPlanetTrail())); } addAction(i18n("Simulate eyepiece view"), map, SLOT(slotEyepieceView())); addSeparator(); -#ifdef HAVE_XPLANET if (obj->isSolarSystem() && obj->type() != SkyObject::COMET) // FIXME: We now have asteroids -- so should this not be isMajorPlanet() || Pluto? { //QMenu *xplanetSubmenu = new QMenu(); //xplanetSubmenu->setTitle( i18n( "Print Xplanet view" ) ); addAction(i18n("View in XPlanet"), map, SLOT(slotXplanetToWindow())); //xplanetSubmenu->addAction( i18n( "To file..." ), map, SLOT( slotXplanetToFile() ) ); //addMenu( xplanetSubmenu ); } -#endif addSeparator(); addINDI(); addAction(i18n("View in What's Interesting"), this, SLOT(slotViewInWI())); } void KSPopupMenu::initFlagActions(SkyObject *obj) { KStars *ks = KStars::Instance(); QList flags = ks->data()->skyComposite()->flags()->getFlagsNearPix(obj, 5); if (flags.size() == 0) { // There is no flag around clicked SkyObject addAction(i18n("Add flag..."), ks->map(), SLOT(slotAddFlag())); } else if (flags.size() == 1) { // There is only one flag around clicked SkyObject addAction(i18n("Edit flag"), this, SLOT(slotEditFlag())); addAction(i18n("Delete flag"), this, SLOT(slotDeleteFlag())); m_CurrentFlagIdx = flags.first(); } else { // There are more than one flags around clicked SkyObject - we need to create submenus QMenu *editMenu = new QMenu(i18n("Edit flag..."), KStars::Instance()); QMenu *deleteMenu = new QMenu(i18n("Delete flag..."), KStars::Instance()); connect(editMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotEditFlag(QAction*))); connect(deleteMenu, SIGNAL(triggered(QAction*)), this, SLOT(slotDeleteFlag(QAction*))); if (m_EditActionMapping) { delete m_EditActionMapping; } if (m_DeleteActionMapping) { delete m_DeleteActionMapping; } m_EditActionMapping = new QHash; m_DeleteActionMapping = new QHash; foreach (int idx, flags) { QIcon flagIcon(QPixmap::fromImage(ks->data()->skyComposite()->flags()->image(idx))); QString flagLabel = ks->data()->skyComposite()->flags()->label(idx); if (flagLabel.size() > 35) { flagLabel = flagLabel.left(35); flagLabel.append("..."); } QAction *editAction = new QAction(flagIcon, flagLabel, ks); editAction->setIconVisibleInMenu(true); editMenu->addAction(editAction); m_EditActionMapping->insert(editAction, idx); QAction *deleteAction = new QAction(flagIcon, flagLabel, ks); deleteAction->setIconVisibleInMenu(true); deleteMenu->addAction(deleteAction); m_DeleteActionMapping->insert(deleteAction, idx); } addMenu(editMenu); addMenu(deleteMenu); } } void KSPopupMenu::addLinksToMenu(SkyObject *obj, bool showDSS) { KStars *ks = KStars::Instance(); QString sURL; QStringList::ConstIterator itList, itTitle, itListEnd; itList = obj->ImageList().constBegin(); itTitle = obj->ImageTitle().constBegin(); itListEnd = obj->ImageList().constEnd(); if (!obj->ImageList().isEmpty()) { QMenu *imageLinkSubMenu = new QMenu(); imageLinkSubMenu->setTitle(i18n("Image Resources")); for (; itList != itListEnd; ++itList) { QString t = QString(*itTitle); sURL = QString(*itList); imageLinkSubMenu->addAction(i18nc("Image/info menu item (should be translated)", t.toLocal8Bit()), ks->map(), SLOT(slotImage())); ++itTitle; } addMenu(imageLinkSubMenu); } if (showDSS) { addAction(i18nc("Sloan Digital Sky Survey", "Show SDSS Image"), ks->map(), SLOT(slotSDSS())); addAction(i18nc("Digitized Sky Survey", "Show DSS Image"), ks->map(), SLOT(slotDSS())); } if (showDSS) addSeparator(); itList = obj->InfoList().constBegin(); itTitle = obj->InfoTitle().constBegin(); itListEnd = obj->InfoList().constEnd(); if (!obj->InfoList().isEmpty()) { QMenu *infoLinkSubMenu = new QMenu(); infoLinkSubMenu->setTitle(i18n("Information Resources")); for (; itList != itListEnd; ++itList) { QString t = QString(*itTitle); sURL = QString(*itList); infoLinkSubMenu->addAction(i18nc("Image/info menu item (should be translated)", t.toLocal8Bit()), ks->map(), SLOT(slotInfo())); ++itTitle; } addMenu(infoLinkSubMenu); } } void KSPopupMenu::addINDI() { #ifdef HAVE_INDI if (INDIListener::Instance()->size() == 0) return; foreach (ISD::GDInterface *gd, INDIListener::Instance()->getDevices()) { INDI::BaseDevice *bd = gd->getBaseDevice(); if (bd == nullptr) continue; //if (bd->isConnected() == false) // continue; QMenu *menuDevice = nullptr; ISD::GDInterface *telescope = nullptr; foreach (INDI::Property *pp, gd->getProperties()) { if (pp->getType() != INDI_SWITCH || INDIListener::Instance()->isStandardProperty(pp->getName()) == false || QString(pp->getName()).startsWith("TELESCOPE_MOTION")) continue; QSignalMapper *sMapper = new QSignalMapper(this); ISwitchVectorProperty *svp = pp->getSwitch(); for (int i = 0; i < svp->nsp; i++) { if (menuDevice == nullptr) { menuDevice = new QMenu(gd->getDeviceName()); addMenu(menuDevice); } QAction *a = menuDevice->addAction(svp->sp[i].label); ISD::GDSetCommand *cmd = new ISD::GDSetCommand(INDI_SWITCH, pp->getName(), svp->sp[i].name, ISS_ON, this); sMapper->setMapping(a, cmd); connect(a, SIGNAL(triggered()), sMapper, SLOT(map())); if (!strcmp(svp->sp[i].name, "SLEW") || !strcmp(svp->sp[i].name, "SYNC") || !strcmp(svp->sp[i].name, "TRACK")) { telescope = INDIListener::Instance()->getDevice(gd->getDeviceName()); if (telescope) { QSignalMapper *scopeMapper = new QSignalMapper(this); scopeMapper->setMapping(a, INDI_SEND_COORDS); connect(a, SIGNAL(triggered()), scopeMapper, SLOT(map())); connect(scopeMapper, SIGNAL(mapped(int)), telescope, SLOT(runCommand(int))); } } } connect(sMapper, SIGNAL(mapped(QObject*)), gd, SLOT(setProperty(QObject*))); if (menuDevice != nullptr) menuDevice->addSeparator(); } if (telescope != nullptr && menuDevice != nullptr) { if (dynamic_cast(telescope)->canCustomPark()) { menuDevice->addSeparator(); QAction *a = menuDevice->addAction(i18n("Slew && Set As Parking Position")); QSignalMapper *scopeMapper = new QSignalMapper(this); scopeMapper->setMapping(a, INDI_CUSTOM_PARKING); connect(a, SIGNAL(triggered()), scopeMapper, SLOT(map())); connect(scopeMapper, SIGNAL(mapped(int)), telescope, SLOT(runCommand(int))); } menuDevice->addSeparator(); QAction *a = menuDevice->addAction(i18n("Center Crosshair")); QSignalMapper *scopeMapper = new QSignalMapper(this); scopeMapper->setMapping(a, INDI_ENGAGE_TRACKING); connect(a, SIGNAL(triggered()), scopeMapper, SLOT(map())); connect(scopeMapper, SIGNAL(mapped(int)), telescope, SLOT(runCommand(int))); } } #endif } void KSPopupMenu::addFancyLabel(const QString &name, int deltaFontSize) { if (name.isEmpty()) return; QLabel *label = new QLabel("" + name + "", this); label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); if (deltaFontSize != 0) { QFont font = label->font(); font.setPointSize(font.pointSize() + deltaFontSize); label->setFont(font); } QWidgetAction *act = new QWidgetAction(this); act->setDefaultWidget(label); addAction(act); } void KSPopupMenu::slotViewInWI() { if (!KStars::Instance()->map()->clickedObject()) return; if (!KStars::Instance()->isWIVisible()) KStars::Instance()->slotToggleWIView(); KStars::Instance()->wiView()->inspectSkyObject(KStars::Instance()->map()->clickedObject()); } diff --git a/kstars/kstars.h b/kstars/kstars.h index 8e890358b..bc9b3e7ad 100644 --- a/kstars/kstars.h +++ b/kstars/kstars.h @@ -1,837 +1,833 @@ /** ************************************************************************* kstars.h - K Desktop Planetarium ------------------- begin : Mon Feb 5 01:11:45 PST 2001 copyright : (C) 2001 by Jason Harris email : jharris@30doradus.org ***************************************************************************/ /** ************************************************************************* * * * 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. * * * ***************************************************************************/ #pragma once #include "config-kstars.h" #include #include #include #include #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) #include #else #include #endif #ifdef HAVE_CFITSIO #include #endif // forward declaration is enough. We only need pointers class QActionGroup; class QDockWidget; class QPalette; class KActionMenu; class KStarsData; class SkyPoint; class SkyMap; class GeoLocation; class FindDialog; class TimeStepBox; class ImageExporter; class AltVsTime; class WUTDialog; class WIView; class WILPSettings; class WIEquipSettings; class ObsConditions; class AstroCalc; class SkyCalendar; class ScriptBuilder; class PlanetViewer; //class JMoonTool; class MoonPhaseTool; class FlagManager; class Execute; class ExportImageDialog; class PrintingWizard; class EkosManager; class HorizonManager; class EyepieceField; class AddDeepSkyObject; class OpsCatalog; class OpsGuides; class OpsSolarSystem; class OpsSatellites; class OpsSupernovae; class OpsColors; class OpsAdvanced; class OpsINDI; class OpsEkos; class OpsFITS; -#ifdef HAVE_XPLANET class OpsXplanet; -#endif #ifdef HAVE_CFITSIO class FITSViewer; #endif /** *@class KStars *@short This is the main window for KStars. *In addition to the GUI elements, the class contains the program clock, KStarsData, and SkyMap objects. It also contains functions for the \ref DBusInterface D-Bus interface. KStars is now a singleton class. Use KStars::createInstance() to create an instance and KStars::Instance() to get a pointer to the instance *@author Jason Harris, Jasem Mutlaq *@version 1.1 */ class KStars : public KXmlGuiWindow { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.kstars") 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. * * @todo Refer to documentation on date format. */ explicit KStars(bool doSplash, bool startClockRunning = true, const QString &startDateString = QString()); public: /** * @short Create an instance of this class. Destroy any previous instance * @param doSplash * @param clockrunning * @param startDateString * @note See KStars::KStars for details on parameters * @return a pointer to the instance */ static KStars *createInstance(bool doSplash, bool clockrunning = true, const QString &startDateString = QString()); /** @return a pointer to the instance of this class */ inline static KStars *Instance() { return pinstance; } /** Destructor. */ ~KStars() override; /** Syncs config file. Deletes objects. */ void releaseResources(); /** @return pointer to KStarsData object which contains application data. */ inline KStarsData *data() const { return m_KStarsData; } /** @return pointer to SkyMap object which is the sky display widget. */ inline SkyMap *map() const { return m_SkyMap; } inline FlagManager *flagManager() const { return m_FlagManager; } inline PrintingWizard *printingWizard() const { return m_PrintingWizard; } #ifdef HAVE_CFITSIO FITSViewer *genericFITSViewer(); QList &getFITSViewersList() { return m_FITSViewers; } #endif #ifdef HAVE_INDI EkosManager *ekosManager(); #endif /** Add an item to the color-scheme action manu * @param name The name to use in the menu * @param actionName The internal name for the action (derived from filename) */ void addColorMenuItem(const QString &name, const QString &actionName); /** Remove an item from the color-scheme action manu * @param actionName The internal name of the action (derived from filename) */ void removeColorMenuItem(const QString &actionName); /** @short Apply config options throughout the program. * In most cases, options are set in the "Options" object directly, * but for some things we have to manually react to config changes. * @param doApplyFocus If true, then focus posiiton will be set * from config file */ void applyConfig(bool doApplyFocus = true); void showImgExportDialog(); void syncFOVActions(); void hideAllFovExceptFirst(); void selectNextFov(); void selectPreviousFov(); void showWISettingsUI(); void showWI(ObsConditions *obs); /** Load HIPS information and repopulate menu. */ void repopulateHIPS(); WIEquipSettings *getWIEquipSettings() { return m_WIEquipmentSettings; } public Q_SLOTS: /** @defgroup DBusInterface DBus Interface KStars provides powerful scripting functionality via DBus. The most common DBus functions can be constructed and executed within the ScriptBuilder tool. Any 3rd party language or tool with support for DBus can access several interfaces provided by KStars:
  • KStars: Provides functions to manipulate the skymap including zoom, pan, and motion to selected objects. Add and remove object trails and labels. Wait for user input before running further actions.
  • SimClock: Provides functions to start and stop time, set a different date and time, and to set the clock scale.
  • Ekos: Provides functions to start and stop Ekos Manager, set Ekos connection mode, and access to Ekos modules:
    • Capture: Provides functions to capture images, load sequence queues, control filter wheel, and obtain information on job progress.
    • Focus: Provides functions to focus control in manual and automated mode. Start and stop focusing procedures and set autofocus options.
    • Guide: Provides functions to start and stop calibration and autoguiding procedures. Set calibration and autoguide options.
    • Align: Provides functions to solve images use online or offline astrometry.net solver.
*/ /*@{*/ /** DBUS interface function. * Set focus to given Ra/Dec coordinates * @param ra the Right Ascension coordinate for the focus (in Hours) * @param dec the Declination coordinate for the focus (in Degrees) */ Q_SCRIPTABLE Q_NOREPLY void setRaDec(double ra, double dec); /** DBUS interface function. * Set focus to given Alt/Az coordinates. * @param alt the Altitude coordinate for the focus (in Degrees) * @param az the Azimuth coordinate for the focus (in Degrees) */ Q_SCRIPTABLE Q_NOREPLY void setAltAz(double alt, double az); /** DBUS interface function. * Point in the direction described by the string argument. * @param direction either an object name, a compass direction (e.g., "north"), or "zenith" */ Q_SCRIPTABLE Q_NOREPLY void lookTowards(const QString &direction); /** DBUS interface function. * Add a name label to the named object * @param name the name of the object to which the label will be attached */ Q_SCRIPTABLE Q_NOREPLY void addLabel(const QString &name); /** DBUS interface function. * Remove a name label from the named object * @param name the name of the object from which the label will be removed */ Q_SCRIPTABLE Q_NOREPLY void removeLabel(const QString &name); /** DBUS interface function. * Add a trail to the named solar system body * @param name the name of the body to which the trail will be attached */ Q_SCRIPTABLE Q_NOREPLY void addTrail(const QString &name); /** DBUS interface function. * Remove a trail from the named solar system body * @param name the name of the object from which the trail will be removed */ Q_SCRIPTABLE Q_NOREPLY void removeTrail(const QString &name); /** DBUS interface function. Zoom in one step. */ Q_SCRIPTABLE Q_NOREPLY void zoomIn(); /** DBUS interface function. Zoom out one step. */ Q_SCRIPTABLE Q_NOREPLY void zoomOut(); /** DBUS interface function. reset to the default zoom level. */ Q_SCRIPTABLE Q_NOREPLY void defaultZoom(); /** DBUS interface function. Set zoom level to specified value. * @param z the zoom level. Units are pixels per radian. */ Q_SCRIPTABLE Q_NOREPLY void zoom(double z); /** DBUS interface function. Set local time and date. * @param yr year of date * @param mth month of date * @param day day of date * @param hr hour of time * @param min minute of time * @param sec second of time */ Q_SCRIPTABLE Q_NOREPLY void setLocalTime(int yr, int mth, int day, int hr, int min, int sec); /** DBUS interface function. Set local time and date to present values acc. system clock * @note Just a proxy for slotSetTimeToNow(), but it is better to * keep the DBus interface separate from the internal methods. */ Q_SCRIPTABLE Q_NOREPLY void setTimeToNow(); /** DBUS interface function. Delay further execution of DBUS commands. * @param t number of seconds to delay */ Q_SCRIPTABLE Q_NOREPLY void waitFor(double t); /** DBUS interface function. Pause further DBUS execution until a key is pressed. * @param k the key which will resume DBUS execution */ Q_SCRIPTABLE Q_NOREPLY void waitForKey(const QString &k); /** DBUS interface function. Toggle tracking. * @param track engage tracking if true; else disengage tracking */ Q_SCRIPTABLE Q_NOREPLY void setTracking(bool track); /** DBUS interface function. modify a view option. * @param option the name of the option to be modified * @param value the option's new value */ Q_SCRIPTABLE Q_NOREPLY void changeViewOption(const QString &option, const QString &value); /** DBUS interface function. * @param name the name of the option to query * @return the current value of the named option */ Q_SCRIPTABLE QString getOption(const QString &name); /** DBUS interface function. Read config file. * This function is useful for restoring the user settings from the config file, * after having modified the settings in memory. * @sa writeConfig() */ Q_SCRIPTABLE Q_NOREPLY void readConfig(); /** DBUS interface function. Write current settings to config file. * This function is useful for storing user settings before modifying them with a DBUS * script. The original settings can be restored with readConfig(). * @sa readConfig() */ Q_SCRIPTABLE Q_NOREPLY void writeConfig(); /** DBUS interface function. Show text message in a popup window. * @note Not Yet Implemented * @param x x-coordinate for message window * @param y y-coordinate for message window * @param message the text to display in the message window */ Q_SCRIPTABLE Q_NOREPLY void popupMessage(int x, int y, const QString &message); /** DBUS interface function. Draw a line on the sky map. * @note Not Yet Implemented * @param x1 starting x-coordinate of line * @param y1 starting y-coordinate of line * @param x2 ending x-coordinate of line * @param y2 ending y-coordinate of line * @param speed speed at which line should appear from start to end points (in pixels per second) */ Q_SCRIPTABLE Q_NOREPLY void drawLine(int x1, int y1, int x2, int y2, int speed); /** DBUS interface function. Set the geographic location. * @param city the city name of the location * @param province the province name of the location * @param country the country name of the location * @return True if geographic location is found and set, false otherwise. */ Q_SCRIPTABLE bool setGeoLocation(const QString &city, const QString &province, const QString &country); /** DBUS interface function. Modify a color. * @param colorName the name of the color to be modified (e.g., "SkyColor") * @param value the new color to use */ Q_SCRIPTABLE Q_NOREPLY void setColor(const QString &colorName, const QString &value); /** DBUS interface function. Load a color scheme. * @param name the name of the color scheme to load (e.g., "Moonless Night") */ Q_SCRIPTABLE Q_NOREPLY void loadColorScheme(const QString &name); /** DBUS interface function. Export the sky image to a file. * @param filename the filename for the exported image * @param width the width for the exported image. Map's width will be used if nothing or an invalid value is supplied. * @param height the height for the exported image. Map's height will be used if nothing or an invalid value is supplied. * @param includeLegend should we include a legend? */ Q_SCRIPTABLE Q_NOREPLY void exportImage(const QString &filename, int width = -1, int height = -1, bool includeLegend = false); /** DBUS interface function. Return a URL to retrieve Digitized Sky Survey image. * @param objectName name of the object. * @note If the object is note found, the string "ERROR" is returned. */ Q_SCRIPTABLE QString getDSSURL(const QString &objectName); /** DBUS interface function. Return a URL to retrieve Digitized Sky Survey image. * @param RA_J2000 J2000.0 RA * @param Dec_J2000 J2000.0 Declination * @param width width of the image, in arcminutes (default = 15) * @param height height of the image, in arcminutes (default = 15) */ Q_SCRIPTABLE QString getDSSURL(double RA_J2000, double Dec_J2000, float width = 15, float height = 15); /** DBUS interface function. Return XML containing information about a sky object * @param objectName name of the object. * @note If the object was not found, the XML is empty. */ Q_SCRIPTABLE QString getObjectDataXML(const QString &objectName); /** DBUS interface function. Return XML containing position info about a sky object * @param objectName name of the object. * @note If the object was not found, the XML is empty. */ Q_SCRIPTABLE QString getObjectPositionInfo(const QString &objectName); /** DBUS interface function. Render eyepiece view and save it in the file(s) specified * @note See EyepieceField::renderEyepieceView() for more info. This is a DBus proxy that calls that method, and then writes the resulting image(s) to file(s). * @note Important: If imagePath is empty, but overlay is true, or destPathImage is supplied, this method will make a blocking DSS download. */ Q_SCRIPTABLE Q_NOREPLY void renderEyepieceView(const QString &objectName, const QString &destPathChart, const double fovWidth = -1.0, const double fovHeight = -1.0, const double rotation = 0.0, const double scale = 1.0, const bool flip = false, const bool invert = false, QString imagePath = QString(), const QString &destPathImage = QString(), const bool overlay = false, const bool invertColors = false); /** DBUS interface function. Set the approx field-of-view * @param FOV_Degrees field of view in degrees */ Q_SCRIPTABLE Q_NOREPLY void setApproxFOV(double FOV_Degrees); /** DBUS interface function. Get the dimensions of the Sky Map. * @return a string containing widthxheight in pixels. */ Q_SCRIPTABLE QString getSkyMapDimensions(); /** DBUS interface function. Return a newline-separated list of objects in the observing wishlist. * @note Unfortunately, unnamed objects are troublesome. Hopefully, we don't have them on the observing list. */ Q_SCRIPTABLE QString getObservingWishListObjectNames(); /** DBUS interface function. Return a newline-separated list of objects in the observing session plan. * @note Unfortunately, unnamed objects are troublesome. Hopefully, we don't have them on the observing list. */ Q_SCRIPTABLE QString getObservingSessionPlanObjectNames(); /** DBUS interface function. Print the sky image. * @param usePrintDialog if true, the KDE print dialog will be shown; otherwise, default parameters will be used * @param useChartColors if true, the "Star Chart" color scheme will be used for the printout, which will save ink. */ Q_SCRIPTABLE Q_NOREPLY void printImage(bool usePrintDialog, bool useChartColors); /** DBUS interface function. Open FITS image. * @param imageURL URL of FITS image to load. For a local file the prefix must be file:// For example * if the file is located at /home/john/m42.fits then the full URL is file:///home/john/m42.fits * @return True if successful, false otherwise. */ Q_SCRIPTABLE bool openFITS(const QString &imageURL); // for DBus bool openFITS(const QUrl &imageUrl); // for C++ code /** @}*/ /** * Update time-dependent data and (possibly) repaint the sky map. * @param automaticDSTchange change DST status automatically? */ void updateTime(const bool automaticDSTchange = true); /** action slot: sync kstars clock to system time */ void slotSetTimeToNow(); /** Apply new settings and redraw skymap */ void slotApplyConfigChanges(); /** Apply new settings for WI */ void slotApplyWIConfigChanges(); /** Called when zoom level is changed. Enables/disables zoom * actions and updates status bar. */ void slotZoomChanged(); /** action slot: Allow user to specify a field-of-view angle for the display window in degrees, * and set the zoom level accordingly. */ void slotSetZoom(); /** action slot: Toggle whether kstars is tracking current position */ void slotTrack(); /** action slot: open dialog for selecting a new geographic location */ void slotGeoLocator(); /** * @brief slotSetTelescopeEnabled call when telescope comes online or goes offline. * @param enable True if telescope is online and connected, false otherwise. */ void slotSetTelescopeEnabled(bool enable); /** * @brief slotSetDomeEnabled call when dome comes online or goes offline. * @param enable True if dome is online and connected, false otherwise. */ void slotSetDomeEnabled(bool enable); /** Delete FindDialog because ObjNames list has changed in KStarsData due to * reloading star data. So list in FindDialog must be new filled with current data. */ void clearCachedFindDialog(); /** Remove all trails which may have been added to solar system bodies */ void slotClearAllTrails(); /** Display position in the status bar. */ void slotShowPositionBar(SkyPoint *); /** action slot: open Flag Manager */ void slotFlagManager(); /** Show the eyepiece view tool */ void slotEyepieceView(SkyPoint *sp, const QString &imagePath = QString()); /** Show the add deep-sky object dialog */ void slotAddDeepSkyObject(); /** action slot: open KStars setup wizard */ void slotWizard(); void updateLocationFromWizard(const GeoLocation& geo); WIView *wiView() { return m_WIView; } bool isWIVisible() { if (!m_WIView) return false; if (!m_wiDock) return false; return m_wiDock->isVisible(); } //FIXME Port to QML2 //#if 0 /** action slot: open What's Interesting settings window */ void slotWISettings(); /** action slot: toggle What's Interesting window */ void slotToggleWIView(); //#endif private slots: /** action slot: open a dialog for setting the time and date */ void slotSetTime(); /** 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(); /** action slot: open dialog for finding a named object */ void slotFind(); /** action slot: open KNewStuff window to download extra data. */ void slotDownload(); /** action slot: open KStars calculator to compute astronomical ephemeris */ void slotCalculator(); /** action slot: open Elevation vs. Time tool */ void slotAVT(); /** action slot: open What's up tonight dialog */ void slotWUT(); /** action slot: open Sky Calendar tool */ void slotCalendar(); /** action slot: open the glossary */ void slotGlossary(); /** action slot: open ScriptBuilder dialog */ void slotScriptBuilder(); /** action slot: open Solar system viewer */ void slotSolarSystem(); /** action slot: open Jupiter Moons tool */ // void slotJMoonTool(); /** action slot: open Moon Phase Calendar tool */ void slotMoonPhaseTool(); /** action slot: open Telescope wizard */ void slotTelescopeWizard(); /** action slot: open INDI driver panel */ void slotINDIDriver(); /** action slot: open INDI control panel */ void slotINDIPanel(); /** action slot: open Ekos panel */ void slotEkos(); /** action slot: Track with the telescope (INDI) */ void slotINDITelescopeTrack(); /** * Action slot: Slew with the telescope (INDI) * * @param focused_object Slew to the focused object or the mouse pointer if false. * */ void slotINDITelescopeSlew(bool focused_object = true); void slotINDITelescopeSlewMousePointer(); /** * Action slot: Sync the telescope (INDI) * * @param focused_object Sync the position of the focused object or the mouse pointer if false. * */ void slotINDITelescopeSync(bool focused_object = true); void slotINDITelescopeSyncMousePointer(); /** action slot: Abort any telescope motion (INDI) */ void slotINDITelescopeAbort(); /** action slot: Park the telescope (INDI) */ void slotINDITelescopePark(); /** action slot: Unpark the telescope (INDI) */ void slotINDITelescopeUnpark(); /** action slot: Park the dome (INDI) */ void slotINDIDomePark(); /** action slot: UnPark the dome (INDI) */ void slotINDIDomeUnpark(); /** action slot: open dialog for setting the view options */ void slotViewOps(); /** finish setting up after the kstarsData has finished */ void datainitFinished(); /** Open FITS image. */ void slotOpenFITS(); /** Action slot to save the sky image to a file.*/ void slotExportImage(); /** Action slot to select a DBUS script and run it.*/ void slotRunScript(); /** Action slot to print skymap. */ void slotPrint(); /** Action slot to start Printing Wizard. */ void slotPrintingWizard(); /** Action slot to show tip-of-the-day window. */ void slotTipOfDay(); /** Action slot to set focus coordinates manually (opens FocusDialog). */ void slotManualFocus(); /** Meta-slot to point the focus at special points (zenith, N, S, E, W). * Uses the name of the Action which sent the Signal to identify the * desired direction. */ void slotPointFocus(); /** Meta-slot to set the color scheme according to the name of the * Action which sent the activating signal. */ void slotColorScheme(); /** * @brief slotThemeChanged save theme name in options */ void slotThemeChanged(); /** Select the Target symbol (a.k.a. field-of-view indicator) */ void slotTargetSymbol(bool flag); /** Select the HIPS Source catalog. */ void slotHIPSSource(); /** Invoke the Field-of-View symbol editor window */ void slotFOVEdit(); /** Toggle between Equatorial and Ecliptic coordinte systems */ void slotCoordSys(); /** Set the map projection according to the menu selection */ void slotMapProjection(); /** Toggle display of the observing list tool*/ void slotObsList(); /** Meta-slot to handle display toggles for all of the viewtoolbar buttons. * uses the name of the sender to identify the item to change. */ void slotViewToolBar(); /** Meta-slot to handle display toggles for all of the INDItoolbar buttons. * uses the name of the sender to identify the item to change. */ void slotINDIToolBar(); /** Meta-slot to handle toggling display of GUI elements (toolbars and infoboxes) * uses name of the sender action to identify the widget to hide/show. */ void slotShowGUIItem(bool); /** Toggle to and from full screen mode */ void slotFullScreen(); /** Save data to config file before exiting.*/ void slotAboutToQuit(); void slotEquipmentWriter(); void slotObserverManager(); void slotHorizonManager(); void slotExecute(); void slotPolarisHourAngle(); /** Update comets orbital elements*/ void slotUpdateComets(); /** Update asteroids orbital elements*/ void slotUpdateAsteroids(); /** Update list of recent supernovae*/ void slotUpdateSupernovae(); /** Update satellites orbital elements*/ void slotUpdateSatellites(); /** Configure Notifications */ void slotConfigureNotifications(); private: /** Load FOV information and repopulate menu. */ void repopulateFOV(); /** * @brief populateThemes Populate application themes */ void populateThemes(); /** Initialize Menu bar, toolbars and all Actions. */ void initActions(); /** Initialize Status bar. */ void initStatusBar(); /** Initialize focus position */ void initFocus(); /** Build the KStars main window */ void buildGUI(); void closeEvent(QCloseEvent *event) override; public: /** Check if the KStars main window is shown */ bool isGUIReady() { return m_SkyMap != nullptr; } /// Set to true when the application is being closed static bool Closing; private: /// Pointer to an instance of KStars static KStars *pinstance; KActionMenu *colorActionMenu { nullptr }; KActionMenu *fovActionMenu { nullptr }; KActionMenu *hipsActionMenu { nullptr }; KStarsData *m_KStarsData { nullptr }; SkyMap *m_SkyMap { nullptr }; // Widgets TimeStepBox *m_TimeStepBox { nullptr }; // Dialogs & Tools // File Menu ExportImageDialog *m_ExportImageDialog { nullptr }; PrintingWizard *m_PrintingWizard { nullptr }; // Pointing Menu FindDialog *m_FindDialog { nullptr }; // Tool Menu AstroCalc *m_AstroCalc { nullptr }; AltVsTime *m_AltVsTime { nullptr }; SkyCalendar *m_SkyCalendar { nullptr }; ScriptBuilder *m_ScriptBuilder { nullptr }; PlanetViewer *m_PlanetViewer { nullptr }; WUTDialog *m_WUTDialog { nullptr }; // JMoonTool *m_JMoonTool { nullptr }; FlagManager *m_FlagManager { nullptr }; HorizonManager *m_HorizonManager { nullptr }; EyepieceField *m_EyepieceView { nullptr }; #ifdef HAVE_CFITSIO QPointer m_GenericFITSViewer; QList m_FITSViewers; #endif #ifdef HAVE_INDI QPointer m_EkosManager; #endif AddDeepSkyObject *m_addDSODialog { nullptr }; // FIXME Port to QML2 //#if 0 WIView *m_WIView { nullptr }; WILPSettings *m_WISettings { nullptr }; WIEquipSettings *m_WIEquipmentSettings { nullptr }; ObsConditions *m_ObsConditions { nullptr }; QDockWidget *m_wiDock { nullptr }; //#endif QActionGroup *projectionGroup { nullptr }; QActionGroup *cschemeGroup { nullptr }; QActionGroup *hipsGroup { nullptr }; QActionGroup *telescopeGroup { nullptr }; QActionGroup *domeGroup { nullptr }; bool DialogIsObsolete { false }; bool StartClockRunning { false }; QString StartDateString; QLabel AltAzField, RADecField, J2000RADecField; //QPalette OriginalPalette, DarkPalette; OpsCatalog *opcatalog { nullptr }; OpsGuides *opguides { nullptr }; OpsSolarSystem *opsolsys { nullptr }; OpsSatellites *opssatellites { nullptr }; OpsSupernovae *opssupernovae { nullptr }; OpsColors *opcolors { nullptr }; OpsAdvanced *opadvanced { nullptr }; OpsINDI *opsindi { nullptr }; OpsEkos *opsekos { nullptr }; OpsFITS *opsfits { nullptr }; -#ifdef HAVE_XPLANET OpsXplanet *opsxplanet { nullptr }; -#endif }; diff --git a/kstars/kstarsactions.cpp b/kstars/kstarsactions.cpp index 1e64bff2e..3b14eb333 100644 --- a/kstars/kstarsactions.cpp +++ b/kstars/kstarsactions.cpp @@ -1,1926 +1,1922 @@ /*************************************************************************** kstarsactions.cpp - K Desktop Planetarium ------------------- begin : Mon Feb 25 2002 copyright : (C) 2002 by Jason Harris email : jharris@30doradus.org ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ // This file contains function definitions for Actions declared in kstars.h #include "kstars.h" #include "imageexporter.h" #include "kstarsdata.h" #include "kswizard.h" #include "Options.h" #include "skymap.h" #include "dialogs/exportimagedialog.h" #include "dialogs/finddialog.h" #include "dialogs/focusdialog.h" #include "dialogs/fovdialog.h" #include "dialogs/locationdialog.h" #include "dialogs/timedialog.h" #include "oal/execute.h" #include "oal/equipmentwriter.h" #include "oal/observeradd.h" #include "options/opsadvanced.h" #include "options/opscatalog.h" #include "options/opscolors.h" #include "options/opsguides.h" #include "options/opssatellites.h" #include "options/opssolarsystem.h" #include "options/opssupernovae.h" #include "printing/printingwizard.h" #include "projections/projector.h" #include "skycomponents/asteroidscomponent.h" #include "skycomponents/cometscomponent.h" #include "skycomponents/satellitescomponent.h" #include "skycomponents/skymapcomposite.h" #include "skycomponents/solarsystemcomposite.h" #include "skycomponents/supernovaecomponent.h" #include "tools/adddeepskyobject.h" #include "tools/altvstime.h" #include "tools/astrocalc.h" #include "tools/eyepiecefield.h" #include "tools/flagmanager.h" #include "tools/horizonmanager.h" #include "tools/observinglist.h" #include "tools/planetviewer.h" #include "tools/scriptbuilder.h" #include "tools/skycalendar.h" #include "tools/wutdialog.h" #include "tools/polarishourangle.h" #include "tools/whatsinteresting/wiequipsettings.h" #include "tools/whatsinteresting/wilpsettings.h" #include "tools/whatsinteresting/wiview.h" #include "hips/hipsmanager.h" #ifdef HAVE_INDI #include #include "indi/telescopewizardprocess.h" #include "indi/opsindi.h" #include "indi/drivermanager.h" #include "indi/guimanager.h" #include "indi/indilistener.h" #endif #ifdef HAVE_CFITSIO #include "fitsviewer/fitsviewer.h" #include "fitsviewer/opsfits.h" #ifdef HAVE_INDI #include "ekos/ekosmanager.h" #include "ekos/opsekos.h" #endif #endif -#ifdef HAVE_XPLANET #include "xplanet/opsxplanet.h" -#endif #ifdef HAVE_NOTIFYCONFIG #include #endif #include #include #include #include #include #include #include #ifdef _WIN32 #include #undef interface #endif #include #include "kstars_debug.h" /** ViewToolBar Action. All of the viewToolBar buttons are connected to this slot. **/ void KStars::slotViewToolBar() { KToggleAction *a = (KToggleAction *)sender(); KConfigDialog *kcd = KConfigDialog::exists("settings"); if (a == actionCollection()->action("show_stars")) { Options::setShowStars(a->isChecked()); if (kcd) { opcatalog->kcfg_ShowStars->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_deepsky")) { Options::setShowDeepSky(a->isChecked()); if (kcd) { opcatalog->kcfg_ShowDeepSky->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_planets")) { Options::setShowSolarSystem(a->isChecked()); if (kcd) { opsolsys->kcfg_ShowSolarSystem->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_clines")) { Options::setShowCLines(a->isChecked()); if (kcd) { opguides->kcfg_ShowCLines->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_cnames")) { Options::setShowCNames(a->isChecked()); if (kcd) { opguides->kcfg_ShowCNames->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_cbounds")) { Options::setShowCBounds(a->isChecked()); if (kcd) { opguides->kcfg_ShowCBounds->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_constellationart")) { Options::setShowConstellationArt(a->isChecked()); if (kcd) { opguides->kcfg_ShowConstellationArt->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_mw")) { Options::setShowMilkyWay(a->isChecked()); if (kcd) { opguides->kcfg_ShowMilkyWay->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_equatorial_grid")) { // if autoSelectGrid is selected and the user clicked the // show_equatorial_grid button, he probably wants us to disable // the autoSelectGrid and display the equatorial grid. Options::setAutoSelectGrid(false); Options::setShowEquatorialGrid(a->isChecked()); if (kcd) { opguides->kcfg_ShowEquatorialGrid->setChecked(a->isChecked()); opguides->kcfg_AutoSelectGrid->setChecked(false); } } else if (a == actionCollection()->action("show_horizontal_grid")) { Options::setAutoSelectGrid(false); Options::setShowHorizontalGrid(a->isChecked()); if (kcd) { opguides->kcfg_ShowHorizontalGrid->setChecked(a->isChecked()); opguides->kcfg_AutoSelectGrid->setChecked(false); } } else if (a == actionCollection()->action("show_horizon")) { Options::setShowGround(a->isChecked()); if (!a->isChecked() && Options::useRefraction()) { QString caption = i18n("Refraction effects disabled"); QString message = i18n("When the horizon is switched off, refraction effects are temporarily disabled."); KMessageBox::information(this, message, caption, "dag_refract_hide_ground"); } if (kcd) { opguides->kcfg_ShowGround->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_flags")) { Options::setShowFlags(a->isChecked()); if (kcd) { opguides->kcfg_ShowFlags->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_satellites")) { Options::setShowSatellites(a->isChecked()); if (kcd) { opssatellites->kcfg_ShowSatellites->setChecked(a->isChecked()); } } else if (a == actionCollection()->action("show_supernovae")) { Options::setShowSupernovae(a->isChecked()); if (kcd) { opssupernovae->kcfg_ShowSupernovae->setChecked(a->isChecked()); } } // update time for all objects because they might be not initialized // it's needed when using horizontal coordinates data()->setFullTimeUpdate(); updateTime(); map()->forceUpdate(); } void KStars::slotINDIToolBar() { #ifdef HAVE_INDI KToggleAction *a = (KToggleAction *)sender(); if (a == actionCollection()->action("show_control_panel")) { if (a->isChecked()) { GUIManager::Instance()->raise(); GUIManager::Instance()->activateWindow(); GUIManager::Instance()->showNormal(); } else GUIManager::Instance()->hide(); } else if (a == actionCollection()->action("show_ekos")) { if (a->isChecked()) { ekosManager()->raise(); ekosManager()->activateWindow(); ekosManager()->showNormal(); } else ekosManager()->hide(); } else if (a == actionCollection()->action("lock_telescope")) { if (INDIListener::Instance()->size() == 0) { KMessageBox::sorry(0, i18n("KStars did not find any active telescopes.")); return; } ISD::GDInterface *oneScope = nullptr; foreach (ISD::GDInterface *gd, INDIListener::Instance()->getDevices()) { INDI::BaseDevice *bd = gd->getBaseDevice(); if (gd->getType() != KSTARS_TELESCOPE) continue; if (bd == nullptr) continue; if (bd->isConnected() == false) { KMessageBox::error( 0, i18n("Telescope %1 is offline. Please connect and retry again.", gd->getDeviceName())); return; } oneScope = gd; break; } if (oneScope == nullptr) { KMessageBox::sorry(0, i18n("KStars did not find any active telescopes.")); return; } if (a->isChecked()) oneScope->runCommand(INDI_CENTER_LOCK); else oneScope->runCommand(INDI_CENTER_UNLOCK); } else if (a == actionCollection()->action("show_fits_viewer")) { if (m_FITSViewers.isEmpty()) { a->setEnabled(false); return; } if (a->isChecked()) { foreach (FITSViewer *view, m_FITSViewers) { if (view->getTabs().empty() == false) { view->raise(); view->activateWindow(); view->showNormal(); } } } else { foreach (FITSViewer *view, m_FITSViewers) { view->hide(); } } } else if (a == actionCollection()->action("show_mount_box")) { ekosManager()->mountModule()->toggleMountToolBox(); } else if (a == actionCollection()->action("show_sensor_fov")) { Options::setShowSensorFOV(a->isChecked()); } #endif } void KStars::slotSetTelescopeEnabled(bool enable) { telescopeGroup->setEnabled(enable); if (enable == false) { for(QAction *a : telescopeGroup->actions()) { a->setChecked(false); } } } void KStars::slotSetDomeEnabled(bool enable) { domeGroup->setEnabled(enable); if (enable == false) { for(QAction *a : domeGroup->actions()) { a->setChecked(false); } } } /** Major Dialog Window Actions **/ void KStars::slotCalculator() { if (!m_AstroCalc) m_AstroCalc = new AstroCalc(this); m_AstroCalc->show(); } void KStars::slotWizard() { QPointer wizard = new KSWizard(this); if (wizard->exec() == QDialog::Accepted) { Options::setRunStartupWizard(false); //don't run on startup next time updateLocationFromWizard(*(wizard->geo())); } delete wizard; } void KStars::updateLocationFromWizard(const GeoLocation& geo) { data()->setLocation(geo); // adjust local time to keep UT the same. // create new LT without DST offset KStarsDateTime ltime = data()->geo()->UTtoLT(data()->ut()); // reset timezonerule to compute next dst change data()->geo()->tzrule()->reset_with_ltime(ltime, data()->geo()->TZ0(), data()->isTimeRunningForward()); // reset next dst change time data()->setNextDSTChange(data()->geo()->tzrule()->nextDSTChange()); // reset local sideral time data()->syncLST(); // Make sure Numbers, Moon, planets, and sky objects are updated immediately data()->setFullTimeUpdate(); // If the sky is in Horizontal mode and not tracking, reset focus such that // Alt/Az remain constant. if (!Options::isTracking() && Options::useAltAz()) { map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat()); } // recalculate new times and objects data()->setSnapNextFocus(); updateTime(); } void KStars::slotDownload() { // 2017-07-04: Explicitly load kstars.knsrc from resources file QPointer dlg(new KNS3::DownloadDialog(":/kconfig/kstars.knsrc", this)); dlg->exec(); // Get the list of all the installed entries. KNS3::Entry::List installed_entries; KNS3::Entry::List changed_entries; if (dlg) { installed_entries = dlg->installedEntries(); changed_entries = dlg->changedEntries(); } delete dlg; foreach (const KNS3::Entry &entry, installed_entries) { foreach (const QString &name, entry.installedFiles()) { if (name.endsWith(QLatin1String(".cat"))) { data()->catalogdb()->AddCatalogContents(name); // To start displaying the custom catalog, add it to SkyMapComposite QString catalogName = data()->catalogdb()->GetCatalogName(name); Options::setShowCatalogNames(Options::showCatalogNames() << catalogName); Options::setCatalogFile(Options::catalogFile() << name); Options::setShowCatalog(Options::showCatalog() << 1); } } KStars::Instance()->data()->skyComposite()->reloadDeepSky(); // update time for all objects because they might be not initialized // it's needed when using horizontal coordinates KStars::Instance()->data()->setFullTimeUpdate(); KStars::Instance()->updateTime(); KStars::Instance()->map()->forceUpdate(); } foreach (const KNS3::Entry &entry, changed_entries) { foreach (const QString &name, entry.uninstalledFiles()) { if (name.endsWith(QLatin1String(".cat"))) { data()->catalogdb()->RemoveCatalog(name); // To start displaying the custom catalog, add it to SkyMapComposite QStringList catFile = Options::catalogFile(); catFile.removeOne(name); Options::setCatalogFile(catFile); } } } } void KStars::slotAVT() { if (!m_AltVsTime) m_AltVsTime = new AltVsTime(this); m_AltVsTime->show(); } void KStars::slotWUT() { if (!m_WUTDialog) m_WUTDialog = new WUTDialog(this); m_WUTDialog->show(); } //FIXME Port to QML2 //#if 0 void KStars::slotWISettings() { if (!m_WIView) slotToggleWIView(); if (m_WIView && !m_wiDock->isVisible()) slotToggleWIView(); if (KConfigDialog::showDialog("wisettings")) { m_WIEquipmentSettings->populateScopeListWidget(); return; } KConfigDialog *dialog = new KConfigDialog(this, "wisettings", Options::self()); connect(dialog, SIGNAL(settingsChanged(QString)), this, SLOT(slotApplyWIConfigChanges())); m_WISettings = new WILPSettings(this); m_WIEquipmentSettings = new WIEquipSettings(); dialog->addPage(m_WISettings, i18n("Light Pollution Settings")); dialog->addPage(m_WIEquipmentSettings, i18n("Equipment Settings - Equipment Type and Parameters")); dialog->exec(); if (m_WIEquipmentSettings) m_WIEquipmentSettings->setAperture(); //Something isn't working with this! } void KStars::slotToggleWIView() { if (KStars::Closing) return; if (!m_WIView) { m_WIView = new WIView(nullptr); m_wiDock = new QDockWidget(this); m_wiDock->setStyleSheet("QDockWidget::title{background-color:black;}"); m_wiDock->setObjectName("What's Interesting"); m_wiDock->setAllowedAreas(Qt::RightDockWidgetArea); QWidget *container = QWidget::createWindowContainer(m_WIView->getWIBaseView()); m_wiDock->setWidget(container); m_wiDock->setMinimumWidth(400); addDockWidget(Qt::RightDockWidgetArea, m_wiDock); connect(m_wiDock, SIGNAL(visibilityChanged(bool)), actionCollection()->action("show_whatsinteresting"), SLOT(setChecked(bool))); m_wiDock->setVisible(true); } else { m_wiDock->setVisible(!m_wiDock->isVisible()); } } void KStars::slotCalendar() { if (!m_SkyCalendar) m_SkyCalendar = new SkyCalendar(this); m_SkyCalendar->show(); } void KStars::slotGlossary() { // GlossaryDialog *dlg = new GlossaryDialog( this, true ); // QString glossaryfile =data()->stdDirs->findResource( "data", "kstars/glossary.xml" ); // QUrl u = glossaryfile; // Glossary *g = new Glossary( u ); // g->setName( i18n( "Knowledge" ) ); // dlg->addGlossary( g ); // dlg->show(); } void KStars::slotScriptBuilder() { if (!m_ScriptBuilder) m_ScriptBuilder = new ScriptBuilder(this); m_ScriptBuilder->show(); } void KStars::slotSolarSystem() { if (!m_PlanetViewer) m_PlanetViewer = new PlanetViewer(this); m_PlanetViewer->show(); } /* void KStars::slotJMoonTool() { if ( ! m_JMoonTool ) m_JMoonTool = new JMoonTool(this); m_JMoonTool->show(); } */ void KStars::slotMoonPhaseTool() { //FIXME Port to KF5 //if( ! mpt ) mpt = new MoonPhaseTool( this ); //mpt->show(); } void KStars::slotFlagManager() { if (!m_FlagManager) m_FlagManager = new FlagManager(this); m_FlagManager->show(); } void KStars::slotTelescopeWizard() { #ifdef HAVE_INDI #ifndef Q_OS_WIN QString indiServerDir = Options::indiServer(); #ifdef Q_OS_OSX if (Options::indiServerIsInternal()) indiServerDir = QCoreApplication::applicationDirPath() + "/indi"; else indiServerDir = QFileInfo(Options::indiServer()).dir().path(); #endif QStringList paths; paths << "/usr/bin" << "/usr/local/bin" << indiServerDir; if (QStandardPaths::findExecutable("indiserver").isEmpty()) { if (QStandardPaths::findExecutable("indiserver", paths).isEmpty()) { KMessageBox::error(nullptr, i18n("Unable to find INDI server. Please make sure the package that provides " "the 'indiserver' binary is installed.")); return; } } #endif QPointer twiz = new telescopeWizardProcess(this); twiz->exec(); delete twiz; #endif } void KStars::slotINDIPanel() { #ifdef HAVE_INDI #ifndef Q_OS_WIN QString indiServerDir = Options::indiServer(); #ifdef Q_OS_OSX if (Options::indiServerIsInternal()) indiServerDir = QCoreApplication::applicationDirPath() + "/indi"; else indiServerDir = QFileInfo(Options::indiServer()).dir().path(); #endif QStringList paths; paths << "/usr/bin" << "/usr/local/bin" << indiServerDir; if (QStandardPaths::findExecutable("indiserver").isEmpty()) { if (QStandardPaths::findExecutable("indiserver", paths).isEmpty()) { KMessageBox::error(nullptr, i18n("Unable to find INDI server. Please make sure the package that provides " "the 'indiserver' binary is installed.")); return; } } #endif GUIManager::Instance()->updateStatus(true); #endif } void KStars::slotINDIDriver() { #ifdef HAVE_INDI #ifndef Q_OS_WIN QString indiServerDir = Options::indiServer(); #ifdef Q_OS_OSX if (Options::indiServerIsInternal()) indiServerDir = QCoreApplication::applicationDirPath() + "/indi"; else indiServerDir = QFileInfo(Options::indiServer()).dir().path(); #endif QStringList paths; paths << "/usr/bin" << "/usr/local/bin" << indiServerDir; if (QStandardPaths::findExecutable("indiserver").isEmpty()) { if (QStandardPaths::findExecutable("indiserver", paths).isEmpty()) { KMessageBox::error(nullptr, i18n("Unable to find INDI server. Please make sure the package that provides " "the 'indiserver' binary is installed.")); return; } } #endif DriverManager::Instance()->raise(); DriverManager::Instance()->activateWindow(); DriverManager::Instance()->showNormal(); #endif } void KStars::slotEkos() { #ifdef HAVE_CFITSIO #ifdef HAVE_INDI #ifndef Q_OS_WIN QString indiServerDir = Options::indiServer(); #ifdef Q_OS_OSX if (Options::indiServerIsInternal()) indiServerDir = QCoreApplication::applicationDirPath() + "/indi"; else indiServerDir = QFileInfo(Options::indiServer()).dir().path(); #endif QStringList paths; paths << "/usr/bin" << "/usr/local/bin" << indiServerDir; if (QStandardPaths::findExecutable("indiserver").isEmpty()) { if (QStandardPaths::findExecutable("indiserver", paths).isEmpty()) { KMessageBox::error(nullptr, i18n("Unable to find INDI server. Please make sure the package that provides " "the 'indiserver' binary is installed.")); return; } } #endif if (ekosManager()->isVisible() && ekosManager()->isActiveWindow()) { ekosManager()->hide(); } else { ekosManager()->raise(); ekosManager()->activateWindow(); ekosManager()->showNormal(); } #endif #endif } void KStars::slotINDITelescopeTrack() { #ifdef HAVE_INDI if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) return; for (auto *gd : INDIListener::Instance()->getDevices()) { ISD::Telescope* telescope = dynamic_cast(gd); if (telescope != nullptr && telescope->isConnected()) { KToggleAction *a = qobject_cast(sender()); if (a != nullptr) { telescope->setTrackEnabled(a->isChecked()); return; } } } #endif } void KStars::slotINDITelescopeSlew(bool focused_object) { #ifdef HAVE_INDI if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) return; for (auto *gd : INDIListener::Instance()->getDevices()) { ISD::Telescope* telescope = dynamic_cast(gd); if (telescope != nullptr && telescope->isConnected()) { if (focused_object) { if (m_SkyMap->focusObject() != nullptr) telescope->Slew(m_SkyMap->focusObject()); } else telescope->Slew(m_SkyMap->mousePoint()); return; } } #else Q_UNUSED(focused_object) #endif } void KStars::slotINDITelescopeSlewMousePointer() { #ifdef HAVE_INDI slotINDITelescopeSlew(false); #endif } void KStars::slotINDITelescopeSync(bool focused_object) { #ifdef HAVE_INDI if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) return; for (auto *gd : INDIListener::Instance()->getDevices()) { ISD::Telescope* telescope = dynamic_cast(gd); if (telescope != nullptr && telescope->isConnected() && telescope->canSync()) { if (focused_object) { if (m_SkyMap->focusObject() != nullptr) telescope->Sync(m_SkyMap->focusObject()); } else telescope->Sync(m_SkyMap->mousePoint()); return; } } #else Q_UNUSED(focused_object) #endif } void KStars::slotINDITelescopeSyncMousePointer() { #ifdef HAVE_INDI slotINDITelescopeSync(false); #endif } void KStars::slotINDITelescopeAbort() { #ifdef HAVE_INDI if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) return; for (auto *gd : INDIListener::Instance()->getDevices()) { ISD::Telescope* telescope = dynamic_cast(gd); if (telescope != nullptr && telescope->isConnected()) { telescope->Abort(); return; } } #endif } void KStars::slotINDITelescopePark() { #ifdef HAVE_INDI if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) return; for (auto *gd : INDIListener::Instance()->getDevices()) { ISD::Telescope* telescope = dynamic_cast(gd); if (telescope != nullptr && telescope->isConnected() && telescope->canPark()) { telescope->Park(); return; } } #endif } void KStars::slotINDITelescopeUnpark() { #ifdef HAVE_INDI if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) return; for (auto *gd : INDIListener::Instance()->getDevices()) { ISD::Telescope* telescope = dynamic_cast(gd); if (telescope != nullptr && telescope->isConnected() && telescope->canPark()) { telescope->UnPark(); return; } } #endif } void KStars::slotINDIDomePark() { #ifdef HAVE_INDI if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) return; for (auto *gd : INDIListener::Instance()->getDevices()) { ISD::Dome* dome = dynamic_cast(gd); if (dome != nullptr && dome->isConnected() && dome->canPark()) { dome->Park(); return; } } #endif } void KStars::slotINDIDomeUnpark() { #ifdef HAVE_INDI if (m_KStarsData == nullptr || INDIListener::Instance() == nullptr) return; for (auto *gd : INDIListener::Instance()->getDevices()) { ISD::Dome* dome = dynamic_cast(gd); if (dome != nullptr && dome->isConnected() && dome->canPark()) { dome->UnPark(); return; } } #endif } void KStars::slotGeoLocator() { QPointer locationdialog = new LocationDialog(this); if (locationdialog->exec() == QDialog::Accepted) { GeoLocation *newLocation = locationdialog->selectedCity(); if (newLocation) { // set new location in options data()->setLocation(*newLocation); // adjust local time to keep UT the same. // create new LT without DST offset KStarsDateTime ltime = newLocation->UTtoLT(data()->ut()); // reset timezonerule to compute next dst change newLocation->tzrule()->reset_with_ltime(ltime, newLocation->TZ0(), data()->isTimeRunningForward()); // reset next dst change time data()->setNextDSTChange(newLocation->tzrule()->nextDSTChange()); // reset local sideral time data()->syncLST(); // Make sure Numbers, Moon, planets, and sky objects are updated immediately data()->setFullTimeUpdate(); // If the sky is in Horizontal mode and not tracking, reset focus such that // Alt/Az remain constant. if (!Options::isTracking() && Options::useAltAz()) { map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat()); } // recalculate new times and objects data()->setSnapNextFocus(); updateTime(); } } delete locationdialog; } void KStars::slotViewOps() { //An instance of your dialog could be already created and could be cached, //in which case you want to display the cached dialog instead of creating //another one if (KConfigDialog::showDialog("settings")) return; //KConfigDialog didn't find an instance of this dialog, so lets create it : KConfigDialog *dialog = new KConfigDialog(this, "settings", Options::self()); // For some reason the dialog does not resize to contents // so we set initial 'resonable' size here. Any better way to do this? dialog->resize(800,600); #ifdef Q_OS_OSX dialog->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); #endif connect(dialog, SIGNAL(settingsChanged(QString)), this, SLOT(slotApplyConfigChanges())); opcatalog = new OpsCatalog(); opguides = new OpsGuides(); opsolsys = new OpsSolarSystem(); opssatellites = new OpsSatellites(); opssupernovae = new OpsSupernovae(); opcolors = new OpsColors(); opadvanced = new OpsAdvanced(); KPageWidgetItem *page; page = dialog->addPage(opcatalog, i18n("Catalogs"), "kstars_catalog"); page->setIcon(QIcon::fromTheme("kstars_catalog")); page = dialog->addPage(opsolsys, i18n("Solar System"), "kstars_solarsystem"); page->setIcon(QIcon::fromTheme("kstars_solarsystem")); page = dialog->addPage(opssatellites, i18n("Satellites"), "kstars_satellites"); page->setIcon(QIcon::fromTheme("kstars_satellites")); page = dialog->addPage(opssupernovae, i18n("Supernovae"), "kstars_supernovae"); page->setIcon(QIcon::fromTheme("kstars_supernovae")); page = dialog->addPage(opguides, i18n("Guides"), "kstars_guides"); page->setIcon(QIcon::fromTheme("kstars_guides")); page = dialog->addPage(opcolors, i18n("Colors"), "kstars_colors"); page->setIcon(QIcon::fromTheme("kstars_colors")); #ifdef HAVE_CFITSIO opsfits = new OpsFITS(); page = dialog->addPage(opsfits, i18n("FITS"), "kstars_fitsviewer"); page->setIcon(QIcon::fromTheme("kstars_fitsviewer")); #endif #ifdef HAVE_INDI opsindi = new OpsINDI(); page = dialog->addPage(opsindi, i18n("INDI"), "kstars_indi"); page->setIcon(QIcon::fromTheme("kstars_indi")); #ifdef HAVE_CFITSIO opsekos = new OpsEkos(); KPageWidgetItem *ekosOption = dialog->addPage(opsekos, i18n("Ekos"), "kstars_ekos"); ekosOption->setIcon(QIcon::fromTheme("kstars_ekos")); if (m_EkosManager) m_EkosManager->setOptionsWidget(ekosOption); #endif #endif -#ifdef HAVE_XPLANET opsxplanet = new OpsXplanet(this); page = dialog->addPage(opsxplanet, i18n("Xplanet"), "kstars_xplanet"); page->setIcon(QIcon::fromTheme("kstars_xplanet")); -#endif page = dialog->addPage(opadvanced, i18n("Advanced"), "kstars_advanced"); page->setIcon(QIcon::fromTheme("kstars_advanced")); dialog->show(); } void KStars::slotApplyConfigChanges() { Options::self()->save(); applyConfig(); //data()->setFullTimeUpdate(); //map()->forceUpdate(); } void KStars::slotApplyWIConfigChanges() { Options::self()->save(); applyConfig(); m_WIView->updateObservingConditions(); m_WIView->onReloadIconClicked(); } void KStars::slotSetTime() { QPointer timedialog = new TimeDialog(data()->lt(), data()->geo(), this); if (timedialog->exec() == QDialog::Accepted) { data()->changeDateTime(data()->geo()->LTtoUT(timedialog->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(); } } delete timedialog; } //Set Time to CPU clock void KStars::slotSetTimeToNow() { data()->changeDateTime(KStarsDateTime::currentDateTimeUtc()); 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 KStars::slotFind() { clearCachedFindDialog(); if (!m_FindDialog) // create new dialog if no dialog is existing { m_FindDialog = new FindDialog(this); } if (!m_FindDialog) qWarning() << i18n("KStars::slotFind() - Not enough memory for dialog"); SkyObject *targetObject; if (m_FindDialog->exec() == QDialog::Accepted && (targetObject = m_FindDialog->targetObject())) { map()->setClickedObject(targetObject); map()->setClickedPoint(map()->clickedObject()); map()->slotCenter(); } // check if data has changed while dialog was open if (DialogIsObsolete) clearCachedFindDialog(); } void KStars::slotOpenFITS() { #ifdef HAVE_CFITSIO static QUrl path = QUrl::fromLocalFile(QDir::homePath()); QUrl fileURL = QFileDialog::getOpenFileUrl(KStars::Instance(), i18n("Open FITS"), path, "FITS (*.fits *.fit *.fts)"); if (fileURL.isEmpty()) return; // Remember last directory path.setUrl(fileURL.url(QUrl::RemoveFilename)); FITSViewer *fv = new FITSViewer((Options::independentWindowFITS()) ? nullptr : this); // Error opening file if (fv->addFITS(&fileURL, FITS_NORMAL, FITS_NONE, QString(), false) == -2) delete (fv); else { m_FITSViewers.append(fv); fv->show(); } #endif } void KStars::slotExportImage() { //TODO Check this //For remote files, this returns //QFileInfo::absolutePath: QFileInfo::absolutePath: Constructed with empty filename //As of 2014-07-19 //QUrl fileURL = KFileDialog::getSaveUrl( QDir::homePath(), "image/png image/jpeg image/gif image/x-portable-pixmap image/bmp image/svg+xml" ); QUrl fileURL = QFileDialog::getSaveFileUrl(KStars::Instance(), i18n("Export Image"), QUrl(), "Images (*.png *.jpeg *.gif *.bmp *.svg)"); //User cancelled file selection dialog - abort image export if (fileURL.isEmpty()) { return; } //Warn user if file exists! if (QFile::exists(fileURL.toLocalFile())) { int r = KMessageBox::warningContinueCancel( parentWidget(), i18n("A file named \"%1\" already exists. Overwrite it?", fileURL.fileName()), i18n("Overwrite File?"), KStandardGuiItem::overwrite()); if (r == KMessageBox::Cancel) return; } // execute image export dialog // Note: We don't let ExportImageDialog create its own ImageExporter because we want legend settings etc to be remembered between UI use and DBus scripting interface use. //if ( !m_ImageExporter ) //m_ImageExporter = new ImageExporter( this ); if (!m_ExportImageDialog) { m_ExportImageDialog = new ExportImageDialog(fileURL.toLocalFile(), QSize(map()->width(), map()->height()), KStarsData::Instance()->imageExporter()); } else { m_ExportImageDialog->setOutputUrl(fileURL.toLocalFile()); m_ExportImageDialog->setOutputSize(QSize(map()->width(), map()->height())); } m_ExportImageDialog->show(); } void KStars::slotRunScript() { QUrl fileURL = QFileDialog::getOpenFileUrl( KStars::Instance(), QString(), QUrl(QDir::homePath()), "*.kstars|" + i18nc("Filter by file type: KStars Scripts.", "KStars Scripts (*.kstars)")); QFile f; //QString fname; if (fileURL.isValid()) { if (fileURL.isLocalFile() == false) { KMessageBox::sorry(nullptr, i18n("Executing remote scripts is not supported.")); return; } f.setFileName(fileURL.toLocalFile()); if (!f.open(QIODevice::ReadOnly)) { QString message = i18n("Could not open file %1", f.fileName()); KMessageBox::sorry(nullptr, message, i18n("Could Not Open File")); return; } QTextStream istream(&f); QString line; bool fileOK(true); while (!istream.atEnd()) { line = istream.readLine(); if (line.at(0) != '#' && line.left(9) != "dbus-send") { fileOK = false; break; } } if (!fileOK) { int answer; answer = KMessageBox::warningContinueCancel( nullptr, i18n("The selected script contains unrecognized elements, " "indicating that it was not created using the KStars script builder. " "This script may not function properly, and it may even contain malicious code. " "Would you like to execute it anyway?"), i18n("Script Validation Failed"), KGuiItem(i18n("Run Nevertheless")), KStandardGuiItem::cancel(), "daExecuteScript"); if (answer == KMessageBox::Cancel) return; } //Add statusbar message that script is running statusBar()->showMessage(i18n("Running script: %1", fileURL.fileName())); // 2017-09-19: Jasem // FIXME This is a hack and does not work on non-Linux systems // The Script Builder should generate files that can run cross-platform QProcess p; p.start(f.fileName()); if (!p.waitForStarted()) return; while (!p.waitForFinished(10)) { qApp->processEvents(); //otherwise tempfile may get deleted before script completes. if (p.state() != QProcess::Running) break; } statusBar()->showMessage(i18n("Script finished."), 0); } } void KStars::slotPrint() { bool switchColors(false); //Suggest Chart color scheme if (data()->colorScheme()->colorNamed("SkyColor") != QColor(255, 255, 255)) { QString message = i18n("You can save printer ink by using the \"Star Chart\" " "color scheme, which uses a white background. Would you like to " "temporarily switch to the Star Chart color scheme for printing?"); int answer; answer = KMessageBox::questionYesNoCancel( nullptr, message, i18n("Switch to Star Chart Colors?"), KGuiItem(i18n("Switch Color Scheme")), KGuiItem(i18n("Do Not Switch")), KStandardGuiItem::cancel(), "askAgainPrintColors"); if (answer == KMessageBox::Cancel) return; if (answer == KMessageBox::Yes) switchColors = true; } printImage(true, switchColors); } void KStars::slotPrintingWizard() { if (m_PrintingWizard) { delete m_PrintingWizard; } m_PrintingWizard = new PrintingWizard(this); m_PrintingWizard->show(); } void KStars::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 KStars::slotStepForward() { if (data()->clock()->isActive()) data()->clock()->stop(); data()->clock()->manualTick(true); map()->forceUpdate(); } void KStars::slotStepBackward() { if (data()->clock()->isActive()) data()->clock()->stop(); data()->clock()->manualTick(true, true); map()->forceUpdate(); } //Pointing void KStars::slotPointFocus() { // In the following cases, we set slewing=true in order to disengage tracking map()->stopTracking(); if (sender() == actionCollection()->action("zenith")) map()->setDestinationAltAz(dms(90.0), map()->focus()->az()); else if (sender() == actionCollection()->action("north")) map()->setDestinationAltAz(dms(15.0), dms(0.0001)); else if (sender() == actionCollection()->action("east")) map()->setDestinationAltAz(dms(15.0), dms(90.0)); else if (sender() == actionCollection()->action("south")) map()->setDestinationAltAz(dms(15.0), dms(180.0)); else if (sender() == actionCollection()->action("west")) map()->setDestinationAltAz(dms(15.0), dms(270.0)); } void KStars::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; } map()->setClickedObject(nullptr); map()->setFocusObject(nullptr); //no longer tracking focusObject map()->setFocusPoint(nullptr); } else { map()->setClickedPoint(map()->focus()); map()->setClickedObject(nullptr); map()->setFocusObject(nullptr); //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(); } void KStars::slotManualFocus() { QPointer focusDialog = new FocusDialog(); if (Options::useAltAz()) focusDialog->activateAzAltPage(); if (focusDialog->exec() == QDialog::Accepted) { //If the requested position is very near the pole, we need to point first //to an intermediate location just below the pole in order to get the longitudinal //position (RA/Az) right. double realAlt(focusDialog->point()->alt().Degrees()); double realDec(focusDialog->point()->dec().Degrees()); if (Options::useAltAz() && realAlt > 89.0) { focusDialog->point()->setAlt(89.0); focusDialog->point()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat()); } if (!Options::useAltAz() && realDec > 89.0) { focusDialog->point()->setDec(89.0); focusDialog->point()->EquatorialToHorizontal(data()->lst(), data()->geo()->lat()); } map()->setClickedPoint(focusDialog->point()); if (Options::isTracking()) slotTrack(); map()->slotCenter(); //The slew takes some time to complete, and this often causes the final focus point to be slightly //offset from the user's requested coordinates (because EquatorialToHorizontal() is called //throughout the process, which depends on the sidereal time). So we now "polish" the final //position by resetting the final focus to the focusDialog point. // //Also, if the requested position was within 1 degree of the coordinate pole, this will //automatically correct the final pointing from the intermediate offset position to the final position data()->setSnapNextFocus(); if (Options::useAltAz()) { map()->setDestinationAltAz(focusDialog->point()->alt(), focusDialog->point()->az()); } else { map()->setDestination(focusDialog->point()->ra(), focusDialog->point()->dec()); } //Now, if the requested point was near a pole, we need to reset the Alt/Dec of the focus. if (Options::useAltAz() && realAlt > 89.0) map()->focus()->setAlt(realAlt); if (!Options::useAltAz() && realDec > 89.0) map()->focus()->setDec(realAlt); //Don't track if we set Alt/Az coordinates. This way, Alt/Az remain constant. if (focusDialog->usedAltAz()) map()->stopTracking(); } delete focusDialog; } void KStars::slotZoomChanged() { // Enable/disable actions actionCollection()->action("zoom_out")->setEnabled(Options::zoomFactor() > MINZOOM); actionCollection()->action("zoom_in")->setEnabled(Options::zoomFactor() < MAXZOOM); // Update status bar map()->setupProjector(); // this needs to be run redundantly, so that the FOV returned below is up-to-date. float fov = map()->projector()->fov(); KLocalizedString fovi18nstring = ki18nc("approximate field of view", "Approximate FOV: %1 degrees"); if (fov < 1.0) { fov = fov * 60.0; fovi18nstring = ki18nc("approximate field of view", "Approximate FOV: %1 arcminutes"); } if (fov < 1.0) { fov = fov * 60.0; fovi18nstring = ki18nc("approximate field of view", "Approximate FOV: %1 arcseconds"); } QString fovstring = fovi18nstring.subs(QString::number(fov, 'f', 1)).toString(); statusBar()->showMessage(fovstring, 0); } void KStars::slotSetZoom() { bool ok; double currentAngle = map()->width() / (Options::zoomFactor() * dms::DegToRad); double minAngle = map()->width() / (MAXZOOM * dms::DegToRad); double maxAngle = map()->width() / (MINZOOM * dms::DegToRad); double angSize = QInputDialog::getDouble( nullptr, i18nc("The user should enter an angle for the field-of-view of the display", "Enter Desired Field-of-View Angle"), i18n("Enter a field-of-view angle in degrees: "), currentAngle, minAngle, maxAngle, 1, &ok); if (ok) { map()->setZoomFactor(map()->width() / (angSize * dms::DegToRad)); } } void KStars::slotCoordSys() { if (Options::useAltAz()) { Options::setUseAltAz(false); if (Options::useRefraction()) { if (map()->focusObject()) //simply update focus to focusObject's position map()->setFocus(map()->focusObject()); else //need to recompute focus for unrefracted position { map()->setFocusAltAz(SkyPoint::unrefract(map()->focus()->alt()), map()->focus()->az()); map()->focus()->HorizontalToEquatorial(data()->lst(), data()->geo()->lat()); } } actionCollection()->action("coordsys")->setText(i18n("Switch to horizonal view (Horizontal &Coordinates)")); } else { Options::setUseAltAz(true); if (Options::useRefraction()) { map()->setFocusAltAz(map()->focus()->altRefracted(), map()->focus()->az()); } actionCollection()->action("coordsys")->setText(i18n("Switch to star globe view (Equatorial &Coordinates)")); } map()->forceUpdate(); } void KStars::slotMapProjection() { if (sender() == actionCollection()->action("project_lambert")) Options::setProjection(Projector::Lambert); if (sender() == actionCollection()->action("project_azequidistant")) Options::setProjection(Projector::AzimuthalEquidistant); if (sender() == actionCollection()->action("project_orthographic")) Options::setProjection(Projector::Orthographic); if (sender() == actionCollection()->action("project_equirectangular")) Options::setProjection(Projector::Equirectangular); if (sender() == actionCollection()->action("project_stereographic")) Options::setProjection(Projector::Stereographic); if (sender() == actionCollection()->action("project_gnomonic")) Options::setProjection(Projector::Gnomonic); //DEBUG qCDebug(KSTARS) << "Projection system: " << Options::projection(); m_SkyMap->forceUpdate(); } //Settings Menu: void KStars::slotColorScheme() { //use mid(3) to exclude the leading "cs_" prefix from the action name QString filename = QString(sender()->objectName()).mid(3) + ".colors"; loadColorScheme(filename); } void KStars::slotTargetSymbol(bool flag) { qDebug() << QString("slotTargetSymbol: %1 %2").arg(sender()->objectName()).arg(flag); QStringList names = Options::fOVNames(); if (flag) { // Add FOV to list names.append(sender()->objectName()); } else { // Remove FOV from list int ix = names.indexOf(sender()->objectName()); if (ix >= 0) names.removeAt(ix); } Options::setFOVNames(names); // Sync visibleFOVs with fovNames data()->syncFOV(); map()->forceUpdate(); } void KStars::slotHIPSSource() { QAction *selectedAction = qobject_cast(sender()); Q_ASSERT(selectedAction != nullptr); QString selectedSource = selectedAction->text().remove("&"); // selectedSource could be translated, while we need to send only Latin "None" // to Hips manager. if (selectedSource == i18n("None")) HIPSManager::Instance()->setCurrentSource("None"); else HIPSManager::Instance()->setCurrentSource(selectedSource); map()->forceUpdate(); } void KStars::slotFOVEdit() { QPointer fovdlg = new FOVDialog(this); if (fovdlg->exec() == QDialog::Accepted) { FOVManager::save(); repopulateFOV(); } delete fovdlg; } void KStars::slotObsList() { m_KStarsData->observingList()->show(); } void KStars::slotEquipmentWriter() { QPointer equipmentdlg = new EquipmentWriter(); equipmentdlg->loadEquipment(); equipmentdlg->exec(); delete equipmentdlg; } void KStars::slotObserverManager() { QPointer m_observerAdd = new ObserverAdd(); m_observerAdd->exec(); delete m_observerAdd; } void KStars::slotHorizonManager() { if (!m_HorizonManager) { m_HorizonManager = new HorizonManager(this); connect(m_SkyMap, SIGNAL(positionClicked(SkyPoint*)), m_HorizonManager, SLOT(addSkyPoint(SkyPoint*))); } m_HorizonManager->show(); } void KStars::slotEyepieceView(SkyPoint *sp, const QString &imagePath) { if (!m_EyepieceView) m_EyepieceView = new EyepieceField(this); // FIXME: Move FOV choice into the Eyepiece View tool itself. bool ok = true; const FOV *fov = nullptr; if (!data()->getAvailableFOVs().isEmpty()) { // Ask the user to choose from a list of available FOVs. //int index; const FOV *f; QMap nameToFovMap; foreach (f, data()->getAvailableFOVs()) { nameToFovMap.insert(f->name(), f); } nameToFovMap.insert(i18n("Attempt to determine from image"), 0); fov = nameToFovMap[QInputDialog::getItem(this, i18n("Eyepiece View: Choose a field-of-view"), i18n("FOV to render eyepiece view for:"), nameToFovMap.uniqueKeys(), 0, false, &ok)]; } if (ok) m_EyepieceView->showEyepieceField(sp, fov, imagePath); } void KStars::slotExecute() { KStarsData::Instance()->executeSession()->init(); KStarsData::Instance()->executeSession()->show(); } void KStars::slotPolarisHourAngle() { QPointer pHourAngle = new PolarisHourAngle(this); pHourAngle->exec(); } //Help Menu void KStars::slotTipOfDay() { KTipDialog::showTip(this, "kstars/tips", true); } // Toggle to and from full screen mode void KStars::slotFullScreen() { if (topLevelWidget()->isFullScreen()) { topLevelWidget()->setWindowState(topLevelWidget()->windowState() & ~Qt::WindowFullScreen); // reset } else { topLevelWidget()->setWindowState(topLevelWidget()->windowState() | Qt::WindowFullScreen); // set } } void KStars::slotClearAllTrails() { //Exclude object with temporary trail SkyObject *exOb(nullptr); if (map()->focusObject() && map()->focusObject()->isSolarSystem() && data()->temporaryTrail) { exOb = map()->focusObject(); } TrailObject::clearTrailsExcept(exOb); map()->forceUpdate(); } //toggle display of GUI Items on/off void KStars::slotShowGUIItem(bool show) { //Toolbars if (sender() == actionCollection()->action("show_statusBar")) { Options::setShowStatusBar(show); statusBar()->setVisible(show); } if (sender() == actionCollection()->action("show_sbAzAlt")) { Options::setShowAltAzField(show); if (!show) AltAzField.hide(); else AltAzField.show(); } if (sender() == actionCollection()->action("show_sbRADec")) { Options::setShowRADecField(show); if (!show) RADecField.hide(); else RADecField.show(); } if (sender() == actionCollection()->action("show_sbJ2000RADec")) { Options::setShowJ2000RADecField(show); if (!show) J2000RADecField.hide(); else J2000RADecField.show(); } } void KStars::addColorMenuItem(const QString &name, const QString &actionName) { KToggleAction *kta = actionCollection()->add(actionName); kta->setText(name); kta->setObjectName(actionName); kta->setActionGroup(cschemeGroup); colorActionMenu->addAction(kta); KConfigGroup cg = KSharedConfig::openConfig()->group("Colors"); if (actionName.mid(3) == cg.readEntry("ColorSchemeFile", "moonless-night.colors").remove(".colors")) { kta->setChecked(true); } connect(kta, SIGNAL(toggled(bool)), this, SLOT(slotColorScheme())); } void KStars::removeColorMenuItem(const QString &actionName) { qCDebug(KSTARS) << "removing " << actionName; colorActionMenu->removeAction(actionCollection()->action(actionName)); } void KStars::slotAboutToQuit() { // Delete skymap. This required to run destructors and save // current state in the option. delete m_SkyMap; //Store Window geometry in Options object Options::setWindowWidth(width()); Options::setWindowHeight(height()); //explicitly save the colorscheme data to the config file data()->colorScheme()->saveToConfig(); //synch the config file with the Config object writeConfig(); //Terminate Child Processes if on OS X #ifdef Q_OS_OSX QProcess *quit = new QProcess(this); quit->start("killall kdeinit5"); quit->waitForFinished(1000); quit->start("killall klauncher"); quit->waitForFinished(1000); quit->start("killall kioslave"); quit->waitForFinished(1000); quit->start("killall kio_http_cache_cleaner"); quit->waitForFinished(1000); delete quit; #endif } void KStars::slotShowPositionBar(SkyPoint *p) { if (Options::showAltAzField()) { dms a = p->alt(); if (Options::useAltAz()) a = p->altRefracted(); QString s = QString("%1, %2").arg(p->az().toDMSString(true), //true: force +/- symbol a.toDMSString(true)); //true: force +/- symbol //statusBar()->changeItem( s, 1 ); AltAzField.setText(s); } if (Options::showRADecField()) { KStarsDateTime lastUpdate; lastUpdate.setDJD(KStarsData::Instance()->updateNum()->getJD()); QString sEpoch = QString::number(lastUpdate.epoch(), 'f', 1); QString s = QString("%1, %2 (J%3)") .arg(p->ra().toHMSString(), p->dec().toDMSString(true), sEpoch); //true: force +/- symbol //statusBar()->changeItem( s, 2 ); RADecField.setText(s); } if (Options::showJ2000RADecField()) { SkyPoint p0; p0 = p->deprecess(KStarsData::Instance()->updateNum()); // deprecess to update RA0/Dec0 from RA/Dec QString s = QString("%1, %2 (J2000)") .arg(p0.ra().toHMSString(), p0.dec().toDMSString(true)); //true: force +/- symbol //statusBar()->changeItem( s, 2 ); J2000RADecField.setText(s); } } void KStars::slotUpdateComets() { data()->skyComposite()->solarSystemComposite()->cometsComponent()->updateDataFile(); } void KStars::slotUpdateAsteroids() { data()->skyComposite()->solarSystemComposite()->asteroidsComponent()->updateDataFile(); } void KStars::slotUpdateSupernovae() { data()->skyComposite()->supernovaeComponent()->slotTriggerDataFileUpdate(); } void KStars::slotUpdateSatellites() { data()->skyComposite()->satellites()->updateTLEs(); } void KStars::slotAddDeepSkyObject() { if (!m_addDSODialog) { Q_ASSERT(data() && data()->skyComposite() && data()->skyComposite()->manualAdditionsComponent()); m_addDSODialog = new AddDeepSkyObject(this, data()->skyComposite()->manualAdditionsComponent()); } m_addDSODialog->show(); } void KStars::slotConfigureNotifications() { #ifdef HAVE_NOTIFYCONFIG KNotifyConfigWidget::configure(this); #endif } diff --git a/kstars/skymap.cpp b/kstars/skymap.cpp index 4449d63f7..1c6c5d5db 100644 --- a/kstars/skymap.cpp +++ b/kstars/skymap.cpp @@ -1,1434 +1,1438 @@ /************************************************************************** skymap.cpp - K Desktop Planetarium ------------------- begin : Sat Feb 10 2001 copyright : (C) 2001 by Jason Harris email : jharris@30doradus.org ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #ifdef _WIN32 #include #endif #include "skymap.h" #include "ksasteroid.h" #include "kstars_debug.h" #include "fov.h" #include "imageviewer.h" #include "ksdssdownloader.h" #include "kspaths.h" #include "kspopupmenu.h" #include "kstars.h" #include "ksutils.h" #include "Options.h" #include "skymapcomposite.h" #ifdef HAVE_OPENGL #include "skymapgldraw.h" #endif #include "skymapqdraw.h" #include "starhopperdialog.h" #include "starobject.h" #include "texturemanager.h" #include "dialogs/detaildialog.h" #include "printing/printingwizard.h" #include "skycomponents/flagcomponent.h" #include "skyobjects/deepskyobject.h" #include "skyobjects/ksplanetbase.h" #include "tools/flagmanager.h" #include "widgets/infoboxwidget.h" #include "projections/azimuthalequidistantprojector.h" #include "projections/equirectangularprojector.h" #include "projections/lambertprojector.h" #include "projections/gnomonicprojector.h" #include "projections/orthographicprojector.h" #include "projections/stereographicprojector.h" #include #include #include #include #include #include #include -#ifdef HAVE_XPLANET #include #include -#endif #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; } } SkyMap *SkyMap::pinstance = nullptr; SkyMap *SkyMap::Create() { delete pinstance; pinstance = new SkyMap(); return pinstance; } SkyMap *SkyMap::Instance() { return pinstance; } SkyMap::SkyMap() : QGraphicsView(KStars::Instance()), computeSkymap(true), rulerMode(false), data(KStarsData::Instance()), pmenu(nullptr), ClickedObject(nullptr), FocusObject(nullptr), m_proj(nullptr), m_previewLegend(false), m_objPointingMode(false) { m_Scale = 1.0; ZoomRect = QRect(); setDefaultMouseCursor(); // set the cross cursor QPalette p = palette(); p.setColor(QPalette::Window, QColor(data->colorScheme()->colorNamed("SkyColor"))); setPalette(p); setFocusPolicy(Qt::StrongFocus); setMinimumSize(380, 250); setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setStyleSheet("QGraphicsView { border-style: none; }"); setMouseTracking(true); //Generate MouseMove events! midMouseButtonDown = false; mouseButtonDown = false; slewing = false; clockSlewing = false; ClickedObject = nullptr; FocusObject = nullptr; m_SkyMapDraw = nullptr; pmenu = new KSPopupMenu(); setupProjector(); //Initialize Transient label stuff m_HoverTimer.setSingleShot(true); // using this timer as a single shot timer connect(&m_HoverTimer, SIGNAL(timeout()), this, SLOT(slotTransientLabel())); connect(this, SIGNAL(destinationChanged()), this, SLOT(slewFocus())); connect(KStarsData::Instance(), SIGNAL(skyUpdate(bool)), this, SLOT(slotUpdateSky(bool))); // Time infobox m_timeBox = new InfoBoxWidget(Options::shadeTimeBox(), Options::positionTimeBox(), Options::stickyTimeBox(), QStringList(), this); m_timeBox->setVisible(Options::showTimeBox()); connect(data->clock(), SIGNAL(timeChanged()), m_timeBox, SLOT(slotTimeChanged())); connect(data->clock(), SIGNAL(timeAdvanced()), m_timeBox, SLOT(slotTimeChanged())); // Geo infobox m_geoBox = new InfoBoxWidget(Options::shadeGeoBox(), Options::positionGeoBox(), Options::stickyGeoBox(), QStringList(), this); m_geoBox->setVisible(Options::showGeoBox()); connect(data, SIGNAL(geoChanged()), m_geoBox, SLOT(slotGeoChanged())); // Object infobox m_objBox = new InfoBoxWidget(Options::shadeFocusBox(), Options::positionFocusBox(), Options::stickyFocusBox(), QStringList(), this); m_objBox->setVisible(Options::showFocusBox()); connect(this, SIGNAL(objectChanged(SkyObject*)), m_objBox, SLOT(slotObjectChanged(SkyObject*))); connect(this, SIGNAL(positionChanged(SkyPoint*)), m_objBox, SLOT(slotPointChanged(SkyPoint*))); m_SkyMapDraw = new SkyMapQDraw(this); m_SkyMapDraw->setMouseTracking(true); m_SkyMapDraw->setParent(this->viewport()); m_SkyMapDraw->show(); m_iboxes = new InfoBoxes(m_SkyMapDraw); m_iboxes->setVisible(Options::showInfoBoxes()); m_iboxes->addInfoBox(m_timeBox); m_iboxes->addInfoBox(m_geoBox); m_iboxes->addInfoBox(m_objBox); } void SkyMap::slotToggleGeoBox(bool flag) { m_geoBox->setVisible(flag); } void SkyMap::slotToggleFocusBox(bool flag) { m_objBox->setVisible(flag); } void SkyMap::slotToggleTimeBox(bool flag) { m_timeBox->setVisible(flag); } void SkyMap::slotToggleInfoboxes(bool flag) { m_iboxes->setVisible(flag); } SkyMap::~SkyMap() { /* == Save infoxes status into Options == */ Options::setShowInfoBoxes(m_iboxes->isVisibleTo(parentWidget())); // Time box Options::setPositionTimeBox(m_timeBox->pos()); Options::setShadeTimeBox(m_timeBox->shaded()); Options::setStickyTimeBox(m_timeBox->sticky()); Options::setShowTimeBox(m_timeBox->isVisibleTo(m_iboxes)); // Geo box Options::setPositionGeoBox(m_geoBox->pos()); Options::setShadeGeoBox(m_geoBox->shaded()); Options::setStickyGeoBox(m_geoBox->sticky()); Options::setShowGeoBox(m_geoBox->isVisibleTo(m_iboxes)); // Obj box Options::setPositionFocusBox(m_objBox->pos()); Options::setShadeFocusBox(m_objBox->shaded()); Options::setStickyFocusBox(m_objBox->sticky()); Options::setShowFocusBox(m_objBox->isVisibleTo(m_iboxes)); //store focus values in Options //If not tracking and using Alt/Az coords, stor the Alt/Az coordinates if (Options::useAltAz() && !Options::isTracking()) { Options::setFocusRA(focus()->az().Degrees()); Options::setFocusDec(focus()->alt().Degrees()); } else { Options::setFocusRA(focus()->ra().Hours()); Options::setFocusDec(focus()->dec().Degrees()); } #ifdef HAVE_OPENGL delete m_SkyMapGLDraw; delete m_SkyMapQDraw; m_SkyMapDraw = 0; // Just a formality #else delete m_SkyMapDraw; #endif delete pmenu; delete m_proj; pinstance = nullptr; } void SkyMap::showFocusCoords() { if (focusObject() && Options::isTracking()) emit objectChanged(focusObject()); else emit positionChanged(focus()); } void SkyMap::slotTransientLabel() { //This function is only called if the HoverTimer manages to timeout. //(HoverTimer is restarted with every mouseMoveEvent; so if it times //out, that means there was no mouse movement for HOVER_INTERVAL msec.) if (hasFocus() && !slewing && !(Options::useAltAz() && Options::showGround() && SkyPoint::refract(m_MousePoint.alt()).Degrees() < 0.0)) { double maxrad = 1000.0 / Options::zoomFactor(); SkyObject *so = data->skyComposite()->objectNearest(&m_MousePoint, maxrad); if (so && !isObjectLabeled(so)) { QToolTip::showText(QCursor::pos(), i18n("%1: %2m", so->translatedLongName(), QString::number(so->mag(), 'f', 1)), this); } } } //Slots void SkyMap::setClickedObject(SkyObject *o) { ClickedObject = o; } void SkyMap::setFocusObject(SkyObject *o) { FocusObject = o; if (FocusObject) Options::setFocusObject(FocusObject->name()); else Options::setFocusObject(i18n("nothing")); } void SkyMap::slotCenter() { KStars *kstars = KStars::Instance(); TrailObject *trailObj = dynamic_cast(focusObject()); SkyPoint *foc; if(ClickedObject != nullptr) foc = ClickedObject; else foc = &ClickedPoint; if (Options::useAltAz()) { // JM 2016-09-12: Following call has problems when ra0/dec0 of an object are not valid for example // because they're solar system bodies. So it creates a lot of issues. It is disabled and centering // works correctly for all different body types as I tested. //DeepSkyObject *dso = dynamic_cast(focusObject()); //if (dso) // foc->updateCoords(data->updateNum(), true, data->geo()->lat(), data->lst(), false); // JM 2018-05-06: No need to do the above foc->EquatorialToHorizontal(data->lst(), data->geo()->lat()); } else foc->updateCoords(data->updateNum(), true, data->geo()->lat(), data->lst(), false); qCDebug(KSTARS) << "Centering on " << foc->ra().toHMSString() << foc->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 && foc->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(nullptr); setFocusObject(nullptr); Options::setIsTracking(false); return; } } //set FocusObject before slewing. Otherwise, KStarsData::updateTime() can reset //destination to previous object... setFocusObject(ClickedObject); if(ClickedObject == nullptr) setFocusPoint(&ClickedPoint); 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(foc->altRefracted(), foc->az()); } else { setDestination(*foc); } foc->EquatorialToHorizontal(data->lst(), data->geo()->lat()); //display coordinates in statusBar emit mousePointChanged(foc); showFocusCoords(); //update FocusBox } void SkyMap::slotUpdateSky(bool now) { // Code moved from KStarsData::updateTime() //Update focus updateFocus(); if (now) QTimer::singleShot( 0, this, SLOT(forceUpdateNow())); // Why is it done this way rather than just calling forceUpdateNow()? -- asimha // --> Opening a neww thread? -- Valentin else forceUpdate(); } void SkyMap::slotDSS() { dms ra(0.0), dec(0.0); QString urlstring; //ra and dec must be the coordinates at J2000. If we clicked on an object, just use the object's ra0, dec0 coords //if we clicked on empty sky, we need to precess to J2000. if (clickedObject()) { urlstring = KSDssDownloader::getDSSURL(clickedObject()); } else { SkyPoint deprecessedPoint = clickedPoint()->deprecess(data->updateNum()); ra = deprecessedPoint.ra(); dec = deprecessedPoint.dec(); urlstring = KSDssDownloader::getDSSURL(ra, dec); // Use default size for non-objects } QUrl url(urlstring); KStars *kstars = KStars::Instance(); if (kstars) { new ImageViewer( url, i18n("Digitized Sky Survey image provided by the Space Telescope Science Institute [public domain]."), this); //iv->show(); } } void SkyMap::slotSDSS() { // TODO: Remove code duplication -- we have the same stuff // implemented in ObservingList::setCurrentImage() etc. in // tools/observinglist.cpp; must try to de-duplicate as much as // possible. QString URLprefix("http://casjobs.sdss.org/ImgCutoutDR6/getjpeg.aspx?"); QString URLsuffix("&scale=1.0&width=600&height=600&opt=GST&query=SR(10,20)"); dms ra(0.0), dec(0.0); QString RAString, DecString; //ra and dec must be the coordinates at J2000. If we clicked on an object, just use the object's ra0, dec0 coords //if we clicked on empty sky, we need to precess to J2000. if (clickedObject()) { ra = clickedObject()->ra0(); dec = clickedObject()->dec0(); } else { SkyPoint deprecessedPoint = clickedPoint()->deprecess(data->updateNum()); ra = deprecessedPoint.ra(); dec = deprecessedPoint.dec(); } RAString = RAString.sprintf("ra=%f", ra.Degrees()); DecString = DecString.sprintf("&dec=%f", dec.Degrees()); //concat all the segments into the kview command line: QUrl url(URLprefix + RAString + DecString + URLsuffix); KStars *kstars = KStars::Instance(); if (kstars) { new ImageViewer(url, i18n("Sloan Digital Sky Survey image provided by the Astrophysical Research Consortium [free " "for non-commercial use]."), this); //iv->show(); } } void SkyMap::slotEyepieceView() { KStars::Instance()->slotEyepieceView((clickedObject() ? clickedObject() : clickedPoint())); } void SkyMap::slotBeginAngularDistance() { beginRulerMode(false); } void SkyMap::slotBeginStarHop() { beginRulerMode(true); } void SkyMap::beginRulerMode(bool starHopRuler) { rulerMode = true; starHopDefineMode = starHopRuler; AngularRuler.clear(); //If the cursor is near a SkyObject, reset the AngularRuler's //start point to the position of the SkyObject double maxrad = 1000.0 / Options::zoomFactor(); SkyObject *so = data->skyComposite()->objectNearest(clickedPoint(), maxrad); if (so) { AngularRuler.append(so); AngularRuler.append(so); m_rulerStartPoint = so; } else { AngularRuler.append(clickedPoint()); AngularRuler.append(clickedPoint()); m_rulerStartPoint = clickedPoint(); } AngularRuler.update(data); } void SkyMap::slotEndRulerMode() { if (!rulerMode) return; if (!starHopDefineMode) // Angular Ruler { QString sbMessage; //If the cursor is near a SkyObject, reset the AngularRuler's //end point to the position of the SkyObject double maxrad = 1000.0 / Options::zoomFactor(); SkyPoint *rulerEndPoint; SkyObject *so = data->skyComposite()->objectNearest(clickedPoint(), maxrad); if (so) { AngularRuler.setPoint(1, so); sbMessage = so->translatedLongName() + " "; rulerEndPoint = so; } else { AngularRuler.setPoint(1, clickedPoint()); rulerEndPoint = clickedPoint(); } rulerMode = false; AngularRuler.update(data); dms angularDistance = AngularRuler.angularSize(); sbMessage += i18n("Angular distance: %1", angularDistance.toDMSString()); const StarObject *p1 = dynamic_cast(m_rulerStartPoint); const StarObject *p2 = dynamic_cast(rulerEndPoint); qCDebug(KSTARS) << "Starobjects? " << p1 << p2; if (p1 && p2) qCDebug(KSTARS) << "Distances: " << p1->distance() << "pc; " << p2->distance() << "pc"; if (p1 && p2 && std::isfinite(p1->distance()) && std::isfinite(p2->distance()) && p1->distance() > 0 && p2->distance() > 0) { double dist = sqrt(p1->distance() * p1->distance() + p2->distance() * p2->distance() - 2 * p1->distance() * p2->distance() * cos(angularDistance.radians())); qCDebug(KSTARS) << "Could calculate physical distance: " << dist << " pc"; sbMessage += i18n("; Physical distance: %1 pc", QString::number(dist)); } AngularRuler.clear(); // Create unobsructive message box with suicidal tendencies // to display result. InfoBoxWidget *box = new InfoBoxWidget(true, mapFromGlobal(QCursor::pos()), 0, QStringList(sbMessage), this); connect(box, SIGNAL(clicked()), box, SLOT(deleteLater())); QTimer::singleShot(5000, box, SLOT(deleteLater())); box->adjust(); box->show(); } else // Star Hop { StarHopperDialog *shd = new StarHopperDialog(this); const SkyPoint &startHop = *AngularRuler.point(0); const SkyPoint &stopHop = *clickedPoint(); double fov; // Field of view in arcminutes bool ok; // true if user did not cancel the operation if (data->getAvailableFOVs().size() == 1) { // Exactly 1 FOV symbol visible, so use that. Also assume a circular FOV of size min{sizeX, sizeY} FOV *f = data->getAvailableFOVs().first(); fov = ((f->sizeX() >= f->sizeY() && f->sizeY() != 0) ? f->sizeY() : f->sizeX()); ok = true; } else if (!data->getAvailableFOVs().isEmpty()) { // Ask the user to choose from a list of available FOVs. FOV const *f; QMap nameToFovMap; foreach (f, data->getAvailableFOVs()) { nameToFovMap.insert(f->name(), ((f->sizeX() >= f->sizeY() && f->sizeY() != 0) ? f->sizeY() : f->sizeX())); } fov = nameToFovMap[QInputDialog::getItem(this, i18n("Star Hopper: Choose a field-of-view"), i18n("FOV to use for star hopping:"), nameToFovMap.uniqueKeys(), 0, false, &ok)]; } else { // Ask the user to enter a field of view fov = QInputDialog::getDouble(this, i18n("Star Hopper: Enter field-of-view to use"), i18n("FOV to use for star hopping (in arcminutes):"), 60.0, 1.0, 600.0, 1, &ok); } Q_ASSERT(fov > 0.0); if (ok) { qCDebug(KSTARS) << "fov = " << fov; shd->starHop(startHop, stopHop, fov / 60.0, 9.0); //FIXME: Hardcoded maglimit value shd->show(); } rulerMode = false; } } void SkyMap::slotCancelRulerMode(void) { rulerMode = false; AngularRuler.clear(); } void SkyMap::slotAddFlag() { KStars *ks = KStars::Instance(); // popup FlagManager window and update coordinates ks->slotFlagManager(); ks->flagManager()->clearFields(); //ra and dec must be the coordinates at J2000. If we clicked on an object, just use the object's ra0, dec0 coords //if we clicked on empty sky, we need to precess to J2000. dms J2000RA, J2000DE; if (clickedObject()) { J2000RA = clickedObject()->ra0(); J2000DE = clickedObject()->dec0(); } else { SkyPoint deprecessedPoint = clickedPoint()->deprecess(data->updateNum()); J2000RA = deprecessedPoint.ra(); J2000DE = deprecessedPoint.dec(); } ks->flagManager()->setRaDec(J2000RA, J2000DE); } void SkyMap::slotEditFlag(int flagIdx) { KStars *ks = KStars::Instance(); // popup FlagManager window and switch to selected flag ks->slotFlagManager(); ks->flagManager()->showFlag(flagIdx); } void SkyMap::slotDeleteFlag(int flagIdx) { KStars *ks = KStars::Instance(); ks->data()->skyComposite()->flags()->remove(flagIdx); ks->data()->skyComposite()->flags()->saveToFile(); // if there is FlagManager created, update its flag model if (ks->flagManager()) { ks->flagManager()->deleteFlagItem(flagIdx); } } void SkyMap::slotImage() { QString message = ((QAction *)sender())->text(); message = message.remove('&'); //Get rid of accelerator markers // Need to do this because we are comparing translated strings int index = -1; for (int i = 0; i < clickedObject()->ImageTitle().size(); ++i) { if (i18nc("Image/info menu item (should be translated)", clickedObject()->ImageTitle().at(i).toLocal8Bit().data()) == message) { index = i; break; } } QString sURL; if (index >= 0 && index < clickedObject()->ImageList().size()) { sURL = clickedObject()->ImageList()[index]; } else { qCWarning(KSTARS) << "ImageList index out of bounds: " << index; if (index == -1) { qCWarning(KSTARS) << "Message string \"" << message << "\" not found in ImageTitle."; qCDebug(KSTARS) << clickedObject()->ImageTitle(); } } QUrl url(sURL); if (!url.isEmpty()) new ImageViewer(url, clickedObject()->messageFromTitle(message), this); } void SkyMap::slotInfo() { QString message = ((QAction *)sender())->text(); message = message.remove('&'); //Get rid of accelerator markers // Need to do this because we are comparing translated strings int index = -1; for (int i = 0; i < clickedObject()->InfoTitle().size(); ++i) { if (i18nc("Image/info menu item (should be translated)", clickedObject()->InfoTitle().at(i).toLocal8Bit().data()) == message) { index = i; break; } } QString sURL; if (index >= 0 && index < clickedObject()->InfoList().size()) { sURL = clickedObject()->InfoList()[index]; } else { qCWarning(KSTARS) << "InfoList index out of bounds: " << index; if (index == -1) { qCWarning(KSTARS) << "Message string \"" << message << "\" not found in InfoTitle."; qCDebug(KSTARS) << clickedObject()->InfoTitle(); } } QUrl url(sURL); if (!url.isEmpty()) QDesktopServices::openUrl(url); } bool SkyMap::isObjectLabeled(SkyObject *object) { return data->skyComposite()->labelObjects().contains(object); } SkyPoint SkyMap::getCenterPoint() { SkyPoint retVal; // FIXME: subtraction of these 0.00001 is a simple workaround, because wrong // SkyPoint is returned when _exact_ center of SkyMap is passed to the projector. retVal = projector()->fromScreen(QPointF((qreal)width() / 2 - 0.00001, (qreal)height() / 2 - 0.00001), data->lst(), data->geo()->lat()); return retVal; } void SkyMap::slotRemoveObjectLabel() { data->skyComposite()->removeNameLabel(clickedObject()); forceUpdate(); } void SkyMap::slotAddObjectLabel() { data->skyComposite()->addNameLabel(clickedObject()); forceUpdate(); } void SkyMap::slotRemovePlanetTrail() { TrailObject *tobj = dynamic_cast(clickedObject()); if (tobj) { tobj->clearTrail(); forceUpdate(); } } void SkyMap::slotAddPlanetTrail() { TrailObject *tobj = dynamic_cast(clickedObject()); if (tobj) { tobj->addToTrail(); forceUpdate(); } } void SkyMap::slotDetail() { // check if object is selected if (!clickedObject()) { KMessageBox::sorry(this, i18n("No object selected."), i18n("Object Details")); return; } DetailDialog *detail = new DetailDialog(clickedObject(), data->ut(), data->geo(), KStars::Instance()); detail->setAttribute(Qt::WA_DeleteOnClose); detail->show(); } void SkyMap::slotObjectSelected() { if (m_objPointingMode && KStars::Instance()->printingWizard()) { KStars::Instance()->printingWizard()->pointingDone(clickedObject()); m_objPointingMode = false; } } void SkyMap::slotCancelLegendPreviewMode() { m_previewLegend = false; forceUpdate(true); KStars::Instance()->showImgExportDialog(); } void SkyMap::slotFinishFovCaptureMode() { if (m_fovCaptureMode && KStars::Instance()->printingWizard()) { KStars::Instance()->printingWizard()->fovCaptureDone(); m_fovCaptureMode = false; } } void SkyMap::slotCaptureFov() { if (KStars::Instance()->printingWizard()) { KStars::Instance()->printingWizard()->captureFov(); } } void SkyMap::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 KStars *kstars = KStars::Instance(); if (kstars) kstars->updateTime(false); } } void SkyMap::setFocus(SkyPoint *p) { setFocus(p->ra(), p->dec()); } void SkyMap::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 SkyMap::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()); slewing = false; forceUpdate(); //need a total update, or slewing with the arrow keys doesn't work. } void SkyMap::setDestination(const SkyPoint &p) { setDestination(p.ra(), p.dec()); } void SkyMap::setDestination(const dms &ra, const dms &dec) { destination()->set(ra, dec); destination()->EquatorialToHorizontal(data->lst(), data->geo()->lat()); emit destinationChanged(); } void SkyMap::setDestinationAltAz(const dms &alt, const dms &az) { destination()->setAlt(alt); destination()->setAz(az); destination()->HorizontalToEquatorial(data->lst(), data->geo()->lat()); emit destinationChanged(); } void SkyMap::setClickedPoint(SkyPoint *f) { ClickedPoint = *f; } void SkyMap::updateFocus() { if (slewing) return; //Tracking on an object if (Options::isTracking() && focusObject() != nullptr) { 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() != nullptr) { 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 SkyMap::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.5; 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()); } slewing = 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()); } slewing = 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 SkyMap::slotZoomIn() { setZoomFactor(Options::zoomFactor() * DZOOM); } void SkyMap::slotZoomOut() { setZoomFactor(Options::zoomFactor() / DZOOM); } void SkyMap::slotZoomDefault() { setZoomFactor(DEFAULTZOOM); } void SkyMap::setZoomFactor(double factor) { Options::setZoomFactor(KSUtils::clamp(factor, MINZOOM, MAXZOOM)); forceUpdate(); emit zoomChanged(); } // force a new calculation of the skymap (used instead of update(), which may skip the redraw) // if now=true, SkyMap::paintEvent() is run immediately, rather than being added to the event queue // also, determine new coordinates of mouse cursor. void SkyMap::forceUpdate(bool now) { QPoint mp(mapFromGlobal(QCursor::pos())); if (!projector()->unusablePoint(mp)) { //determine RA, Dec of mouse pointer m_MousePoint = projector()->fromScreen(mp, data->lst(), data->geo()->lat()); } computeSkymap = true; // Ensure that stars are recomputed data->incUpdateID(); if (now) m_SkyMapDraw->repaint(); else m_SkyMapDraw->update(); } float SkyMap::fov() { float diagonalPixels = sqrt(static_cast(width() * width() + height() * height())); return diagonalPixels / (2 * Options::zoomFactor() * dms::DegToRad); } void SkyMap::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 Gnomonic: m_proj = new GnomonicProjector(p); break; case Stereographic: m_proj = new StereographicProjector(p); break; case Orthographic: m_proj = new OrthographicProjector(p); break; case AzimuthalEquidistant: m_proj = new AzimuthalEquidistantProjector(p); break; case Equirectangular: m_proj = new EquirectangularProjector(p); break; case Lambert: default: //TODO: implement other projection classes m_proj = new LambertProjector(p); break; } } } void SkyMap::setZoomMouseCursor() { mouseMoveCursor = false; // no mousemove cursor QBitmap cursor = zoomCursorBitmap(2); QBitmap mask = zoomCursorBitmap(4); setCursor(QCursor(cursor, mask)); } void SkyMap::setDefaultMouseCursor() { mouseMoveCursor = false; // no mousemove cursor QBitmap cursor = defaultCursorBitmap(2); QBitmap mask = defaultCursorBitmap(3); setCursor(QCursor(cursor, mask)); } void SkyMap::setMouseMoveCursor() { if (mouseButtonDown) { setCursor(Qt::SizeAllCursor); // cursor shape defined in qt mouseMoveCursor = true; } } void SkyMap::updateAngleRuler() { if (rulerMode && (!pmenu || !pmenu->isVisible())) AngularRuler.setPoint(1, &m_MousePoint); AngularRuler.update(data); } bool SkyMap::isSlewing() const { return (slewing || (clockSlewing && data->clock()->isActive())); } -#ifdef HAVE_XPLANET void SkyMap::startXplanet(const QString &outputFile) { QString year, month, day, hour, minute, seconde, fov; + const QString xPlanetLocation = Options::xplanetPath(); + // If Options::xplanetPath() is empty, return - if (Options::xplanetPath().isEmpty()) + if (xPlanetLocation.isEmpty()) { KMessageBox::error(nullptr, i18n("Xplanet binary path is empty in config panel.")); return; } + // If Options::xplanetPath() does not exist, return + const QFileInfo xPlanetLocationInfo(xPlanetLocation); + if (!xPlanetLocationInfo.exists() || !xPlanetLocationInfo.isExecutable()) + { + KMessageBox::error(nullptr, i18n("The configured Xplanet binary does not exist or is not executable.")); + return; + } + // Format date if (year.setNum(data->ut().date().year()).size() == 1) year.push_front('0'); if (month.setNum(data->ut().date().month()).size() == 1) month.push_front('0'); if (day.setNum(data->ut().date().day()).size() == 1) day.push_front('0'); if (hour.setNum(data->ut().time().hour()).size() == 1) hour.push_front('0'); if (minute.setNum(data->ut().time().minute()).size() == 1) minute.push_front('0'); if (seconde.setNum(data->ut().time().second()).size() == 1) seconde.push_front('0'); // Create xplanet process QProcess *xplanetProc = new QProcess; // Add some options QStringList args; args << "-body" << clickedObject()->name().toLower() << "-geometry" << Options::xplanetWidth() + 'x' + Options::xplanetHeight() << "-date" << year + month + day + '.' + hour + minute + seconde << "-glare" << Options::xplanetGlare() << "-base_magnitude" << Options::xplanetMagnitude() << "-light_time" << "-window"; // General options if (!Options::xplanetTitle().isEmpty()) args << "-window_title" << "\"" + Options::xplanetTitle() + "\""; if (Options::xplanetFOV()) args << "-fov" << fov.setNum(this->fov()).replace('.', ','); if (Options::xplanetConfigFile()) args << "-config" << Options::xplanetConfigFilePath(); if (Options::xplanetStarmap()) args << "-starmap" << Options::xplanetStarmapPath(); if (Options::xplanetArcFile()) args << "-arc_file" << Options::xplanetArcFilePath(); if (Options::xplanetWait()) args << "-wait" << Options::xplanetWaitValue(); if (!outputFile.isEmpty()) args << "-output" << outputFile << "-quality" << Options::xplanetQuality(); // Labels if (Options::xplanetLabel()) { args << "-fontsize" << Options::xplanetFontSize() << "-color" << "0x" + Options::xplanetColor().mid(1) << "-date_format" << Options::xplanetDateFormat(); if (Options::xplanetLabelGMT()) args << "-gmtlabel"; else args << "-label"; if (!Options::xplanetLabelString().isEmpty()) args << "-label_string" << "\"" + Options::xplanetLabelString() + "\""; if (Options::xplanetLabelTL()) args << "-labelpos" << "+15+15"; else if (Options::xplanetLabelTR()) args << "-labelpos" << "-15+15"; else if (Options::xplanetLabelBR()) args << "-labelpos" << "-15-15"; else if (Options::xplanetLabelBL()) args << "-labelpos" << "+15-15"; } // Markers if (Options::xplanetMarkerFile()) args << "-marker_file" << Options::xplanetMarkerFilePath(); if (Options::xplanetMarkerBounds()) args << "-markerbounds" << Options::xplanetMarkerBoundsPath(); // Position if (Options::xplanetRandom()) args << "-random"; else args << "-latitude" << Options::xplanetLatitude() << "-longitude" << Options::xplanetLongitude(); // Projection if (Options::xplanetProjection()) { switch (Options::xplanetProjection()) { case 1: args << "-projection" << "ancient"; break; case 2: args << "-projection" << "azimuthal"; break; case 3: args << "-projection" << "bonne"; break; case 4: args << "-projection" << "gnomonic"; break; case 5: args << "-projection" << "hemisphere"; break; case 6: args << "-projection" << "lambert"; break; case 7: args << "-projection" << "mercator"; break; case 8: args << "-projection" << "mollweide"; break; case 9: args << "-projection" << "orthographic"; break; case 10: args << "-projection" << "peters"; break; case 11: args << "-projection" << "polyconic"; break; case 12: args << "-projection" << "rectangular"; break; case 13: args << "-projection" << "tsc"; break; default: break; } if (Options::xplanetBackground()) { if (Options::xplanetBackgroundImage()) args << "-background" << Options::xplanetBackgroundImagePath(); else args << "-background" << "0x" + Options::xplanetBackgroundColorValue().mid(1); } } // We add this option at the end otherwise it does not work (???) args << "-origin" << "earth"; // Run xplanet //qDebug() << "Run:" << xplanetProc->program().join(" "); - QString xPlanetLocation = Options::xplanetPath(); - #ifdef Q_OS_OSX if (Options::xplanetIsInternal()) { xPlanetLocation = QCoreApplication::applicationDirPath() + "/xplanet/bin/xplanet"; QString searchDir = QCoreApplication::applicationDirPath() + "/xplanet/share/xplanet/"; args << "-searchdir" << searchDir; } #endif xplanetProc->start(xPlanetLocation, args); if (xplanetProc) { xplanetProc->waitForFinished(1000); new ImageViewer(QUrl::fromLocalFile(outputFile), "XPlanet View: " + clickedObject()->name() + ", " + data->lt().date().toString() + ", " + data->lt().time().toString(), this); //iv->show(); } else { KMessageBox::sorry(this, i18n("XPlanet Program Error")); } } void SkyMap::slotXplanetToWindow() { QDir writableDir; QString xPlanetDirPath = KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "xplanet"; writableDir.mkpath(xPlanetDirPath); QString xPlanetPath = xPlanetDirPath + QDir::separator() + clickedObject()->name() + ".png"; startXplanet(xPlanetPath); } void SkyMap::slotXplanetToFile() { QString filename = QFileDialog::getSaveFileName(); if (!filename.isEmpty()) { startXplanet(filename); } } -#endif diff --git a/kstars/skymap.h b/kstars/skymap.h index 2ad0826d8..a604fb675 100644 --- a/kstars/skymap.h +++ b/kstars/skymap.h @@ -1,683 +1,679 @@ /*************************************************************************** skymap.h - K Desktop Planetarium ------------------- begin : Sat Feb 10 2001 copyright : (C) 2001 by Jason Harris email : jharris@30doradus.org ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #pragma once #include "config-kstars.h" #include "skymapdrawabstract.h" #include "printing/legend.h" #include "skyobjects/skypoint.h" #include "skyobjects/skyline.h" #include #include class QPainter; class QPaintDevice; class dms; class InfoBoxes; class InfoBoxWidget; class KSPopupMenu; class KStarsData; class Projector; class SkyObject; #ifdef HAVE_OPENGL class SkyMapGLDraw; class SkyMapQDraw; #endif /** * @class SkyMap * * This is the canvas on which the sky is painted. It's the main widget for KStars. * Contains SkyPoint members for the map's Focus (current central position), Destination * (requested central position), FocusPoint (next queued position to be focused), * MousePoint (position of mouse cursor), and ClickedPoint (position of last mouse click). * Also contains the InfoBoxes for on-screen data display. * * SkyMap handles most user interaction events (both mouse and keyboard). * * @short Canvas widget for displaying the sky bitmap; also handles user interaction events. * * @author Jason Harris * @version 1.0 */ class SkyMap : public QGraphicsView { Q_OBJECT friend class SkyMapDrawAbstract; // FIXME: SkyMapDrawAbstract requires a lot of access to SkyMap friend class SkyMapQDraw; // FIXME: SkyMapQDraw requires access to computeSkymap protected: /** *Constructor. Read stored settings from KConfig object (focus position, *zoom factor, sky color, etc.). Run initPopupMenus(). */ SkyMap(); public: static SkyMap *Create(); static SkyMap *Instance(); static bool IsSlewing() { return pinstance->isSlewing(); } /** Destructor (empty) */ ~SkyMap() override; enum Projection { Lambert, AzimuthalEquidistant, Orthographic, Equirectangular, Stereographic, Gnomonic, UnknownProjection }; /** @return the angular field of view of the sky map, in degrees. *@note it must use either the height or the width of the window to calculate the *FOV angle. It chooses whichever is larger. */ float fov(); /** @short Update object name and coordinates in the Focus InfoBox */ void showFocusCoords(); /** @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 Retrieve the mouse pointer position. * * @return The sky coordinates where the mouse pointer is over. */ SkyPoint *mousePoint() { return &m_MousePoint; } /** @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 nullptr 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 nullptr 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); /** @short Call to set up the projector before a draw cycle. */ void setupProjector(); /** @ Set zoom factor. *@param factor zoom factor */ void setZoomFactor(double factor); bool isSlewing() const; // NOTE: This method is draw-backend independent. /** @short update the geometry of the angle ruler. */ void updateAngleRuler(); /** @return true if the object currently has a user label attached. *@note this function only checks for a label explicitly added to the object *with the right-click popup menu; other kinds of labels are not detected by *this function. *@param o pointer to the sky object to be tested for a User label. */ bool isObjectLabeled(SkyObject *o); /*@*@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; } // NOTE: These dynamic casts must not segfault. If they do, it's good because we know that there is a problem. /** *@short Proxy method for SkyMapDrawAbstract::exportSkyImage() */ inline void exportSkyImage(QPaintDevice *pd, bool scale = false) { dynamic_cast(m_SkyMapDraw)->exportSkyImage(pd, scale); } inline void exportSkyImage(SkyQPainter *painter, bool scale = false) { dynamic_cast(m_SkyMapDraw)->exportSkyImage(painter, scale); } SkyMapDrawAbstract *getSkyMapDrawAbstract() { return dynamic_cast(m_SkyMapDraw); } /** *@short Proxy method for SkyMapDrawAbstract::drawObjectLabels() */ inline void drawObjectLabels(QList &labelObjects) { dynamic_cast(m_SkyMapDraw)->drawObjectLabels(labelObjects); } void setPreviewLegend(bool preview) { m_previewLegend = preview; } void setLegend(const Legend &legend) { m_legend = legend; } bool isInObjectPointingMode() const { return m_objPointingMode; } void setObjectPointingMode(bool enabled) { m_objPointingMode = enabled; } void setFovCaptureMode(bool enabled) { m_fovCaptureMode = enabled; } bool isInFovCaptureMode() const { return m_fovCaptureMode; } SkyPoint getCenterPoint(); public slots: /** Recalculates the positions of objects in the sky, and then repaints the sky map. * If the positions don't need to be recalculated, use update() instead of forceUpdate(). * This saves a lot of CPU time. * @param now if true, paintEvent() is run immediately. Otherwise, it is added to the event queue */ void forceUpdate(bool now = false); /** @short Convenience function; simply calls forceUpdate(true). * @see forceUpdate() */ void forceUpdateNow() { forceUpdate(true); } /** * @short Update the focus point and call forceUpdate() * @param now is passed on to forceUpdate() */ void slotUpdateSky(bool now); /** Toggle visibility of geo infobox */ void slotToggleGeoBox(bool); /** Toggle visibility of focus infobox */ void slotToggleFocusBox(bool); /** Toggle visibility of time infobox */ void slotToggleTimeBox(bool); /** Toggle visibility of all infoboxes */ void slotToggleInfoboxes(bool); /** 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(); /** @short Popup menu function: Display 1st-Generation DSS image with the Image Viewer. * @note the URL is generated using the coordinates of ClickedPoint. */ void slotDSS(); /** @short Popup menu function: Display Sloan Digital Sky Survey image with the Image Viewer. * @note the URL is generated using the coordinates of ClickedPoint. */ void slotSDSS(); /** @short Popup menu function: Show webpage about ClickedObject * (only available for some objects). */ void slotInfo(); /** @short Popup menu function: Show image of ClickedObject * (only available for some objects). */ void slotImage(); /** @short Popup menu function: Show the Detailed Information window for ClickedObject. */ void slotDetail(); /** Add ClickedObject to KStarsData::ObjLabelList, which stores pointers to SkyObjects which * have User Labels attached. */ void slotAddObjectLabel(); /** Remove ClickedObject from KStarsData::ObjLabelList, which stores pointers to SkyObjects which * have User Labels attached. */ void slotRemoveObjectLabel(); /** @short Add a Planet Trail to ClickedObject. * @note Trails are added simply by calling KSPlanetBase::addToTrail() to add the first point. * as long as the trail is not empty, new points will be automatically appended to it. * @note if ClickedObject is not a Solar System body, this function does nothing. * @see KSPlanetBase::addToTrail() */ void slotAddPlanetTrail(); /** @short Remove the PlanetTrail from ClickedObject. * @note The Trail is removed by simply calling KSPlanetBase::clearTrail(). As long as * the trail is empty, no new points will be automatically appended. * @see KSPlanetBase::clearTrail() */ void slotRemovePlanetTrail(); /** Checks whether the timestep exceeds a threshold value. If so, sets * ClockSlewing=true and sets the SimClock to ManualMode. */ void slotClockSlewing(); /** Enables the angular distance measuring mode. It saves the first * position of the ruler in a SkyPoint. It makes difference between * having clicked on the skymap and not having done so * \note This method is draw-backend independent. */ void slotBeginAngularDistance(); void slotBeginStarHop(); // TODO: Add docs /** Computes the angular distance, prints the result in the status * bar and disables the angular distance measuring mode * If the user has clicked on the map the status bar shows the * name of the clicked object plus the angular distance. If * the user did not clicked on the map, just pressed ], only * the angular distance is printed * \note This method is draw-backend independent. */ void slotEndRulerMode(); /** Disables the angular distance measuring mode. Nothing is printed * in the status bar */ void slotCancelRulerMode(); /** @short Open Flag Manager window with clickedObject() RA and Dec entered. */ void slotAddFlag(); /** @short Open Flag Manager window with selected flag focused and ready to edit. *@param flagIdx index of flag to be edited. */ void slotEditFlag(int flagIdx); /** @short Delete selected flag. *@param flagIdx index of flag to be deleted. */ void slotDeleteFlag(int flagIdx); #ifdef HAVE_OPENGL void slotToggleGL(); #endif -#ifdef HAVE_XPLANET /** Run Xplanet to print a view in a Window*/ void slotXplanetToWindow(); /** Run Xplanet to print a view in a file */ void slotXplanetToFile(); -#endif /** Render eyepiece view */ void slotEyepieceView(); /** Zoom in one step. */ void slotZoomIn(); /** Zoom out one step. */ void slotZoomOut(); /** Set default zoom. */ void slotZoomDefault(); /** Object pointing for Printing Wizard done */ void slotObjectSelected(); void slotCancelLegendPreviewMode(); void slotFinishFovCaptureMode(); void slotCaptureFov(); 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(SkyObject *); /** Emitted when pointing changed. (At least should) */ void positionChanged(SkyPoint *); /** Emitted when position under mouse changed. */ void mousePointChanged(SkyPoint *); /** Emitted when a position is clicked */ void positionClicked(SkyPoint *); /** Emitted when a position is clicked */ void objectClicked(SkyObject *); 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 */ void keyPressEvent(QKeyEvent *e) override; /** When keyRelease is triggered, just set the "slewing" flag to false, * and update the display (to draw objects that are hidden when slewing==true). */ void keyReleaseEvent(QKeyEvent *e) override; /** 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. */ void mousePressEvent(QMouseEvent *e) override; /** set mouseButtonDown==false, slewing==false */ void mouseReleaseEvent(QMouseEvent *e) override; /** Center SkyMap at double-clicked location */ void mouseDoubleClickEvent(QMouseEvent *e) override; /** 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. */ void mouseMoveEvent(QMouseEvent *e) override; /** Zoom in and out with the mouse wheel. */ void wheelEvent(QWheelEvent *e) override; /** If the skymap will be resized, the sky must be new computed. So this * function calls explicitly new computing of the skymap. */ void resizeEvent(QResizeEvent *) override; 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 incraase 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); void beginRulerMode(bool starHopRuler); // TODO: Add docs -#ifdef HAVE_XPLANET /** * @short Strart xplanet. * @param outputFile Output file path. */ void startXplanet(const QString &outputFile = ""); -#endif bool mouseButtonDown { false }; bool midMouseButtonDown { false }; /// True if mouseMoveEvent; needed by setMouseMoveCursor bool mouseMoveCursor { false }; bool slewing { false }; bool clockSlewing { false }; //if false only old pixmap will repainted with bitBlt(), this // saves a lot of cpu usage bool computeSkymap { false }; // True if we are either looking for angular distance or star hopping directions bool rulerMode { false }; // 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 { false }; double y0; double m_Scale; KStarsData *data { nullptr }; KSPopupMenu *pmenu { nullptr }; /// Coordinates of point under cursor. It's update in function mouseMoveEvent SkyPoint m_MousePoint; SkyPoint Focus, ClickedPoint, FocusPoint, Destination; SkyObject *ClickedObject { nullptr }; SkyObject *FocusObject { nullptr }; Projector *m_proj { nullptr }; 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; // InfoBoxes. Used in desctructor to save state InfoBoxWidget *m_timeBox { nullptr }; InfoBoxWidget *m_geoBox { nullptr }; InfoBoxWidget *m_objBox { nullptr }; InfoBoxes *m_iboxes { nullptr }; // legend bool m_previewLegend { false }; Legend m_legend; bool m_objPointingMode { false }; bool m_fovCaptureMode { false }; QWidget *m_SkyMapDraw { nullptr }; // Can be dynamic_cast<> to SkyMapDrawAbstract // NOTE: These are pointers to the individual widgets #ifdef HAVE_OPENGL SkyMapQDraw *m_SkyMapQDraw { nullptr }; SkyMapGLDraw *m_SkyMapGLDraw { nullptr }; #endif static SkyMap *pinstance; /// Good to keep the original ruler start-point for purposes of dynamic_cast const SkyPoint *m_rulerStartPoint { nullptr }; };