Merge lp:~registry/stellarium/socis2015 into lp:stellarium
- socis2015
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~registry/stellarium/socis2015 |
Merge into: | lp:stellarium |
Diff against target: |
72688 lines (+65902/-1757) (has conflicts) 238 files modified
CMakeLists.txt (+31/-6) cmake/Doxyfile.cmake (+8/-5) data/CMakeLists.txt (+5/-2) data/gui/normalStyle.css (+1/-1) doc/DoxygenLayout.xml (+1/-1) doc/doxygen.css (+2/-1) doc/mainpage.doxygen (+3/-3) doc/plugIns.doxygen (+1/-0) guide/plg_interfaces.tex (+95/-1) plugins/ArchaeoLines/src/ArchaeoLines.cpp (+27/-10) plugins/ArchaeoLines/src/ArchaeoLines.hpp (+23/-14) plugins/ArchaeoLines/src/gui/ArchaeoLinesDialog.cpp (+8/-1) plugins/ArchaeoLines/src/gui/ArchaeoLinesDialog.hpp (+1/-0) plugins/Oculars/src/Oculars.cpp (+57/-83) plugins/Oculars/src/Oculars.hpp (+15/-1) plugins/Oculars/src/gui/OcularsGuiPanel.cpp (+115/-132) plugins/RemoteControl/CMakeLists.txt (+46/-0) plugins/RemoteControl/COPYING (+340/-0) plugins/RemoteControl/ChangeLog (+3/-0) plugins/RemoteControl/README (+47/-0) plugins/RemoteControl/RemoteControl.qrc (+6/-0) plugins/RemoteControl/doc/qtwebapp.doxygen (+35/-0) plugins/RemoteControl/doc/remoteControl.doxygen (+61/-0) plugins/RemoteControl/doc/remoteControlApi.doxygen (+461/-0) plugins/RemoteControl/doc/remoteControlWeb.doxygen (+564/-0) plugins/RemoteControl/src/APIController.cpp (+141/-0) plugins/RemoteControl/src/APIController.hpp (+64/-0) plugins/RemoteControl/src/AbstractAPIService.cpp (+159/-0) plugins/RemoteControl/src/AbstractAPIService.hpp (+160/-0) plugins/RemoteControl/src/CMakeLists.txt (+78/-0) plugins/RemoteControl/src/LocationSearchService.cpp (+104/-0) plugins/RemoteControl/src/LocationSearchService.hpp (+58/-0) plugins/RemoteControl/src/LocationService.cpp (+258/-0) plugins/RemoteControl/src/LocationService.hpp (+56/-0) plugins/RemoteControl/src/MainService.cpp (+622/-0) plugins/RemoteControl/src/MainService.hpp (+122/-0) plugins/RemoteControl/src/ObjectService.cpp (+216/-0) plugins/RemoteControl/src/ObjectService.hpp (+67/-0) plugins/RemoteControl/src/RemoteControl.cpp (+288/-0) plugins/RemoteControl/src/RemoteControl.hpp (+179/-0) plugins/RemoteControl/src/RequestHandler.cpp (+222/-0) plugins/RemoteControl/src/RequestHandler.hpp (+88/-0) plugins/RemoteControl/src/ScriptService.cpp (+169/-0) plugins/RemoteControl/src/ScriptService.hpp (+52/-0) plugins/RemoteControl/src/SimbadService.cpp (+193/-0) plugins/RemoteControl/src/SimbadService.hpp (+53/-0) plugins/RemoteControl/src/StelActionService.cpp (+115/-0) plugins/RemoteControl/src/StelActionService.hpp (+54/-0) plugins/RemoteControl/src/StelPropertyService.cpp (+113/-0) plugins/RemoteControl/src/StelPropertyService.hpp (+50/-0) plugins/RemoteControl/src/ViewService.cpp (+201/-0) plugins/RemoteControl/src/ViewService.hpp (+51/-0) plugins/RemoteControl/src/gui/RemoteControlDialog.cpp (+182/-0) plugins/RemoteControl/src/gui/RemoteControlDialog.hpp (+61/-0) plugins/RemoteControl/src/gui/remoteControlDialog.ui (+323/-0) plugins/RemoteControl/src/qtwebapp/copyright.txt (+11/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpconnectionhandler.cpp (+295/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpconnectionhandler.h (+146/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpconnectionhandlerpool.cpp (+137/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpconnectionhandlerpool.h (+119/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpcookie.cpp (+243/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpcookie.h (+112/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpglobal.cpp (+7/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpglobal.h (+30/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httplistener.cpp (+90/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httplistener.h (+113/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httprequest.cpp (+553/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httprequest.h (+235/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httprequesthandler.cpp (+21/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httprequesthandler.h (+50/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpresponse.cpp (+202/-0) plugins/RemoteControl/src/qtwebapp/httpserver/httpresponse.h (+163/-0) plugins/RemoteControl/src/qtwebapp/httpserver/staticfilecontroller.cpp (+185/-0) plugins/RemoteControl/src/qtwebapp/httpserver/staticfilecontroller.h (+117/-0) plugins/RemoteControl/src/qtwebapp/lgpl-3.0.txt (+165/-0) plugins/RemoteControl/src/qtwebapp/readme.txt (+7/-0) plugins/RemoteControl/src/qtwebapp/templateengine/template.cpp (+295/-0) plugins/RemoteControl/src/qtwebapp/templateengine/template.h (+187/-0) plugins/RemoteControl/src/qtwebapp/templateengine/templateglobal.h (+24/-0) plugins/RemoteControl/util/update_translationdata.py (+42/-0) plugins/RemoteControl/webroot/dejavusans-webfont.svg (+6922/-0) plugins/RemoteControl/webroot/dejavusansmono-webfont.svg (+3318/-0) plugins/RemoteControl/webroot/external/jquery-ui.css (+1225/-0) plugins/RemoteControl/webroot/iframestyle.css (+54/-0) plugins/RemoteControl/webroot/index.html (+496/-0) plugins/RemoteControl/webroot/js/api/actions.js (+142/-0) plugins/RemoteControl/webroot/js/api/flags.js (+54/-0) plugins/RemoteControl/webroot/js/api/location.js (+172/-0) plugins/RemoteControl/webroot/js/api/properties.js (+161/-0) plugins/RemoteControl/webroot/js/api/remotecontrol.js (+205/-0) plugins/RemoteControl/webroot/js/api/scripts.js (+63/-0) plugins/RemoteControl/webroot/js/api/search.js (+174/-0) plugins/RemoteControl/webroot/js/api/time.js (+377/-0) plugins/RemoteControl/webroot/js/api/trunc.js (+8/-0) plugins/RemoteControl/webroot/js/api/updatequeue.js (+40/-0) plugins/RemoteControl/webroot/js/api/viewcontrol.js (+131/-0) plugins/RemoteControl/webroot/js/api/viewoptions.js (+85/-0) plugins/RemoteControl/webroot/js/globalize.js (+1586/-0) plugins/RemoteControl/webroot/js/jquery-1.11.3.js (+10351/-0) plugins/RemoteControl/webroot/js/jquery-ui.js (+16617/-0) plugins/RemoteControl/webroot/js/jquery.ui.touch-punch.js (+180/-0) plugins/RemoteControl/webroot/js/main.js (+31/-0) plugins/RemoteControl/webroot/js/plugins/archaeolines.js (+7/-0) plugins/RemoteControl/webroot/js/require.js (+2103/-0) plugins/RemoteControl/webroot/js/settings.js (+22/-0) plugins/RemoteControl/webroot/js/translationdata.js (+33/-0) plugins/RemoteControl/webroot/js/ui/actions.js (+84/-0) plugins/RemoteControl/webroot/js/ui/combobox.js (+148/-0) plugins/RemoteControl/webroot/js/ui/jqueryuifixes.js (+162/-0) plugins/RemoteControl/webroot/js/ui/location.js (+237/-0) plugins/RemoteControl/webroot/js/ui/mainui.js (+334/-0) plugins/RemoteControl/webroot/js/ui/scripts.js (+90/-0) plugins/RemoteControl/webroot/js/ui/search.js (+267/-0) plugins/RemoteControl/webroot/js/ui/time.js (+223/-0) plugins/RemoteControl/webroot/js/ui/viewcontrol.js (+88/-0) plugins/RemoteControl/webroot/js/ui/viewoptions.js (+132/-0) plugins/RemoteControl/webroot/style.css (+889/-0) plugins/RemoteControl/webroot/style_tablet7in.css (+161/-0) plugins/RemoteControl/webroot/tablet7in.html (+690/-0) plugins/RemoteControl/webroot/translate_files (+17/-0) plugins/RemoteSync/CMakeLists.txt (+20/-0) plugins/RemoteSync/RemoteSync.qrc (+6/-0) plugins/RemoteSync/src/CMakeLists.txt (+43/-0) plugins/RemoteSync/src/RemoteSync.cpp (+276/-0) plugins/RemoteSync/src/RemoteSync.hpp (+159/-0) plugins/RemoteSync/src/SyncClient.cpp (+185/-0) plugins/RemoteSync/src/SyncClient.hpp (+71/-0) plugins/RemoteSync/src/SyncClientHandlers.cpp (+243/-0) plugins/RemoteSync/src/SyncClientHandlers.hpp (+89/-0) plugins/RemoteSync/src/SyncMessages.cpp (+171/-0) plugins/RemoteSync/src/SyncMessages.hpp (+127/-0) plugins/RemoteSync/src/SyncProtocol.cpp (+227/-0) plugins/RemoteSync/src/SyncProtocol.hpp (+191/-0) plugins/RemoteSync/src/SyncServer.cpp (+294/-0) plugins/RemoteSync/src/SyncServer.hpp (+86/-0) plugins/RemoteSync/src/SyncServerEventSenders.cpp (+104/-0) plugins/RemoteSync/src/SyncServerEventSenders.hpp (+131/-0) plugins/RemoteSync/src/SyncServerHandlers.cpp (+105/-0) plugins/RemoteSync/src/SyncServerHandlers.hpp (+61/-0) plugins/RemoteSync/src/gui/RemoteSyncDialog.cpp (+207/-0) plugins/RemoteSync/src/gui/RemoteSyncDialog.hpp (+60/-0) plugins/RemoteSync/src/gui/remoteSyncDialog.ui (+373/-0) plugins/Scenery3d/src/Scenery3d.cpp (+4/-2) plugins/TextUserInterface/src/TextUserInterface.cpp (+6/-14) plugins/TextUserInterface/src/TextUserInterface.hpp (+0/-1) po/CMakeLists.txt (+3/-0) po/stellarium-remotecontrol/CMakeLists.txt (+73/-0) po/stellarium-remotecontrol/POTFILES.in (+23/-0) po/stellarium-remotecontrol/en.po (+325/-0) po/stellarium-remotecontrol/stellarium-remotecontrol-js.pot (+123/-0) po/stellarium-remotecontrol/stellarium-remotecontrol.pot (+581/-0) scripts/tests/real_time.ssc (+2/-2) src/CLIProcessor.cpp (+6/-1) src/CMakeLists.txt (+19/-0) src/StelLogger.cpp (+11/-0) src/StelLogger.hpp (+2/-0) src/StelMainView.cpp (+23/-5) src/core/SimbadSearcher.cpp (+20/-2) src/core/SimbadSearcher.hpp (+4/-1) src/core/StelActionMgr.cpp (+64/-54) src/core/StelActionMgr.hpp (+84/-37) src/core/StelApp.cpp (+19/-12) src/core/StelApp.hpp (+7/-4) src/core/StelAudioMgr.cpp (+52/-0) src/core/StelAudioMgr.hpp (+12/-0) src/core/StelCore.cpp (+108/-7) src/core/StelCore.hpp (+58/-10) src/core/StelLocation.cpp (+6/-0) src/core/StelLocation.hpp (+7/-0) src/core/StelLocationMgr.cpp (+34/-26) src/core/StelLocationMgr.hpp (+28/-29) src/core/StelModule.cpp (+6/-1) src/core/StelModule.hpp (+16/-3) src/core/StelModuleMgr.cpp (+4/-0) src/core/StelMovementMgr.cpp (+150/-33) src/core/StelMovementMgr.hpp (+74/-18) src/core/StelObject.cpp (+3/-1) src/core/StelObject.hpp (+8/-3) src/core/StelObjectModule.hpp (+1/-0) src/core/StelObjectType.hpp (+2/-0) src/core/StelObserver.cpp (+5/-3) src/core/StelObserver.hpp (+9/-1) src/core/StelProjector.cpp (+1/-0) src/core/StelProjector.hpp (+6/-3) src/core/StelProjectorClasses.cpp (+26/-16) src/core/StelPropertyMgr.cpp (+225/-0) src/core/StelPropertyMgr.hpp (+318/-0) src/core/StelRegionObject.hpp (+8/-6) src/core/StelSkyCultureMgr.cpp (+44/-1) src/core/StelSkyCultureMgr.hpp (+20/-1) src/core/StelSkyDrawer.cpp (+25/-20) src/core/StelSkyDrawer.hpp (+83/-27) src/core/StelTranslator.cpp (+5/-0) src/core/StelTranslator.hpp (+8/-0) src/core/StelUtils.cpp (+15/-5) src/core/StelUtils.hpp (+2/-2) src/core/VecMath.hpp (+16/-0) src/core/modules/Constellation.cpp (+3/-2) src/core/modules/Constellation.hpp (+3/-0) src/core/modules/ConstellationMgr.cpp (+66/-25) src/core/modules/ConstellationMgr.hpp (+43/-13) src/core/modules/LabelMgr.cpp (+4/-1) src/core/modules/LandscapeMgr.cpp (+50/-18) src/core/modules/LandscapeMgr.hpp (+80/-15) src/core/modules/MilkyWay.cpp (+1/-1) src/core/modules/MilkyWay.hpp (+8/-2) src/core/modules/Nebula.hpp (+9/-8) src/core/modules/NebulaMgr.cpp (+31/-16) src/core/modules/NebulaMgr.hpp (+58/-14) src/core/modules/SolarSystem.cpp (+34/-10) src/core/modules/SolarSystem.hpp (+55/-6) src/core/modules/SporadicMeteorMgr.cpp (+5/-2) src/core/modules/StarMgr.cpp (+1/-1) src/core/modules/StarMgr.hpp (+10/-5) src/core/modules/ZodiacalLight.cpp (+1/-0) src/core/modules/ZodiacalLight.hpp (+126/-120) src/gui/AtmosphereDialog.cpp (+3/-10) src/gui/ConfigurationDialog.cpp (+12/-27) src/gui/LocationDialog.cpp (+25/-40) src/gui/LocationDialog.hpp (+9/-0) src/gui/ScriptConsole.cpp (+24/-60) src/gui/ScriptConsole.hpp (+2/-0) src/gui/SearchDialog.cpp (+8/-34) src/gui/SearchDialog.hpp (+49/-6) src/gui/StelDialog.cpp (+405/-220) src/gui/StelDialog.hpp (+56/-5) src/gui/StelDialog_p.hpp (+110/-0) src/gui/StelGuiItems.hpp (+10/-3) src/gui/ViewDialog.cpp (+242/-388) src/gui/ViewDialog.hpp (+15/-18) src/gui/configurationDialog.ui (+5/-1) src/gui/viewDialog.ui (+6/-3) src/scripting/ScreenImageMgr.cpp (+8/-6) src/scripting/ScreenImageMgr.hpp (+5/-2) src/scripting/StelMainScriptAPI.cpp (+36/-13) src/scripting/StelMainScriptAPI.hpp (+37/-4) src/scripting/StelScriptMgr.cpp (+95/-26) src/scripting/StelScriptMgr.hpp (+56/-20) Text conflict in CMakeLists.txt |
To merge this branch: | bzr merge lp:~registry/stellarium/socis2015 |
Related bugs: | |
Related blueprints: |
Convert objects to use Qt properties
(Medium)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
gzotti | Needs Resubmitting | ||
Fabien Chéreau | Needs Fixing | ||
Review via email: mp+294410@code.launchpad.net |
This proposal has been superseded by a proposal from 2016-06-04.
Commit message
Merging SoCiS2015 branch: StelProperty system, RemoteControl and preliminary RemoteSync plugin.
Description of the change
This branch introduces a new way how objects distribute changes in their properties: the StelProperty system. (Based on a proper use of the QT_PROPERTY mechanism.) This allows better interaction between several ways to switch settings, not only triggering (via StelAction) but also distributing other data.
The reason for this is its second contribution: RemoteControl plugin. A web interface which allows a presenter in front of a screen to switch almost all things from a handheld tablet (or other computer) with a decent web browser (via JavaScript). Or just start a script via wget or curl per cronjob. The StelProperty system is used to automatically propagate changes into all connected GUIs. This system has now worked flawlessly for several weeks in a big museum installation.
Yet another plugin, RemoteSync, has not been completed so far. I still propose merging this branch now, because StelProperty is working well and should be used in future development, and also RemoteControl is working well and ready for a first release with V0.15.0. Both plugins will become better over time. For now, I recommend deactivating RemoteSync from default builds, it does not otherwise disturb.
Florian Schaukowitsch (fschauk) wrote : | # |
Hello Fabien,
thanks for the kind words!
To adress your issues:
StelProperty:
- Directly using the modules is an interesting idea. This would still retain the StelPropertyMgr as the central access point, having readProperty(
There could be a method that registers arbitrary QObjects, but maybe we could register all StelModule subclasses automatically. Maybe there are some properties that you do not want exposed, what to do about those? Nevertheless, this system seems to be worth testing out. I probably can retain the other added API as-is (StelDialog, RemoteControl).
- My consideration was that a StelAction is mainly a wrapper for an UI operation, which can be assigned hotkeys, etc. This only seems to make sense for boolean or argument-less actions, assigning an hotkey to an Q_PROPERTY of arbitrary type would be a bit strange? StelProperty on the other hand is more of an development/
RemoteControl:
- In the source tree, the webroot folder could be easily moved to the plugin folder. Do you still want to move it to 'share/
- The only new library used is Stefan Fring's QtWebApp (http://
Fabien Chéreau (xalioth) wrote : | # |
Hi,
see me replies inline
On Thu, May 19, 2016 at 12:31 AM, Florian Schaukowitsch <
<email address hidden>> wrote:
> Hello Fabien,
> thanks for the kind words!
>
> To adress your issues:
> StelProperty:
> - Directly using the modules is an interesting idea. This would still
> retain the StelPropertyMgr as the central access point, having
> readProperty(
> methods, and something like connectToProper
> target, QString slot) or similar? A disadvantage would probably be that
> some string manipulation and lookup must be used each time, for finding out
> the object name and property name, but we can probably avoid most of this
> by putting all QMetaProperties of an object in a global QMap when it is
> registered -- assuming object names never change. Still, in a class using
> this, the property ID would need to be specified each time, instead of
> using a single StelProperty reference.
>
Yes there are drawbacks, but somehow this was already done for
QtScript/QML, which allow access to QObjects by names.
> There could be a method that registers arbitrary QObjects, but maybe we
> could register all StelModule subclasses automatically. Maybe there are
> some properties that you do not want exposed, what to do about those?
We should check if there are. But we could also probably just assume that
the preliminary goal of using Qproperties on a value is precisely to expose
it to script/GUI/remote control
> Nevertheless, this system seems to be worth testing out. I probably can
> retain the other added API as-is (StelDialog, RemoteControl).
>
yes, excepted a properties renaming, this should not be different from the
point of view of the external user of the API
> - My consideration was that a StelAction is mainly a wrapper for an UI
> operation, which can be assigned hotkeys, etc. This only seems to make
> sense for boolean or argument-less actions, assigning an hotkey to an
> Q_PROPERTY of arbitrary type would be a bit strange? StelProperty on the
> other hand is more of an development/
> internals of the various classes, and reacting to changes of these
> properties if desired. Actually, I have modified StelAction to use a
> StelProperty when possible, meaning when bound to a boolean Q_PROPERTY with
> a NOTIFY event, it internally creates and uses a StelProperty with the same
> name as the action. I still think that it makes sense to retain at least
> the direct connection to an argumentless slot somehow, to enable actions
> that have no inherent "state". I found the variant with a slot(bool) to be
> a bit weird because the StelAction has to track the current "state" itself,
> which could possibly lead to discrepencies if the slot is called directly
> elsewhere. Nevertheless, I think this variant is not really used that much,
> and introducing a boolean property for these cases should not be hard.
>
OK, I didn't look in enough details to conclude on that so please do as you
think is the best. Just try to refactor and simplify other parts of the
code if possible, even if you remove not much used feat...
- 7776. By Florian Schaukowitsch
-
Move RemoteControl webroot into plugin folder
The installation is done in a webroot folder in the install root directory, and can be overridden by a webroot folder in the Stellarium user root directory - 7777. By gzotti
-
slightly enlarged time spinner buttons (better to touch)
- 7778. By Alexander Wolf
-
changed the naming of configure options (avoid inconsistency to other configure options); auto start of Remote Control plugin was disabled for security reasons
- 7779. By Florian Schaukowitsch
-
StelPropertyMgr can now register all properties of a QObject automatically, with the ID of the StelProperty following the format "<objectName>
.<propertyName> ", like QtScript uses for property access
All StelModules which are registered with the StelModuleMgr are also automatically registered with the StelPropertyMgr
Added an alternative way to get/set StelProperty values directly with the string ID, without retrieving the StelProperty object first
Removed all StelPropertyMgr::registerPrope rty calls from StelModules and core classes, it is still being used to register StelActions as StelProperty
Renamed all property accesses to use the new format
Made StelPropery management more efficient by using QMap instead of relying on QObject parent/child relationship - 7780. By Florian Schaukowitsch
-
Removed support for boolean slots from StelAction to simplify the code and make the usage cases clearer
Modified Oculars plugin to use Q_PROPERTY instead of boolean slots for StelAction, this seems to be the only place where this functionality was actually used
StelAction now always uses a StelProperty when connected to a bool property because StelProperty now supports arbitrary properties
Fixed some whitespace issues
Florian Schaukowitsch (fschauk) wrote : | # |
Sorry for the delay, I was sick for a few days and then I somehow managed to mess up my Qt installation so hard that even a reinstall could not fix it :P
I tried out a few things. The StelPropertyMgr can now register arbitrary QObjects and their properties. All StelModules are automatically registered (in StelModuleMgr:
The properties can now be accessed with a "<objectName>
I removed the support for bool slots from StelAction, the Oculars plugin seems to be the only place this was used. StelAction now has basically 2 modes:
- connection to a bool Q_PROPERTY - the property is also registered as StelProperty with the ID of the action, a NOTIFY signal is recommended but not required
- connection to an argumentless slot, which I still think is a valid use-case
I don't think we should split this up further or combine it with StelProperty somehow because of the different uses these classes should have.
I am quite happy now with the current system, what do you think?
gzotti (georg-zotti) wrote : | # |
Looks very good IMHO, thank you!
Fabien?
- 7781. By Alexander Wolf
-
A small fix for translations support
- 7782. By Alexander Wolf
-
A small fix for cmake
- 7783. By gzotti
-
removed useless files
- 7784. By Alexander Wolf
-
sync with trunk; avoid conflicts
- 7785. By Alexander Wolf
-
added changes for Miller projection
Unmerged revisions
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-05-31 18:55:03 +0000 |
3 | +++ CMakeLists.txt 2016-06-03 22:29:41 +0000 |
4 | @@ -18,9 +18,21 @@ |
5 | |
6 | ########### Project name ########### |
7 | PROJECT(Stellarium) |
8 | +<<<<<<< TREE |
9 | SET(STELLARIUM_MAJOR "0") |
10 | SET(STELLARIUM_MINOR "14") |
11 | SET(STELLARIUM_PATCH "90") |
12 | +======= |
13 | +# Use integer versions instead of strings for easier handling if required |
14 | +SET(STELLARIUM_MAJOR 0) |
15 | +SET(STELLARIUM_MINOR 15) |
16 | +SET(STELLARIUM_PATCH 0) |
17 | +ADD_DEFINITIONS( |
18 | +-DSTELLARIUM_MAJOR=${STELLARIUM_MAJOR} |
19 | +-DSTELLARIUM_MINOR=${STELLARIUM_MINOR} |
20 | +-DSTELLARIUM_PATCH=${STELLARIUM_PATCH} |
21 | +) |
22 | +>>>>>>> MERGE-SOURCE |
23 | SET(VERSION "${STELLARIUM_MAJOR}.${STELLARIUM_MINOR}.${STELLARIUM_PATCH}") |
24 | SET(PACKAGE stellarium) |
25 | SET(COPYRIGHT_YEARS "2000-2016") |
26 | @@ -174,7 +186,7 @@ |
27 | SET(STELLARIUM_PLUGINS) # Global list of all the plugins. |
28 | MACRO(ADD_PLUGIN NAME DEFAULT) |
29 | STRING(TOUPPER ${NAME} NAME_UP) |
30 | - SET(USE_PLUGIN_${NAME_UP} ${DEFAULT} CACHE BOOL "Define wheter the ${NAME} plugin should be created.") |
31 | + SET(USE_PLUGIN_${NAME_UP} ${DEFAULT} CACHE BOOL "Define whether the ${NAME} plugin should be created.") |
32 | SET(STELLARIUM_PLUGINS ${STELLARIUM_PLUGINS} ${NAME}) |
33 | ENDMACRO() |
34 | |
35 | @@ -197,6 +209,9 @@ |
36 | ADD_PLUGIN(PointerCoordinates 1) |
37 | ADD_PLUGIN(Pulsars 1) |
38 | ADD_PLUGIN(Quasars 1) |
39 | +# SOCIS 2015: |
40 | +ADD_PLUGIN(RemoteControl 1) |
41 | +ADD_PLUGIN(RemoteSync 1) |
42 | ADD_PLUGIN(Satellites 1) |
43 | ADD_PLUGIN(Scenery3d 1) |
44 | ADD_PLUGIN(SolarSystemEditor 1) |
45 | @@ -461,9 +476,9 @@ |
46 | SET(CPACK_PACKAGE_VENDOR "Stellarium's team") |
47 | SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") |
48 | SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") |
49 | - SET(CPACK_PACKAGE_VERSION_MAJOR ${STELLARIUM_MAJOR}) |
50 | - SET(CPACK_PACKAGE_VERSION_MINOR ${STELLARIUM_MINOR}) |
51 | - SET(CPACK_PACKAGE_VERSION_PATCH ${STELLARIUM_PATCH}) |
52 | + SET(CPACK_PACKAGE_VERSION_MAJOR "${STELLARIUM_MAJOR}") |
53 | + SET(CPACK_PACKAGE_VERSION_MINOR "${STELLARIUM_MINOR}") |
54 | + SET(CPACK_PACKAGE_VERSION_PATCH "${STELLARIUM_PATCH}") |
55 | SET(CPACK_PACKAGE_INSTALL_DIRECTORY "stellarium") |
56 | SET(CPACK_SOURCE_PACKAGE_FILE_NAME "stellarium-${VERSION}") |
57 | SET(CPACK_SOURCE_GENERATOR "TGZ") |
58 | @@ -517,8 +532,18 @@ |
59 | ENDIF() |
60 | |
61 | ########### Generate doxygen doc ############### |
62 | -CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/cmake/Doxyfile.cmake ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) |
63 | -ADD_CUSTOM_TARGET(apidoc doxygen ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generate the doxygen documentation into the doc directory.") |
64 | +FIND_PACKAGE(Doxygen) |
65 | +IF(DOXYGEN_FOUND) |
66 | + IF(DOXYGEN_DOT_FOUND) |
67 | + SET(HAVE_DOT "YES") |
68 | + SET(DOT_PATH ${DOXYGEN_DOT_PATH}) |
69 | + ELSE() |
70 | + SET(HAVE_DOT "NO") |
71 | + SET(DOT_PATH "") |
72 | + ENDIF() |
73 | + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/cmake/Doxyfile.cmake ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) |
74 | + ADD_CUSTOM_TARGET(apidoc ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generate the doxygen documentation into the doc directory.") |
75 | +ENDIF() |
76 | |
77 | ##################### Generate translation copying script ###################### |
78 | IF(WIN32) |
79 | |
80 | === modified file 'cmake/Doxyfile.cmake' |
81 | --- cmake/Doxyfile.cmake 2016-04-21 07:15:21 +0000 |
82 | +++ cmake/Doxyfile.cmake 2016-06-03 22:29:41 +0000 |
83 | @@ -150,7 +150,7 @@ |
84 | # shortest path that makes the file name unique will be used |
85 | # The default value is: YES. |
86 | |
87 | -FULL_PATH_NAMES = NO |
88 | +FULL_PATH_NAMES = YES |
89 | |
90 | # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. |
91 | # Stripping is only done if one of the specified strings matches the left-hand |
92 | @@ -2026,6 +2026,9 @@ |
93 | # run, you must also specify the path to the tagfile here. |
94 | |
95 | TAGFILES = qt.tag=http://doc.qt.io/qt-5/ |
96 | + qtcore.tags=http://doc.qt.io/qt-5/ \ |
97 | + qtgui.tags=http://doc.qt.io/qt-5/ \ |
98 | + qtwidgets.tags=http://doc.qt.io/qt-5/ |
99 | |
100 | # When a file name is specified after GENERATE_TAGFILE, doxygen will create a |
101 | # tag file that is based on the input files it reads. See section "Linking to |
102 | @@ -2101,7 +2104,7 @@ |
103 | # set to NO |
104 | # The default value is: YES. |
105 | |
106 | -HAVE_DOT = NO |
107 | +HAVE_DOT = @HAVE_DOT@ |
108 | |
109 | # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed |
110 | # to run in parallel. When set to 0 doxygen will base this on the number of |
111 | @@ -2143,7 +2146,7 @@ |
112 | # The default value is: YES. |
113 | # This tag requires that the tag HAVE_DOT is set to YES. |
114 | |
115 | -CLASS_GRAPH = NO |
116 | +CLASS_GRAPH = YES |
117 | |
118 | # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a |
119 | # graph for each documented class showing the direct and indirect implementation |
120 | @@ -2152,7 +2155,7 @@ |
121 | # The default value is: YES. |
122 | # This tag requires that the tag HAVE_DOT is set to YES. |
123 | |
124 | -COLLABORATION_GRAPH = NO |
125 | +COLLABORATION_GRAPH = YES |
126 | |
127 | # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for |
128 | # groups, showing the direct groups dependencies. |
129 | @@ -2275,7 +2278,7 @@ |
130 | # found. If left blank, it is assumed the dot tool can be found in the path. |
131 | # This tag requires that the tag HAVE_DOT is set to YES. |
132 | |
133 | -DOT_PATH = |
134 | +DOT_PATH = "@DOT_PATH@" |
135 | |
136 | # The DOTFILE_DIRS tag can be used to specify one or more directories that |
137 | # contain dot files that are included in the documentation (see the \dotfile |
138 | |
139 | === modified file 'data/CMakeLists.txt' |
140 | --- data/CMakeLists.txt 2016-05-29 09:27:35 +0000 |
141 | +++ data/CMakeLists.txt 2016-06-03 22:29:41 +0000 |
142 | @@ -53,13 +53,16 @@ |
143 | ENDIF() |
144 | |
145 | # install Scenery3d shaders |
146 | +IF(USE_PLUGIN_SCENERY3D) |
147 | INSTALL(DIRECTORY shaders/ DESTINATION share/${PACKAGE}/data/shaders FILES_MATCHING |
148 | - PATTERN "s3d_*.vert" PATTERN "s3d_*.geom" PATTERN "s3d_*.frag") |
149 | - |
150 | + PATTERN "s3d_*.vert" |
151 | + PATTERN "s3d_*.geom" |
152 | + PATTERN "s3d_*.frag") |
153 | # install Scenery3D docs for Windows |
154 | IF(WIN32) |
155 | INSTALL(FILES ../plugins/Scenery3d/doc/Scenery3d.pdf DESTINATION share/${PACKAGE}/data) |
156 | ENDIF(WIN32) |
157 | +ENDIF() |
158 | |
159 | IF (BUILD_FOR_MAEMO) |
160 | INSTALL(FILES maemo/stellarium.desktop DESTINATION /usr/share/applications/hildon) |
161 | |
162 | === modified file 'data/gui/normalStyle.css' |
163 | --- data/gui/normalStyle.css 2015-08-18 06:29:08 +0000 |
164 | +++ data/gui/normalStyle.css 2016-06-03 22:29:41 +0000 |
165 | @@ -149,7 +149,7 @@ |
166 | font-size: 12px; |
167 | } |
168 | |
169 | -QLineEdit[enabled="false"] { |
170 | +QLineEdit:disabled { |
171 | background: rgb(90, 90, 90); |
172 | } |
173 | |
174 | |
175 | === modified file 'doc/DoxygenLayout.xml' |
176 | --- doc/DoxygenLayout.xml 2014-06-22 14:08:40 +0000 |
177 | +++ doc/DoxygenLayout.xml 2016-06-03 22:29:41 +0000 |
178 | @@ -18,7 +18,7 @@ |
179 | <tab type="user" url="@ref scripting" visible="yes" title="Scripting" intro=""/> |
180 | <tab type="user" url="@ref plugins" visible="yes" title="Plugins" intro=""/> |
181 | <tab type="user" url="@ref fileStructure" visible="yes" title="File Structure" intro=""/> |
182 | - <tab type="files" visible="no" title=""> |
183 | + <tab type="files" visible="yes" title=""> |
184 | <tab type="filelist" visible="yes" title="" intro=""/> |
185 | <tab type="globals" visible="yes" title="" intro=""/> |
186 | </tab> |
187 | |
188 | === modified file 'doc/doxygen.css' |
189 | --- doc/doxygen.css 2015-06-08 20:08:26 +0000 |
190 | +++ doc/doxygen.css 2016-06-03 22:29:41 +0000 |
191 | @@ -1193,7 +1193,8 @@ |
192 | float: right; |
193 | height: auto; |
194 | margin: 0 20px 10px 10px; |
195 | - width: 200px; |
196 | + min-width: 200px; |
197 | + max-width: 400px; |
198 | } |
199 | |
200 | div.toc li { |
201 | |
202 | === modified file 'doc/mainpage.doxygen' |
203 | --- doc/mainpage.doxygen 2016-02-25 17:31:00 +0000 |
204 | +++ doc/mainpage.doxygen 2016-06-03 22:29:41 +0000 |
205 | @@ -32,9 +32,9 @@ |
206 | <ul> |
207 | <li>the main loop and main widget classes @em StelMainWindow and @em StelMainGraphicsView. Those classes have a single instance which is created at startup by the main() function. They perform various tasks such as the creation of the main program window and openGL context, the creation of the stellarium core, the creation of the GUI. After initialization, they manage user's input event propagation and event loop. There are heavily based on %Qt features.</li> |
208 | <li>the core which provides a number of generic services and features to the other components. The main class is the StelApp singleton class which is used everywhere in the code to access other elements. It is the StelApp instance which creates all the main core services and modules at initialization. Example services are OpenGL textures management with the StelTextureMgr, font management with the StelFontMgr, sky images management (images which have a fixed position in the sky) with the StelSkyImageMgr etc.. Two especially important manager classes (the ones with the "Mgr" suffix) are the StelModuleMgr and StelCore classes: the first one manages the collection of StelModule instances which are registered in the program (see next point for more info on what a StelModule is). The second one provides performance critical features for rendering various elements using openGL, or for computing coordinate transformation and other mathematical services.</li> |
209 | -<li>a collection of StelModule instances which display the main elements of the program such as planets and stars. Each StelModule should be registered to the StelModuleMgr. Because many components of Stellarium derive from the StelModule class, it is possible for the main loop to treat them generically by calling their standard methods such StelModule::update() and StelModule::draw() at each program iteration. It also allows other program components to access them by name. StelModule can also be loaded dynamically by Stellarium, which is the standard way of creating @ref plugins.</li> |
210 | -<li>the Graphical User Interface (StelGui). It is based on styled %Qt widgets which are rendered directly in the openGL window. Users actions trigger signals which are connected to core and StelModules slots.</li> |
211 | -<li>the script engine (StelScriptMgr) allows scripts to calls slots from the core and StelModules slots.</li> |
212 | +<li>a collection of StelModule instances which display the main elements of the program such as planets and stars. Each StelModule should be registered to the StelModuleMgr. Because many components of Stellarium derive from the StelModule class, it is possible for the main loop to treat them generically by calling their standard methods such StelModule::update() and StelModule::draw() at each program iteration. It also allows other program components to access them by name. StelProperty can be used to access all defined static properties (see the [Qt property system](https://doc.qt.io/qt-5/properties.html) for more information) of all registered StelModule instances. StelModule can also be loaded dynamically by Stellarium, which is the standard way of creating @ref plugins. StelAction instances can be used to define actions that can be triggered by the user through UI controls or key combinations.</li> |
213 | +<li>the Graphical User Interface (StelGui). It is based on styled %Qt widgets which are rendered directly in the openGL window. Users actions can trigger signals which are connected to core and StelModules slots. Many UI controls can also be directly connected to StelAction and/or StelProperty instances to reduce the amount of boilerplate code required to link UI changes to the back-end modules and vice-versa.</li> |
214 | +<li>the script engine (StelScriptMgr) allows user scripts based on QtScript (a JavaScript dialect) to access properties and calls slots from the core and StelModule instances.</li> |
215 | </ul> |
216 | @image html stellarium-architecture.png |
217 | |
218 | |
219 | === modified file 'doc/plugIns.doxygen' |
220 | --- doc/plugIns.doxygen 2016-04-21 06:48:03 +0000 |
221 | +++ doc/plugIns.doxygen 2016-06-03 22:29:41 +0000 |
222 | @@ -65,6 +65,7 @@ |
223 | - @ref meteorShowers |
224 | - @ref pointerCoordinates |
225 | - @ref archaeoLines |
226 | + - @ref remoteControl |
227 | |
228 | You can find some untechnical details on our wiki [Plugins](http://www.stellarium.org/wiki/index.php/Plugins) page. |
229 | |
230 | |
231 | === added file 'guide/pictures/remote.png' |
232 | Binary files guide/pictures/remote.png 1970-01-01 00:00:00 +0000 and guide/pictures/remote.png 2016-06-03 22:29:41 +0000 differ |
233 | === added file 'guide/pictures/remote_web.png' |
234 | Binary files guide/pictures/remote_web.png 1970-01-01 00:00:00 +0000 and guide/pictures/remote_web.png 2016-06-03 22:29:41 +0000 differ |
235 | === modified file 'guide/plg_interfaces.tex' |
236 | --- guide/plg_interfaces.tex 2016-05-05 23:42:27 +0000 |
237 | +++ guide/plg_interfaces.tex 2016-06-03 22:29:41 +0000 |
238 | @@ -373,7 +373,101 @@ |
239 | \section{Remote Control} |
240 | \label{sec:plugin:RemoteControl} |
241 | |
242 | -[This will come as user documentation from SoCiS2015 work] |
243 | +The Remote Control plugin was developed in 2015 during the |
244 | +\href{http://sophia.estec.esa.int/socis/}{ESA Summer of Code in Space} |
245 | +initiative. It enables the user to control Stellarium through an external web |
246 | +interface using a standard web browser like Firefox or Chrome, instead of using |
247 | +the main GUI. This works on the same computer Stellarium runs as well as over |
248 | +the network. Even more, multiple "remote controls" can access the same |
249 | +Stellarium instance at the same time, without getting in the way of each other. |
250 | +Much of the functionality the main interface provides is already available |
251 | +through it, and it is still getting extended. |
252 | + |
253 | +The plugin may be useful for presentation scenarios, hiding the GUI from the |
254 | +audience and allowing the presenter to change settings on a separate monitor |
255 | +without showing distracting dialog windows. It also allows to start and stop |
256 | +scripts remotely. Because the web interface can be customized (or completely |
257 | +replaced) with some knowledge of HTML, CSS and JavaScript, another possibility |
258 | +is a kiosk mode, where untrusted users can execute a variety of predefined |
259 | +actions (like starting recorded tours) without having access to all Stellarium |
260 | +settings. The web API can also be accessed directly (without using a browser |
261 | +and the HTML interface), allowing control of Stellarium with external programs |
262 | +and scripts using HTTP calls like with the tools \file{wget} and \file{curl}. |
263 | + |
264 | +\subsection{Using the plugin} |
265 | +\label{sec:plugins:RemoteControl:using} |
266 | + |
267 | +\begin{figure}[h] |
268 | +\centering\includegraphics[width=\columnwidth]{remote_web} |
269 | +\caption{The default remote control web interface} |
270 | +\end{figure} |
271 | + |
272 | +After enabling the plugin, you can set it up through the configuration dialog. |
273 | +When ``Enable automatically on startup'' is checked (it is by default), the web |
274 | +server is automatically started whenever Stellarium starts. You can also |
275 | +manually start/stop the server using the ``Server enabled'' checkbox and the |
276 | +button \includegraphics[scale=0.5]{remote} in the toolbar. |
277 | + |
278 | +The plugin starts a HTTP server on the specified port. The default port is |
279 | +8090, so you can try to reach the remote control after enabling it by starting |
280 | +a browser on the same computer and entering \url{http://localhost:8090} in the |
281 | +address bar. When trying to access the remote control from another computer, |
282 | +you need the IP address or the hostname of the server on which Stellarium runs. |
283 | +The plugin shows the locally detected address, but depending on your network or |
284 | +if you need external access you might need to use a different one |
285 | +--- contact your network administrator if you need help with that. |
286 | + |
287 | +The access to the remote control may optionally be restricted with a simple |
288 | +password. |
289 | + |
290 | +\textbf{Warning:} \emph{currently no network encryption is used, meaning that |
291 | +an attacker having access to your network can easily find out the password by |
292 | +waiting for a user entering it. Access from the Internet to the |
293 | +plugin should generally be restricted, except if countermeasures such as VPN |
294 | +usage are taken! If you are in a home network using NAT (network access |
295 | +translation), this should be enough for basic security except if port |
296 | +forwarding or a DMZ is configured.} |
297 | + |
298 | +If you are familiar with the main Stellarium interface, you should easily find |
299 | +your way around the web interface. Tabs at the top allow access to |
300 | +different settings and controls. The remote control automatically uses the |
301 | +same language as set in the main program. |
302 | + |
303 | +The contents of the various tabs: |
304 | +\begin{description} |
305 | +\item[Main] Contains the time controls and most of the buttons of the |
306 | +main bottom toolbar. An additional control allows moving the view like when |
307 | +dragging the mouse or using the arrow keys in Stellarium, and a slider enables |
308 | +the changing of the field of view. There are also buttons to quickly execute |
309 | +time jumps using the commonly used astronomical time intervals. |
310 | +\item[Selection] Allows searching and selecting objects like in \autoref{sec:gui:search}. |
311 | +SIMBAD search is also supported. Quick select buttons are available for the |
312 | +primary solar system objects. It also displays the information text for current |
313 | +selection. |
314 | +\item[Sky] Settings related to the sky display as shown in the ``View'' dialog |
315 | +as shown in \autoref{sec:gui:view:sky}. |
316 | +\item[DSO] The deep-sky object catalog, filter and display settings like in |
317 | +\autoref{sec:gui:view:markings}. |
318 | +\item[Landscape] Changing and configuring the background landscape, see |
319 | +\autoref{sec:gui:view:landscape} |
320 | +\item[Actions and scripts] Lists all registered actions, and allows starting |
321 | +and stopping of scripts (\autoref{ch:scripting}). If there is no button for the |
322 | +action you want in another tab, you can find all actions which can be |
323 | +configured as a keyboard shortcut (\autoref{sec:gui:configuration}) here. |
324 | +\item[Location] Allows changing the location, like in |
325 | +\autoref{sec:gui:location}. Custom location saving is currently not |
326 | +supported. |
327 | +\item[Projection] Switch the projection method used, like \autoref{sec:gui:view:markings}. |
328 | +\end{description} |
329 | + |
330 | +\subsection{Developer information} |
331 | +\label{sec:plugins:RemoteControl:developer} |
332 | + |
333 | +If you are a developer and would like to add functionality to the Remote |
334 | +Control API, customize the web interface or access the API through another |
335 | +program, further information can be found in the |
336 | +\href{http://stellarium.org/doc-plugins/head/}{plugin's developer |
337 | +documentation}. |
338 | |
339 | |
340 | % \newpage |
341 | |
342 | === modified file 'plugins/ArchaeoLines/src/ArchaeoLines.cpp' |
343 | --- plugins/ArchaeoLines/src/ArchaeoLines.cpp 2015-12-29 13:15:57 +0000 |
344 | +++ plugins/ArchaeoLines/src/ArchaeoLines.cpp 2016-06-03 22:29:41 +0000 |
345 | @@ -89,7 +89,7 @@ |
346 | objMgr=GETSTELMODULE(StelObjectMgr); |
347 | Q_ASSERT(objMgr); |
348 | |
349 | - // optimize readabiity so that each upper line of the lunistice doubles is labeled. |
350 | + // optimize readability so that each upper line of the lunistice doubles is labeled. |
351 | equinoxLine = new ArchaeoLine(ArchaeoLine::Equinox, 0.0); |
352 | northernSolsticeLine = new ArchaeoLine(ArchaeoLine::Solstices, 23.50); |
353 | southernSolsticeLine = new ArchaeoLine(ArchaeoLine::Solstices, -23.50); |
354 | @@ -116,6 +116,7 @@ |
355 | |
356 | configDialog = new ArchaeoLinesDialog(); |
357 | conf = StelApp::getInstance().getSettings(); |
358 | + |
359 | } |
360 | |
361 | ArchaeoLines::~ArchaeoLines() |
362 | @@ -188,7 +189,8 @@ |
363 | StelApp& app = StelApp::getInstance(); |
364 | |
365 | // Create action for enable/disable & hook up signals |
366 | - addAction("actionShow_Archaeo_Lines", N_("ArchaeoLines"), N_("ArchaeoLines"), "enabled", "Ctrl+U"); |
367 | + QString section=N_("ArchaeoLines"); |
368 | + addAction("actionShow_Archaeo_Lines", section, N_("ArchaeoLines"), "enabled", "Ctrl+U"); |
369 | |
370 | // Add a toolbar button |
371 | try |
372 | @@ -208,6 +210,16 @@ |
373 | { |
374 | qWarning() << "WARNING: unable to create toolbar button for ArchaeoLines plugin: " << e.what(); |
375 | } |
376 | + addAction("actionAL_showEquinoxLine", section, N_("Show Line for Equinox"), "flagShowEquinox" ); // No Shortcuts configured. |
377 | + addAction("actionAL_showSolsticeLines", section, N_("Show Line for Solstices"), "flagShowSolstices" ); // No Shortcuts configured. |
378 | + addAction("actionAL_showCrossquarterLines", section, N_("Show Line for Crossquarter"), "flagShowCrossquarters" ); // No Shortcuts configured. |
379 | + addAction("actionAL_showMajorStandstillLines", section, N_("Show Line for Major Standstill"), "flagShowMajorStandstills"); // No Shortcuts configured. |
380 | + addAction("actionAL_showMinorStandstillLines", section, N_("Show Line for Minor Standstill"), "flagShowMinorStandstills"); // No Shortcuts configured. |
381 | + addAction("actionAL_showZenithPassageLine", section, N_("Show Line for Zenith Passage"), "flagShowZenithPassage" ); // No Shortcuts configured. |
382 | + addAction("actionAL_showNadirPassageLine", section, N_("Show Line for Nadir Passage"), "flagShowNadirPassage" ); // No Shortcuts configured. |
383 | + addAction("actionAL_showSelectedObjectLine", section, N_("Show Line for Selected Object"), "flagShowSelectedObject" ); // No Shortcuts configured. |
384 | + addAction("actionAL_showCurrentSunLine", section, N_("Show Line for Current Sun"), "flagShowCurrentSun" ); // No Shortcuts configured. |
385 | + addAction("actionAL_showCurrentMoonLine", section, N_("Show Line for Current Moon"), "flagShowCurrentMoon" ); // No Shortcuts configured. |
386 | } |
387 | |
388 | void ArchaeoLines::update(double deltaTime) |
389 | @@ -450,7 +462,7 @@ |
390 | // indicators for current declinations (those move fast over days...) |
391 | showCurrentSun(conf->value("ArchaeoLines/show_current_sun", true).toBool()); |
392 | showCurrentMoon(conf->value("ArchaeoLines/show_current_moon", true).toBool()); |
393 | - showCurrentPlanet(conf->value("ArchaeoLines/show_current_planet", "none").toString()); |
394 | + showCurrentPlanetNamed(conf->value("ArchaeoLines/show_current_planet", "none").toString()); |
395 | |
396 | enableArchaeoLines(conf->value("ArchaeoLines/enable_at_startup", false).toBool()); |
397 | } |
398 | @@ -526,15 +538,20 @@ |
399 | |
400 | void ArchaeoLines::showCurrentPlanet(ArchaeoLine::Line l) |
401 | { |
402 | - enumShowCurrentPlanet=l; |
403 | - const char *planetStrings[]={"none", "Mercury", "Venus", "Mars", "Jupiter", "Saturn"}; |
404 | - |
405 | - conf->setValue("ArchaeoLines/show_current_planet", planetStrings[l-ArchaeoLine::CurrentPlanetNone]); |
406 | - currentPlanetLine->setLineType(enumShowCurrentPlanet); |
407 | - currentPlanetLine->setDisplayed(enumShowCurrentPlanet != ArchaeoLine::CurrentPlanetNone); |
408 | + if(l!=enumShowCurrentPlanet) |
409 | + { |
410 | + enumShowCurrentPlanet=l; |
411 | + const char *planetStrings[]={"none", "Mercury", "Venus", "Mars", "Jupiter", "Saturn"}; |
412 | + |
413 | + conf->setValue("ArchaeoLines/show_current_planet", planetStrings[l-ArchaeoLine::CurrentPlanetNone]); |
414 | + currentPlanetLine->setLineType(enumShowCurrentPlanet); |
415 | + currentPlanetLine->setDisplayed(enumShowCurrentPlanet != ArchaeoLine::CurrentPlanetNone); |
416 | + |
417 | + emit currentPlanetChanged(l); |
418 | + } |
419 | } |
420 | |
421 | -void ArchaeoLines::showCurrentPlanet(QString planet) |
422 | +void ArchaeoLines::showCurrentPlanetNamed(QString planet) |
423 | { |
424 | if (planet=="none") |
425 | enumShowCurrentPlanet=ArchaeoLine::CurrentPlanetNone; |
426 | |
427 | === modified file 'plugins/ArchaeoLines/src/ArchaeoLines.hpp' |
428 | --- plugins/ArchaeoLines/src/ArchaeoLines.hpp 2015-08-03 13:17:06 +0000 |
429 | +++ plugins/ArchaeoLines/src/ArchaeoLines.hpp 2016-06-03 22:29:41 +0000 |
430 | @@ -77,6 +77,10 @@ |
431 | Q_OBJECT |
432 | Q_PROPERTY(Vec3f color READ getColor WRITE setColor) |
433 | Q_PROPERTY(bool flagLabel READ isLabelVisible WRITE setLabelVisible) |
434 | + |
435 | + //Need to register Enum with Qt to be able to use it as Q_PROPERTY |
436 | + //or in signals/slots |
437 | + Q_ENUMS(Line) |
438 | public: |
439 | enum Line { |
440 | Equinox, |
441 | @@ -174,7 +178,8 @@ |
442 | WRITE showCurrentMoon) |
443 | Q_PROPERTY(ArchaeoLine::Line enumShowCurrentPlanet |
444 | READ whichCurrentPlanetDisplayed |
445 | - WRITE showCurrentPlanet) |
446 | + WRITE showCurrentPlanet |
447 | + NOTIFY currentPlanetChanged) |
448 | |
449 | public: |
450 | ArchaeoLines(); |
451 | @@ -190,19 +195,7 @@ |
452 | virtual double getCallOrder(StelModuleActionName actionName) const; |
453 | virtual void handleKeys(class QKeyEvent* event){event->setAccepted(false);} |
454 | virtual bool configureGui(bool show=true); |
455 | - bool isEnabled() const {return flagShowArchaeoLines;} |
456 | bool isDmsFormat() const { return flagUseDmsFormat; } // NOT SURE IF USEFUL |
457 | - bool isEquinoxDisplayed() const {return flagShowEquinox;} |
458 | - bool isSolsticesDisplayed() const {return flagShowSolstices;} |
459 | - bool isCrossquartersDisplayed() const {return flagShowCrossquarters;} |
460 | - bool isMajorStandstillsDisplayed() const {return flagShowMajorStandstills;} |
461 | - bool isMinorStandstillsDisplayed() const {return flagShowMinorStandstills;} |
462 | - bool isZenithPassageDisplayed() const {return flagShowZenithPassage;} |
463 | - bool isNadirPassageDisplayed() const {return flagShowNadirPassage;} |
464 | - bool isSelectedObjectDisplayed() const {return flagShowSelectedObject;} |
465 | - bool isCurrentSunDisplayed() const {return flagShowCurrentSun;} |
466 | - bool isCurrentMoonDisplayed() const {return flagShowCurrentMoon;} |
467 | - ArchaeoLine::Line whichCurrentPlanetDisplayed() const {return enumShowCurrentPlanet;} |
468 | |
469 | //! Restore the plug-in's settings to the default state. |
470 | //! Replace the plug-in's settings in Stellarium's configuration file |
471 | @@ -217,11 +210,27 @@ |
472 | //! @see restoreDefaultSettings() |
473 | void loadSettings(); |
474 | |
475 | +signals: |
476 | + void currentPlanetChanged(ArchaeoLine::Line l); // meaningful only CurrentPlanetNone...CurrentPlanetSaturn. |
477 | |
478 | public slots: |
479 | void enableArchaeoLines(bool b); |
480 | //void useDmsFormat(bool b); |
481 | |
482 | + bool isEnabled() const {return flagShowArchaeoLines;} |
483 | + bool isEquinoxDisplayed() const {return flagShowEquinox;} |
484 | + bool isSolsticesDisplayed() const {return flagShowSolstices;} |
485 | + bool isCrossquartersDisplayed() const {return flagShowCrossquarters;} |
486 | + bool isMajorStandstillsDisplayed() const {return flagShowMajorStandstills;} |
487 | + bool isMinorStandstillsDisplayed() const {return flagShowMinorStandstills;} |
488 | + bool isZenithPassageDisplayed() const {return flagShowZenithPassage;} |
489 | + bool isNadirPassageDisplayed() const {return flagShowNadirPassage;} |
490 | + bool isSelectedObjectDisplayed() const {return flagShowSelectedObject;} |
491 | + bool isCurrentSunDisplayed() const {return flagShowCurrentSun;} |
492 | + bool isCurrentMoonDisplayed() const {return flagShowCurrentMoon;} |
493 | + ArchaeoLine::Line whichCurrentPlanetDisplayed() const {return enumShowCurrentPlanet;} |
494 | + |
495 | + |
496 | void showEquinox(bool b); |
497 | void showSolstices(bool b); |
498 | void showCrossquarters(bool b); |
499 | @@ -233,7 +242,7 @@ |
500 | void showCurrentSun(bool b); |
501 | void showCurrentMoon(bool b); |
502 | void showCurrentPlanet(ArchaeoLine::Line l); // Allowed values for l: CurrentPlanetNone...CurrentPlanetSaturn. |
503 | - void showCurrentPlanet(QString planet); // Allowed values for planet: "none", "Mercury", "Venus", "Mars", "Jupiter", "Saturn". |
504 | + void showCurrentPlanetNamed(QString planet); // Allowed values for planet: "none", "Mercury", "Venus", "Mars", "Jupiter", "Saturn". |
505 | |
506 | // called by the dialog GUI, converts GUI's QColor (0..255) to Stellarium's Vec3f float color. |
507 | void setLineColor(ArchaeoLine::Line whichLine, QColor color); |
508 | |
509 | === modified file 'plugins/ArchaeoLines/src/gui/ArchaeoLinesDialog.cpp' |
510 | --- plugins/ArchaeoLines/src/gui/ArchaeoLinesDialog.cpp 2016-01-22 11:05:08 +0000 |
511 | +++ plugins/ArchaeoLines/src/gui/ArchaeoLinesDialog.cpp 2016-06-03 22:29:41 +0000 |
512 | @@ -90,7 +90,8 @@ |
513 | ui->currentMoonCheckBox->setChecked(al->isCurrentMoonDisplayed()); |
514 | connect(ui->currentMoonCheckBox, SIGNAL(toggled(bool)), al, SLOT(showCurrentMoon(bool))); |
515 | // Planet ComboBox requires special handling! |
516 | - ui->currentPlanetComboBox->setCurrentIndex(al->whichCurrentPlanetDisplayed()-ArchaeoLine::CurrentPlanetNone); |
517 | + setCurrentPlanetFromApp(); |
518 | + connect(al, SIGNAL(currentPlanetChanged(ArchaeoLine::Line)), this, SLOT(setCurrentPlanetFromApp())); |
519 | connect(ui->currentPlanetComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setCurrentPlanetFromGUI(int))); |
520 | |
521 | equinoxColor = al->getLineColor(ArchaeoLine::Equinox); |
522 | @@ -177,6 +178,12 @@ |
523 | al->showCurrentPlanet((ArchaeoLine::Line) (ArchaeoLine::CurrentPlanetNone+index)); |
524 | } |
525 | |
526 | +void ArchaeoLinesDialog::setCurrentPlanetFromApp() |
527 | +{ |
528 | + Q_ASSERT(al); |
529 | + ui->currentPlanetComboBox->setCurrentIndex(al->whichCurrentPlanetDisplayed()-ArchaeoLine::CurrentPlanetNone); |
530 | +} |
531 | + |
532 | |
533 | void ArchaeoLinesDialog::setAboutHtml(void) |
534 | { |
535 | |
536 | === modified file 'plugins/ArchaeoLines/src/gui/ArchaeoLinesDialog.hpp' |
537 | --- plugins/ArchaeoLines/src/gui/ArchaeoLinesDialog.hpp 2015-05-30 19:56:47 +0000 |
538 | +++ plugins/ArchaeoLines/src/gui/ArchaeoLinesDialog.hpp 2016-06-03 22:29:41 +0000 |
539 | @@ -103,6 +103,7 @@ |
540 | void resetArchaeoLinesSettings(); |
541 | //! setting planet requires a small function to link Combobox indices to line IDs. |
542 | void setCurrentPlanetFromGUI(int index); |
543 | + void setCurrentPlanetFromApp(); |
544 | |
545 | }; |
546 | |
547 | |
548 | === modified file 'plugins/Oculars/src/Oculars.cpp' |
549 | --- plugins/Oculars/src/Oculars.cpp 2016-05-12 05:51:25 +0000 |
550 | +++ plugins/Oculars/src/Oculars.cpp 2016-06-03 22:29:41 +0000 |
551 | @@ -124,7 +124,7 @@ |
552 | flagMoonScale(false), |
553 | maxEyepieceAngle(0.0), |
554 | requireSelection(true), |
555 | - flagLimitMagnitude(false), |
556 | + flagLimitMagnitude(false), |
557 | useMaxEyepieceAngle(true), |
558 | guiPanelEnabled(false), |
559 | flagDecimalDegrees(false), |
560 | @@ -256,7 +256,7 @@ |
561 | lens->writeToSettings(settings, index); |
562 | index++; |
563 | } |
564 | - |
565 | + |
566 | settings->setValue("ocular_count", oculars.count()); |
567 | settings->setValue("telescope_count", telescopes.count()); |
568 | settings->setValue("ccd_count", ccds.count()); |
569 | @@ -281,22 +281,22 @@ |
570 | if (selectedCCDIndex > ccds.count()) |
571 | { |
572 | qWarning() << "Oculars: the selected sensor index of " |
573 | - << selectedCCDIndex << " is greater than the sensor count of " |
574 | - << ccds.count() << ". Module disabled!"; |
575 | + << selectedCCDIndex << " is greater than the sensor count of " |
576 | + << ccds.count() << ". Module disabled!"; |
577 | ready = false; |
578 | } |
579 | if (selectedOcularIndex > oculars.count()) |
580 | { |
581 | qWarning() << "Oculars: the selected ocular index of " |
582 | - << selectedOcularIndex << " is greater than the ocular count of " |
583 | - << oculars.count() << ". Module disabled!"; |
584 | + << selectedOcularIndex << " is greater than the ocular count of " |
585 | + << oculars.count() << ". Module disabled!"; |
586 | ready = false; |
587 | } |
588 | else if (selectedTelescopeIndex > telescopes.count()) |
589 | { |
590 | qWarning() << "Oculars: the selected telescope index of " |
591 | - << selectedTelescopeIndex << " is greater than the telescope count of " |
592 | - << telescopes.count() << ". Module disabled!"; |
593 | + << selectedTelescopeIndex << " is greater than the telescope count of " |
594 | + << telescopes.count() << ". Module disabled!"; |
595 | ready = false; |
596 | } |
597 | |
598 | @@ -779,7 +779,7 @@ |
599 | } |
600 | } |
601 | guiPanelEnabled = enable; |
602 | - settings->setValue("enable_control_panel", enable); |
603 | + settings->setValue("enable_control_panel", enable); |
604 | settings->sync(); |
605 | } |
606 | |
607 | @@ -827,7 +827,7 @@ |
608 | if (oculars.isEmpty()) |
609 | { |
610 | selectedOcularIndex = -1; |
611 | - actionShowOcular->setChecked(false); |
612 | + enableOcular(false); |
613 | } |
614 | else |
615 | { |
616 | @@ -841,8 +841,8 @@ |
617 | if (telescopes.isEmpty()) |
618 | { |
619 | selectedTelescopeIndex = -1; |
620 | - actionShowOcular->setChecked(false); |
621 | - actionShowSensor->setChecked(false); |
622 | + enableOcular(false); |
623 | + toggleCCD(false); |
624 | } |
625 | else |
626 | { |
627 | @@ -856,7 +856,7 @@ |
628 | if (ccds.isEmpty()) |
629 | { |
630 | selectedCCDIndex = -1; |
631 | - actionShowSensor->setChecked(false); |
632 | + toggleCCD(false); |
633 | } |
634 | else |
635 | { |
636 | @@ -889,8 +889,7 @@ |
637 | // Close the sensor view if it's displayed |
638 | if (flagShowCCD) |
639 | { |
640 | - if (actionShowSensor->isChecked()) |
641 | - actionShowSensor->setChecked(false); |
642 | + toggleCCD(false); |
643 | flagShowCCD = false; |
644 | selectedCCDIndex = -1; |
645 | } |
646 | @@ -898,8 +897,7 @@ |
647 | // Close the Telrad sight if it's displayed |
648 | if (flagShowTelrad) |
649 | { |
650 | - if (actionShowTelrad->isChecked()) |
651 | - actionShowTelrad->setChecked(false); |
652 | + toggleTelrad(false); |
653 | } |
654 | |
655 | // Check to ensure that we have enough oculars & telescopes, as they may have been edited in the config dialog |
656 | @@ -948,10 +946,6 @@ |
657 | usageMessageLabelID = labelManager->labelScreen(labelText, xPosition, yPosition, |
658 | true, font.pixelSize(), tcolor); |
659 | } |
660 | - // we didn't accept the new status - make sure the toolbar button reflects this |
661 | - disconnect(actionShowOcular, SIGNAL(toggled(bool)), this, SLOT(enableOcular(bool))); |
662 | - actionShowOcular->setChecked(false); |
663 | - connect(actionShowOcular, SIGNAL(toggled(bool)), this, SLOT(enableOcular(bool))); |
664 | } |
665 | else |
666 | { |
667 | @@ -966,6 +960,8 @@ |
668 | guiPanel->showOcularGui(); |
669 | } |
670 | } |
671 | + |
672 | + emit enableOcularChanged(flagShowOculars); |
673 | } |
674 | |
675 | void Oculars::decrementCCDIndex() |
676 | @@ -1357,31 +1353,19 @@ |
677 | flagShowCCD = false; |
678 | selectedCCDIndex = -1; |
679 | show = false; |
680 | - if (actionShowSensor->isChecked()) |
681 | - { |
682 | - actionShowSensor->setChecked(false); |
683 | - } |
684 | } |
685 | |
686 | StelCore *core = StelApp::getInstance().getCore(); |
687 | - StelMovementMgr *movementManager = core->getMovementMgr(); |
688 | + StelMovementMgr *movementManager = core->getMovementMgr(); |
689 | if (show) |
690 | { |
691 | initialFOV = movementManager->getCurrentFov(); |
692 | //Mutually exclusive with the ocular mode |
693 | hideUsageMessageIfDisplayed(); |
694 | - if (flagShowOculars) |
695 | - { |
696 | - if (actionShowOcular->isChecked()) |
697 | - { |
698 | - actionShowOcular->setChecked(false); |
699 | - } |
700 | - } |
701 | + enableOcular(false); |
702 | |
703 | if (flagShowTelrad) { |
704 | - if (actionShowTelrad->isChecked()) { |
705 | - actionShowTelrad->setChecked(false); |
706 | - } |
707 | + toggleTelrad(false); |
708 | } |
709 | |
710 | if (selectedTelescopeIndex < 0) |
711 | @@ -1393,7 +1377,7 @@ |
712 | selectedCCDIndex = 0; |
713 | } |
714 | flagShowCCD = true; |
715 | - setScreenFOVForCCD(); |
716 | + setScreenFOVForCCD(); |
717 | |
718 | if (guiPanel) |
719 | { |
720 | @@ -1405,7 +1389,7 @@ |
721 | flagShowCCD = false; |
722 | |
723 | movementManager->setFlagTracking(false); |
724 | - //Zoom out |
725 | + //Zoom out |
726 | if (getFlagInitFovUsage()) |
727 | movementManager->zoomTo(movementManager->getInitFov()); |
728 | else |
729 | @@ -1422,51 +1406,42 @@ |
730 | guiPanel->foldGui(); |
731 | } |
732 | } |
733 | + |
734 | + emit enableCCDChanged(flagShowCCD); |
735 | } |
736 | |
737 | void Oculars::toggleCCD() |
738 | { |
739 | - if (flagShowCCD) |
740 | - { |
741 | - toggleCCD(false); |
742 | - } |
743 | - else |
744 | - { |
745 | - toggleCCD(true); |
746 | - } |
747 | + toggleCCD(!flagShowCCD); |
748 | } |
749 | |
750 | void Oculars::toggleCrosshairs(bool show) |
751 | { |
752 | - if (show && flagShowOculars) |
753 | - { |
754 | - flagShowCrosshairs = true; |
755 | - } |
756 | - else |
757 | - { |
758 | - flagShowCrosshairs = false; |
759 | + if(show != flagShowCrosshairs) |
760 | + { |
761 | + flagShowCrosshairs = show; |
762 | + emit enableCrosshairsChanged(show); |
763 | } |
764 | } |
765 | |
766 | void Oculars::toggleTelrad(bool show) |
767 | { |
768 | - if (show) |
769 | + if(show!=flagShowTelrad) |
770 | { |
771 | - hideUsageMessageIfDisplayed(); |
772 | - if (actionShowOcular->isChecked()) |
773 | - actionShowOcular->setChecked(false); |
774 | - if (actionShowSensor->isChecked()) |
775 | - actionShowSensor->setChecked(false); |
776 | + if (show) |
777 | + { |
778 | + hideUsageMessageIfDisplayed(); |
779 | + enableOcular(false); |
780 | + toggleCCD(false); |
781 | + } |
782 | + flagShowTelrad = show; |
783 | + emit enableTelradChanged(flagShowTelrad); |
784 | } |
785 | - flagShowTelrad = show; |
786 | } |
787 | |
788 | void Oculars::toggleTelrad() |
789 | { |
790 | - if (flagShowTelrad) |
791 | - toggleTelrad(false); |
792 | - else |
793 | - toggleTelrad(true); |
794 | + toggleTelrad(!flagShowTelrad); |
795 | } |
796 | |
797 | /* ****************************************************************************************************************** */ |
798 | @@ -1481,8 +1456,7 @@ |
799 | Q_ASSERT(gui); |
800 | |
801 | QString ocularsGroup = N_("Oculars"); |
802 | - actionShowOcular = addAction("actionShow_Ocular", ocularsGroup, N_("Ocular view"), "enableOcular(bool)", "Ctrl+O"); |
803 | - actionShowOcular->setChecked(flagShowOculars); |
804 | + actionShowOcular = addAction("actionShow_Ocular", ocularsGroup, N_("Ocular view"), "enableOcular", "Ctrl+O"); |
805 | // Make a toolbar button |
806 | try |
807 | { |
808 | @@ -1498,9 +1472,9 @@ |
809 | } |
810 | |
811 | actionMenu = addAction("actionShow_Ocular_Menu", ocularsGroup, N_("Oculars popup menu"), "displayPopupMenu()", "Alt+O"); |
812 | - actionShowCrosshairs = addAction("actionShow_Ocular_Crosshairs", ocularsGroup, N_("Show crosshairs"), "toggleCrosshairs(bool)", "Alt+C"); |
813 | - actionShowSensor = addAction("actionShow_Sensor", ocularsGroup, N_("Image sensor frame"), "toggleCCD(bool)"); |
814 | - actionShowTelrad = addAction("actionShow_Telrad", ocularsGroup, N_("Telrad sight"), "toggleTelrad(bool)", "Ctrl+B"); |
815 | + actionShowCrosshairs = addAction("actionShow_Ocular_Crosshairs", ocularsGroup, N_("Show crosshairs"), "enableCrosshairs", "Alt+C"); |
816 | + actionShowSensor = addAction("actionShow_Sensor", ocularsGroup, N_("Image sensor frame"), "enableCCD"); |
817 | + actionShowTelrad = addAction("actionShow_Telrad", ocularsGroup, N_("Telrad sight"), "enableTelrad", "Ctrl+B"); |
818 | actionConfiguration = addAction("actionOpen_Oculars_Configuration", ocularsGroup, N_("Oculars plugin configuration"), ocularDialog, "visible"); |
819 | // Select next telescope via keyboard |
820 | addAction("actionShow_Telescope_Increment", ocularsGroup, N_("Select next telescope"), "incrementTelescopeIndex()", ""); |
821 | @@ -1544,11 +1518,11 @@ |
822 | |
823 | void Oculars::paintCCDBounds() |
824 | { |
825 | - StelCore *core = StelApp::getInstance().getCore(); |
826 | + StelCore *core = StelApp::getInstance().getCore(); |
827 | StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams(); |
828 | Lens *lens = selectedLensIndex >=0 ? lense[selectedLensIndex] : NULL; |
829 | |
830 | - const StelProjectorP projector = core->getProjection(StelCore::FrameEquinoxEqu); |
831 | + const StelProjectorP projector = core->getProjection(StelCore::FrameEquinoxEqu); |
832 | double screenFOV = params.fov; |
833 | |
834 | // draw sensor rectangle |
835 | @@ -1636,9 +1610,9 @@ |
836 | |
837 | //painter.setColor(0.60f, 0.20f, 0.20f, .5f); |
838 | painter.drawCircle(params.viewportCenter[0] * params.devicePixelsPerPixel, |
839 | - params.viewportCenter[1] * params.devicePixelsPerPixel, in_oag_r); |
840 | + params.viewportCenter[1] * params.devicePixelsPerPixel, in_oag_r); |
841 | painter.drawCircle(params.viewportCenter[0] * params.devicePixelsPerPixel, |
842 | - params.viewportCenter[1] * params.devicePixelsPerPixel, out_oag_r); |
843 | + params.viewportCenter[1] * params.devicePixelsPerPixel, out_oag_r); |
844 | |
845 | QTransform oag_transform = QTransform().translate(params.viewportCenter[0] * params.devicePixelsPerPixel, |
846 | params.viewportCenter[1] * params.devicePixelsPerPixel).rotate(-(ccd->chipRotAngle() + polarAngle + ccd->prismPosAngle())); |
847 | @@ -1774,8 +1748,8 @@ |
848 | reticleTexture->getDimensions(textureWidth, textureHeight); |
849 | |
850 | painter.drawSprite2dMode(params.viewportXywh[2] / 2 * params.devicePixelsPerPixel, |
851 | - params.viewportXywh[3] / 2 * params.devicePixelsPerPixel, |
852 | - inner, reticleRotation); |
853 | + params.viewportXywh[3] / 2 * params.devicePixelsPerPixel, |
854 | + inner, reticleRotation); |
855 | } |
856 | |
857 | if (oculars[selectedOcularIndex]->hasPermanentCrosshair()) |
858 | @@ -1833,7 +1807,7 @@ |
859 | void Oculars::paintText(const StelCore* core) |
860 | { |
861 | const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz); |
862 | - StelPainter painter(prj); |
863 | + StelPainter painter(prj); |
864 | |
865 | // Get the current instruments |
866 | CCD *ccd = NULL; |
867 | @@ -1910,7 +1884,7 @@ |
868 | QString ocularFOVLabel = QString(q_("Ocular aFOV: %1")).arg(ocularFov); |
869 | painter.drawText(xPosition, yPosition, ocularFOVLabel); |
870 | yPosition-=lineHeight; |
871 | - |
872 | + |
873 | QString lensNumberLabel; |
874 | // Barlow and Shapley lens |
875 | if (lens != NULL) // it's null if lens is not selected (lens index = -1) |
876 | @@ -1931,7 +1905,7 @@ |
877 | } |
878 | painter.drawText(xPosition, yPosition, lensNumberLabel); |
879 | yPosition-=lineHeight; |
880 | - |
881 | + |
882 | // The telescope |
883 | QString telescopeString = ""; |
884 | QString magString = ""; |
885 | @@ -2002,7 +1976,7 @@ |
886 | .arg(name); |
887 | } |
888 | // The telescope |
889 | - QString telescopeNumberLabel; |
890 | + QString telescopeNumberLabel; |
891 | if (telescopeName.isEmpty()) |
892 | { |
893 | telescopeNumberLabel = QString(q_("Telescope #%1")) |
894 | @@ -2039,7 +2013,7 @@ |
895 | if (!src.copy(ocularIniPath)) |
896 | { |
897 | qWarning() << "Oculars::validateIniFile cannot copy default_ocular.ini resource to [non-existing] " |
898 | - + ocularIniPath; |
899 | + + ocularIniPath; |
900 | } |
901 | else |
902 | { |
903 | @@ -2242,7 +2216,7 @@ |
904 | } |
905 | telescope = telescopes[selectedTelescopeIndex]; |
906 | core->setFlipHorz(telescope->isHFlipped()); |
907 | - core->setFlipVert(telescope->isVFlipped()); |
908 | + core->setFlipVert(telescope->isVFlipped()); |
909 | } |
910 | |
911 | // Limit stars and DSOs if it enable and it's telescope + eyepiece combination |
912 | @@ -2289,7 +2263,7 @@ |
913 | QMenu* Oculars::addLensSubmenu(QMenu* parent) |
914 | { |
915 | Q_ASSERT(parent); |
916 | - |
917 | + |
918 | QMenu *submenu = new QMenu(q_("&Lens"), parent); |
919 | submenu->addAction(q_("&Previous lens"), this, SLOT(decrementLensIndex())); |
920 | submenu->addAction(q_("&Next lens"), this, SLOT(incrementLensIndex())); |
921 | @@ -2352,7 +2326,7 @@ |
922 | void Oculars::setFlagDecimalDegrees(const bool b) |
923 | { |
924 | flagDecimalDegrees = b; |
925 | - settings->setValue("use_decimal_degrees", b); |
926 | + settings->setValue("use_decimal_degrees", b); |
927 | settings->sync(); |
928 | } |
929 | |
930 | |
931 | === modified file 'plugins/Oculars/src/Oculars.hpp' |
932 | --- plugins/Oculars/src/Oculars.hpp 2016-03-06 17:02:08 +0000 |
933 | +++ plugins/Oculars/src/Oculars.hpp 2016-06-03 22:29:41 +0000 |
934 | @@ -75,6 +75,12 @@ |
935 | class Oculars : public StelModule |
936 | { |
937 | Q_OBJECT |
938 | + |
939 | + Q_PROPERTY(bool enableOcular READ getEnableOcular WRITE enableOcular NOTIFY enableOcularChanged) |
940 | + Q_PROPERTY(bool enableCrosshairs READ getEnableCrosshairs WRITE toggleCrosshairs NOTIFY enableCrosshairsChanged) |
941 | + Q_PROPERTY(bool enableCCD READ getEnableCCD WRITE toggleCCD NOTIFY enableCCDChanged) |
942 | + Q_PROPERTY(bool enableTelrad READ getEnableTelrad WRITE toggleTelrad NOTIFY enableTelradChanged) |
943 | + |
944 | //BM: Temporary, until the GUI is finalized and some other method of getting |
945 | //info from the main class is implemented. |
946 | friend class OcularsGuiPanel; |
947 | @@ -119,6 +125,7 @@ |
948 | //! This method is called with we detect that our hot key is pressed. It handles |
949 | //! determining if we should do anything - based on a selected object. |
950 | void enableOcular(bool b); |
951 | + bool getEnableOcular() const { return flagShowOculars; } |
952 | void incrementCCDIndex(); |
953 | void incrementOcularIndex(); |
954 | void incrementTelescopeIndex(); |
955 | @@ -133,9 +140,12 @@ |
956 | void toggleCCD(bool show); |
957 | //! Toggles the sensor frame overlay (overloaded for blind switching). |
958 | void toggleCCD(); |
959 | + bool getEnableCCD() const { return flagShowCCD; } |
960 | void toggleCrosshairs(bool show = true); |
961 | + bool getEnableCrosshairs() const { return flagShowCrosshairs; } |
962 | //! Toggles the Telrad sight overlay. |
963 | void toggleTelrad(bool show); |
964 | + bool getEnableTelrad() const { return flagShowTelrad; } |
965 | //! Toggles the Telrad sight overlay (overloaded for blind switching). |
966 | void toggleTelrad(); |
967 | void enableGuiPanel(bool enable = true); |
968 | @@ -156,6 +166,10 @@ |
969 | bool getFlagUseSemiTransparency(void) const; |
970 | |
971 | signals: |
972 | + void enableOcularChanged(bool value); |
973 | + void enableCrosshairsChanged(bool value); |
974 | + void enableCCDChanged(bool value); |
975 | + void enableTelradChanged(bool value); |
976 | void selectedCCDChanged(); |
977 | void selectedOcularChanged(); |
978 | void selectedTelescopeChanged(); |
979 | @@ -166,7 +180,7 @@ |
980 | void instrumentChanged(); |
981 | void determineMaxEyepieceAngle(); |
982 | void setRequireSelection(bool state); |
983 | - void setScaleImageCircle(bool state); |
984 | + void setScaleImageCircle(bool state); |
985 | void setScreenFOVForCCD(); |
986 | void retranslateGui(); |
987 | void setStelStyle(const QString& style); |
988 | |
989 | === modified file 'plugins/Oculars/src/gui/OcularsGuiPanel.cpp' |
990 | --- plugins/Oculars/src/gui/OcularsGuiPanel.cpp 2016-03-04 15:04:20 +0000 |
991 | +++ plugins/Oculars/src/gui/OcularsGuiPanel.cpp 2016-06-03 22:29:41 +0000 |
992 | @@ -37,8 +37,8 @@ |
993 | #include <QWidget> |
994 | |
995 | OcularsGuiPanel::OcularsGuiPanel(Oculars* plugin, |
996 | - QGraphicsWidget *parent, |
997 | - Qt::WindowFlags wFlags): |
998 | + QGraphicsWidget *parent, |
999 | + Qt::WindowFlags wFlags): |
1000 | QGraphicsWidget(parent, wFlags), |
1001 | ocularsPlugin(plugin), |
1002 | parentWidget(parent), |
1003 | @@ -58,56 +58,49 @@ |
1004 | StelApp& stelApp = StelApp::getInstance(); |
1005 | Q_ASSERT(ocularsPlugin->actionShowOcular); |
1006 | buttonOcular = new StelButton(buttonBar, |
1007 | - QPixmap(":/ocular/bt_ocular_on.png"), |
1008 | - QPixmap(":/ocular/bt_ocular_off.png"), |
1009 | - QPixmap(), |
1010 | - ocularsPlugin->actionShowOcular, |
1011 | - true); //No background |
1012 | + QPixmap(":/ocular/bt_ocular_on.png"), |
1013 | + QPixmap(":/ocular/bt_ocular_off.png"), |
1014 | + QPixmap(), |
1015 | + ocularsPlugin->actionShowOcular, |
1016 | + true); //No background |
1017 | buttonOcular->setToolTip(ocularsPlugin->actionShowOcular->getText()); |
1018 | buttonOcular->setParentItem(buttonBar); |
1019 | |
1020 | - //Hack to avoid buttonOcular being left "checked" if it has been toggled |
1021 | - //without any object selected. |
1022 | - disconnect(ocularsPlugin->actionShowOcular, SIGNAL(toggled(bool)), |
1023 | - ocularsPlugin, SLOT(enableOcular(bool))); |
1024 | - connect(ocularsPlugin->actionShowOcular, SIGNAL(toggled(bool)), |
1025 | - ocularsPlugin, SLOT(enableOcular(bool))); |
1026 | - |
1027 | Q_ASSERT(ocularsPlugin->actionShowCrosshairs); |
1028 | buttonCrosshairs = new StelButton(buttonBar, |
1029 | - QPixmap(":/ocular/bt_crosshairs_on.png"), |
1030 | - QPixmap(":/ocular/bt_crosshairs_off.png"), |
1031 | - QPixmap(), |
1032 | - ocularsPlugin->actionShowCrosshairs, |
1033 | - true); |
1034 | + QPixmap(":/ocular/bt_crosshairs_on.png"), |
1035 | + QPixmap(":/ocular/bt_crosshairs_off.png"), |
1036 | + QPixmap(), |
1037 | + ocularsPlugin->actionShowCrosshairs, |
1038 | + true); |
1039 | buttonCrosshairs->setToolTip(ocularsPlugin->actionShowCrosshairs->getText()); |
1040 | buttonCrosshairs->setVisible(false); |
1041 | |
1042 | Q_ASSERT(ocularsPlugin->actionShowSensor); |
1043 | buttonCcd = new StelButton(buttonBar, |
1044 | - QPixmap(":/ocular/bt_sensor_on.png"), |
1045 | - QPixmap(":/ocular/bt_sensor_off.png"), |
1046 | - QPixmap(), |
1047 | - ocularsPlugin->actionShowSensor, |
1048 | - true); |
1049 | + QPixmap(":/ocular/bt_sensor_on.png"), |
1050 | + QPixmap(":/ocular/bt_sensor_off.png"), |
1051 | + QPixmap(), |
1052 | + ocularsPlugin->actionShowSensor, |
1053 | + true); |
1054 | buttonCcd->setToolTip(ocularsPlugin->actionShowSensor->getText()); |
1055 | |
1056 | Q_ASSERT(ocularsPlugin->actionShowTelrad); |
1057 | buttonTelrad = new StelButton(buttonBar, |
1058 | - QPixmap(":/ocular/bt_telrad_on.png"), |
1059 | - QPixmap(":/ocular/bt_telrad_off.png"), |
1060 | - QPixmap(), |
1061 | - ocularsPlugin->actionShowTelrad, |
1062 | - true); |
1063 | + QPixmap(":/ocular/bt_telrad_on.png"), |
1064 | + QPixmap(":/ocular/bt_telrad_off.png"), |
1065 | + QPixmap(), |
1066 | + ocularsPlugin->actionShowTelrad, |
1067 | + true); |
1068 | buttonTelrad->setToolTip(ocularsPlugin->actionShowTelrad->getText()); |
1069 | |
1070 | Q_ASSERT(ocularsPlugin->actionConfiguration); |
1071 | buttonConfiguration = new StelButton(buttonBar, |
1072 | - QPixmap(":/ocular/bt_settings_on.png"), |
1073 | - QPixmap(":/ocular/bt_settings_off.png"), |
1074 | - QPixmap(), |
1075 | - ocularsPlugin->actionConfiguration, |
1076 | - true); |
1077 | + QPixmap(":/ocular/bt_settings_on.png"), |
1078 | + QPixmap(":/ocular/bt_settings_off.png"), |
1079 | + QPixmap(), |
1080 | + ocularsPlugin->actionConfiguration, |
1081 | + true); |
1082 | buttonConfiguration->setToolTip(ocularsPlugin->actionConfiguration->getText()); |
1083 | |
1084 | qreal buttonHeight = buttonOcular->boundingRect().height(); |
1085 | @@ -179,73 +172,63 @@ |
1086 | QPixmap naOff(":/graphicGui/btTimeForward-off.png"); |
1087 | QPixmap nextArrowOff = naOff.scaledToHeight(scale, Qt::SmoothTransformation); |
1088 | |
1089 | - StelAction* defaultAction = new StelAction(this); |
1090 | - defaultAction->setCheckable(false); |
1091 | prevOcularButton = new StelButton(ocularControls, |
1092 | - prevArrow, |
1093 | - prevArrowOff, |
1094 | - QPixmap(), |
1095 | - defaultAction); |
1096 | + prevArrow, |
1097 | + prevArrowOff, |
1098 | + QPixmap()); |
1099 | prevOcularButton->setToolTip(q_("Previous ocular")); |
1100 | nextOcularButton = new StelButton(ocularControls, |
1101 | - nextArrow, |
1102 | - nextArrowOff, |
1103 | - QPixmap(), |
1104 | - defaultAction); |
1105 | + nextArrow, |
1106 | + nextArrowOff, |
1107 | + QPixmap()); |
1108 | nextOcularButton->setToolTip(q_("Next ocular")); |
1109 | prevLensButton = new StelButton(lensControls, |
1110 | - prevArrow, |
1111 | - prevArrowOff, |
1112 | - QPixmap(), |
1113 | - defaultAction); |
1114 | + prevArrow, |
1115 | + prevArrowOff, |
1116 | + QPixmap()); |
1117 | prevLensButton->setToolTip(q_("Previous lens")); |
1118 | nextLensButton = new StelButton(lensControls, |
1119 | - nextArrow, |
1120 | - nextArrowOff, |
1121 | - QPixmap(), |
1122 | - defaultAction); |
1123 | + nextArrow, |
1124 | + nextArrowOff, |
1125 | + QPixmap()); |
1126 | nextLensButton->setToolTip(q_("Next lens")); |
1127 | prevCcdButton = new StelButton(ccdControls, |
1128 | - prevArrow, |
1129 | - prevArrowOff, |
1130 | - QPixmap(), |
1131 | - defaultAction); |
1132 | + prevArrow, |
1133 | + prevArrowOff, |
1134 | + QPixmap()); |
1135 | prevCcdButton->setToolTip(q_("Previous CCD frame")); |
1136 | nextCcdButton = new StelButton(ccdControls, |
1137 | - nextArrow, |
1138 | - nextArrowOff, |
1139 | - QPixmap(), |
1140 | - defaultAction); |
1141 | + nextArrow, |
1142 | + nextArrowOff, |
1143 | + QPixmap()); |
1144 | nextCcdButton->setToolTip(q_("Next CCD frame")); |
1145 | prevTelescopeButton = new StelButton(telescopeControls, |
1146 | - prevArrow, |
1147 | - prevArrowOff, |
1148 | - QPixmap(), |
1149 | - defaultAction); |
1150 | + prevArrow, |
1151 | + prevArrowOff, |
1152 | + QPixmap()); |
1153 | prevTelescopeButton->setToolTip(q_("Previous telescope")); |
1154 | nextTelescopeButton = new StelButton(telescopeControls, |
1155 | - nextArrow, |
1156 | - nextArrowOff, |
1157 | - QPixmap(), |
1158 | - defaultAction); |
1159 | + nextArrow, |
1160 | + nextArrowOff, |
1161 | + QPixmap()); |
1162 | nextTelescopeButton->setToolTip(q_("Next telescope")); |
1163 | |
1164 | connect(nextOcularButton, SIGNAL(triggered()), |
1165 | - ocularsPlugin, SLOT(incrementOcularIndex())); |
1166 | + ocularsPlugin, SLOT(incrementOcularIndex())); |
1167 | connect(nextCcdButton, SIGNAL(triggered()), |
1168 | - ocularsPlugin, SLOT(incrementCCDIndex())); |
1169 | + ocularsPlugin, SLOT(incrementCCDIndex())); |
1170 | connect(nextTelescopeButton, SIGNAL(triggered()), |
1171 | - ocularsPlugin, SLOT(incrementTelescopeIndex())); |
1172 | + ocularsPlugin, SLOT(incrementTelescopeIndex())); |
1173 | connect(prevOcularButton, SIGNAL(triggered()), |
1174 | - ocularsPlugin, SLOT(decrementOcularIndex())); |
1175 | + ocularsPlugin, SLOT(decrementOcularIndex())); |
1176 | connect(prevCcdButton, SIGNAL(triggered()), |
1177 | - ocularsPlugin, SLOT(decrementCCDIndex())); |
1178 | + ocularsPlugin, SLOT(decrementCCDIndex())); |
1179 | connect(prevTelescopeButton, SIGNAL(triggered()), |
1180 | - ocularsPlugin, SLOT(decrementTelescopeIndex())); |
1181 | + ocularsPlugin, SLOT(decrementTelescopeIndex())); |
1182 | connect(nextLensButton, SIGNAL(triggered()), |
1183 | - ocularsPlugin, SLOT(incrementLensIndex())); |
1184 | + ocularsPlugin, SLOT(incrementLensIndex())); |
1185 | connect(prevLensButton, SIGNAL(triggered()), |
1186 | - ocularsPlugin, SLOT(decrementLensIndex())); |
1187 | + ocularsPlugin, SLOT(decrementLensIndex())); |
1188 | |
1189 | QColor cOn(255, 255, 255); |
1190 | QColor cOff(102, 102, 102); |
1191 | @@ -256,11 +239,11 @@ |
1192 | QPixmap pOff = createPixmapFromText(degrees, degreesW, lineHeight, newFont, cOff); |
1193 | QPixmap pHover = createPixmapFromText(degrees, degreesW, lineHeight, newFont, cHover); |
1194 | rotateCcdMinus15Button = new StelButton(ccdControls, |
1195 | - pOn, |
1196 | - pOff, |
1197 | - pHover, |
1198 | - defaultAction, |
1199 | - true); |
1200 | + pOn, |
1201 | + pOff, |
1202 | + pHover, |
1203 | + NULL, |
1204 | + true); |
1205 | rotateCcdMinus15Button->setToolTip(q_("Rotate the sensor frame 15 degrees counterclockwise")); |
1206 | |
1207 | degrees = QString("-5%1").arg(QChar(0x00B0)); |
1208 | @@ -269,10 +252,10 @@ |
1209 | pOff = createPixmapFromText(degrees, degreesW, lineHeight, newFont, cOff); |
1210 | pHover = createPixmapFromText(degrees, degreesW, lineHeight, newFont, cHover); |
1211 | rotateCcdMinus5Button = new StelButton(ccdControls, |
1212 | - pOn, |
1213 | - pOff, |
1214 | - pHover, |
1215 | - defaultAction, |
1216 | + pOn, |
1217 | + pOff, |
1218 | + pHover, |
1219 | + NULL, |
1220 | true); |
1221 | rotateCcdMinus5Button->setToolTip(q_("Rotate the sensor frame 5 degrees counterclockwise")); |
1222 | |
1223 | @@ -284,8 +267,8 @@ |
1224 | rotateCcdMinus1Button = new StelButton(ccdControls, |
1225 | pOn, |
1226 | pOff, |
1227 | - pHover, |
1228 | - defaultAction, |
1229 | + pHover, |
1230 | + NULL, |
1231 | true); |
1232 | rotateCcdMinus1Button->setToolTip(q_("Rotate the sensor frame 1 degree counterclockwise")); |
1233 | |
1234 | @@ -295,10 +278,10 @@ |
1235 | pOff = createPixmapFromText(degrees, degreesW, lineHeight, newFont, cOff); |
1236 | pHover = createPixmapFromText(degrees, degreesW, lineHeight, newFont, cHover); |
1237 | resetCcdRotationButton = new StelButton(ccdControls, |
1238 | - pOn, |
1239 | - pOff, |
1240 | - pHover, |
1241 | - defaultAction, |
1242 | + pOn, |
1243 | + pOff, |
1244 | + pHover, |
1245 | + NULL, |
1246 | true); |
1247 | resetCcdRotationButton->setToolTip(q_("Reset the sensor frame rotation")); |
1248 | |
1249 | @@ -311,7 +294,7 @@ |
1250 | pOn, |
1251 | pOff, |
1252 | pHover, |
1253 | - defaultAction, |
1254 | + NULL, |
1255 | true); |
1256 | rotateCcdPlus1Button->setToolTip(q_("Rotate the sensor frame 1 degree clockwise")); |
1257 | |
1258 | @@ -324,7 +307,7 @@ |
1259 | pOn, |
1260 | pOff, |
1261 | pHover, |
1262 | - defaultAction, |
1263 | + NULL, |
1264 | true); |
1265 | rotateCcdPlus5Button->setToolTip(q_("Rotate the sensor frame 5 degrees clockwise")); |
1266 | |
1267 | @@ -336,8 +319,8 @@ |
1268 | rotateCcdPlus15Button = new StelButton(ccdControls, |
1269 | pOn, |
1270 | pOff, |
1271 | - pHover, |
1272 | - defaultAction, |
1273 | + pHover, |
1274 | + NULL, |
1275 | true); |
1276 | rotateCcdPlus15Button->setToolTip(q_("Rotate the sensor frame 15 degrees clockwise")); |
1277 | |
1278 | @@ -350,34 +333,34 @@ |
1279 | sm->setMapping(rotateCcdPlus15Button, QString("15")); |
1280 | |
1281 | connect(rotateCcdMinus15Button, SIGNAL(triggered()), |
1282 | - sm, SLOT(map())); |
1283 | + sm, SLOT(map())); |
1284 | connect(rotateCcdMinus5Button, SIGNAL(triggered()), |
1285 | - sm, SLOT(map())); |
1286 | + sm, SLOT(map())); |
1287 | connect(rotateCcdMinus1Button, SIGNAL(triggered()), |
1288 | - sm, SLOT(map())); |
1289 | + sm, SLOT(map())); |
1290 | connect(rotateCcdPlus1Button, SIGNAL(triggered()), |
1291 | - sm, SLOT(map())); |
1292 | + sm, SLOT(map())); |
1293 | connect(rotateCcdPlus5Button, SIGNAL(triggered()), |
1294 | - sm, SLOT(map())); |
1295 | + sm, SLOT(map())); |
1296 | connect(rotateCcdPlus15Button, SIGNAL(triggered()), |
1297 | - sm, SLOT(map())); |
1298 | + sm, SLOT(map())); |
1299 | connect(resetCcdRotationButton, SIGNAL(triggered()), |
1300 | - ocularsPlugin, SLOT(ccdRotationReset())); |
1301 | + ocularsPlugin, SLOT(ccdRotationReset())); |
1302 | |
1303 | connect(rotateCcdMinus15Button, SIGNAL(triggered()), |
1304 | - this, SLOT(updateCcdControls())); |
1305 | + this, SLOT(updateCcdControls())); |
1306 | connect(rotateCcdMinus5Button, SIGNAL(triggered()), |
1307 | - this, SLOT(updateCcdControls())); |
1308 | + this, SLOT(updateCcdControls())); |
1309 | connect(rotateCcdMinus1Button, SIGNAL(triggered()), |
1310 | - this, SLOT(updateCcdControls())); |
1311 | + this, SLOT(updateCcdControls())); |
1312 | connect(rotateCcdPlus1Button, SIGNAL(triggered()), |
1313 | - this, SLOT(updateCcdControls())); |
1314 | + this, SLOT(updateCcdControls())); |
1315 | connect(rotateCcdPlus5Button, SIGNAL(triggered()), |
1316 | - this, SLOT(updateCcdControls())); |
1317 | + this, SLOT(updateCcdControls())); |
1318 | connect(rotateCcdPlus15Button, SIGNAL(triggered()), |
1319 | - this, SLOT(updateCcdControls())); |
1320 | + this, SLOT(updateCcdControls())); |
1321 | connect(resetCcdRotationButton, SIGNAL(triggered()), |
1322 | - this, SLOT(updateCcdControls())); |
1323 | + this, SLOT(updateCcdControls())); |
1324 | |
1325 | |
1326 | //Set the layout and update the size |
1327 | @@ -395,7 +378,7 @@ |
1328 | |
1329 | //Border/background for the widget |
1330 | borderPath = new QGraphicsPathItem(); |
1331 | - borderPath->setZValue(100); |
1332 | + borderPath->setZValue(100); |
1333 | QBrush borderBrush(QColor::fromRgbF(0.22, 0.22, 0.23, 0.2)); |
1334 | borderPath->setBrush(borderBrush); |
1335 | QPen borderPen = QPen(QColor::fromRgbF(0.7,0.7,0.7,0.5)); |
1336 | @@ -405,17 +388,17 @@ |
1337 | |
1338 | updatePosition(); |
1339 | connect (parentWidget, SIGNAL(geometryChanged()), |
1340 | - this, SLOT(updatePosition())); |
1341 | + this, SLOT(updatePosition())); |
1342 | |
1343 | //Connecting other slots |
1344 | connect(ocularsPlugin, SIGNAL(selectedOcularChanged()), |
1345 | - this, SLOT(updateOcularControls())); |
1346 | + this, SLOT(updateOcularControls())); |
1347 | connect(ocularsPlugin, SIGNAL(selectedCCDChanged()), |
1348 | - this, SLOT(updateCcdControls())); |
1349 | + this, SLOT(updateCcdControls())); |
1350 | connect(ocularsPlugin, SIGNAL(selectedTelescopeChanged()), |
1351 | - this, SLOT(updateTelescopeControls())); |
1352 | + this, SLOT(updateTelescopeControls())); |
1353 | connect(ocularsPlugin, SIGNAL(selectedLensChanged()), |
1354 | - this, SLOT(updateTelescopeControls())); |
1355 | + this, SLOT(updateTelescopeControls())); |
1356 | |
1357 | //Night mode |
1358 | connect(&stelApp, SIGNAL(colorSchemeChanged(const QString&)), |
1359 | @@ -479,7 +462,7 @@ |
1360 | QPointF verticalBorderStart = geometry().topLeft(); |
1361 | QPointF horizontalBorderEnd = geometry().bottomRight(); |
1362 | QPointF cornerArcStart(verticalBorderStart.x(), |
1363 | - horizontalBorderEnd.y() - cornerRadius); |
1364 | + horizontalBorderEnd.y() - cornerRadius); |
1365 | newBorderPath.moveTo(verticalBorderStart); |
1366 | newBorderPath.lineTo(cornerArcStart); |
1367 | newBorderPath.arcTo(cornerArcStart.x(), cornerArcStart.y(), cornerRadius, cornerRadius, 180, 90); |
1368 | @@ -552,7 +535,7 @@ |
1369 | QString apparentFovString = QString::number(apparentFov); |
1370 | apparentFovString.append(QChar(0x00B0));// Degree sign |
1371 | QString apparentFovLabel = QString(q_("Ocular aFOV: %1")) |
1372 | - .arg(apparentFovString); |
1373 | + .arg(apparentFovString); |
1374 | fieldOcularAfov->setPlainText(apparentFovLabel); |
1375 | fieldOcularAfov->setToolTip(q_("Apparent field of view of the ocular")); |
1376 | fieldOcularAfov->setPos(posX, posY); |
1377 | @@ -637,8 +620,8 @@ |
1378 | |
1379 | //Get the name |
1380 | int index = ocularsPlugin->selectedCCDIndex; |
1381 | - CCD* ccd = ocularsPlugin->ccds[index]; |
1382 | - Q_ASSERT(ccd); |
1383 | + CCD* ccd = ocularsPlugin->ccds[index]; |
1384 | + Q_ASSERT(ccd); |
1385 | QString name = ccd->name(); |
1386 | QString fullName; |
1387 | if (name.isEmpty()) |
1388 | @@ -801,7 +784,7 @@ |
1389 | posY = 0.; |
1390 | widgetHeight = 0.; |
1391 | |
1392 | - fieldMagnification->setToolTip(q_("Magnification provided by these binoculars")); |
1393 | + fieldMagnification->setToolTip(q_("Magnification provided by these binoculars")); |
1394 | fieldFov->setToolTip(q_("Actual field of view provided by these binoculars")); |
1395 | fieldExitPupil->setToolTip(q_("Exit pupil provided by these binoculars")); |
1396 | } |
1397 | @@ -811,15 +794,15 @@ |
1398 | nextTelescopeButton->setVisible(true); |
1399 | fieldTelescopeName->setVisible(true); |
1400 | |
1401 | - fieldMagnification->setToolTip(q_("Magnification provided by this ocular/lens/telescope combination")); |
1402 | + fieldMagnification->setToolTip(q_("Magnification provided by this ocular/lens/telescope combination")); |
1403 | fieldFov->setToolTip(q_("Actual field of view provided by this ocular/lens/telescope combination")); |
1404 | fieldExitPupil->setToolTip(q_("Exit pupil provided by this ocular/lens/telescope combination")); |
1405 | } |
1406 | |
1407 | //WTF? Rounding? |
1408 | double magnification = ((int)(ocular->magnification(telescope, lens) * 10.0)) / 10.0; |
1409 | - QString magnificationString = QString::number(magnification); |
1410 | - magnificationString.append(QChar(0x00D7)); |
1411 | + QString magnificationString = QString::number(magnification); |
1412 | + magnificationString.append(QChar(0x00D7)); |
1413 | QString magnificationLabel = QString(q_("Magnification: %1")).arg(magnificationString); |
1414 | fieldMagnification->setPlainText(magnificationLabel); |
1415 | fieldMagnification->setPos(posX, posY); |
1416 | @@ -963,7 +946,7 @@ |
1417 | void OcularsGuiPanel::updateMainButtonsPositions() |
1418 | { |
1419 | Q_ASSERT(buttonOcular); |
1420 | - Q_ASSERT(buttonCrosshairs); |
1421 | + Q_ASSERT(buttonCrosshairs); |
1422 | Q_ASSERT(buttonCcd); |
1423 | Q_ASSERT(buttonTelrad); |
1424 | Q_ASSERT(buttonConfiguration); |
1425 | @@ -984,7 +967,7 @@ |
1426 | { |
1427 | qreal parentWidth = buttonOcular->parentItem()->boundingRect().width(); |
1428 | int nGaps = n - 1;//n buttons have n-1 gaps |
1429 | - spacing = qRound((parentWidth-width)/nGaps); |
1430 | + spacing = qRound((parentWidth-width)/nGaps); |
1431 | } |
1432 | buttonOcular->setPos(posX, posY); |
1433 | posX += buttonOcular->getButtonPixmapWidth() + spacing; |
1434 | @@ -1067,11 +1050,11 @@ |
1435 | } |
1436 | |
1437 | QPixmap OcularsGuiPanel::createPixmapFromText(const QString& text, |
1438 | - int width, |
1439 | - int height, |
1440 | - const QFont& font, |
1441 | - const QColor& textColor, |
1442 | - const QColor& backgroundColor) |
1443 | + int width, |
1444 | + int height, |
1445 | + const QFont& font, |
1446 | + const QColor& textColor, |
1447 | + const QColor& backgroundColor) |
1448 | { |
1449 | if (width <= 0 || height <=0) { |
1450 | return QPixmap(); |
1451 | @@ -1088,8 +1071,8 @@ |
1452 | painter.setFont(font); |
1453 | painter.setPen(QPen(textColor)); |
1454 | painter.drawText(0, 0, width, height, |
1455 | - Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, |
1456 | - text); |
1457 | + Qt::AlignHCenter | Qt::AlignVCenter | Qt::TextSingleLine, |
1458 | + text); |
1459 | |
1460 | return pixmap; |
1461 | } |
1462 | |
1463 | === added directory 'plugins/RemoteControl' |
1464 | === added file 'plugins/RemoteControl/CMakeLists.txt' |
1465 | --- plugins/RemoteControl/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1466 | +++ plugins/RemoteControl/CMakeLists.txt 2016-06-03 22:29:41 +0000 |
1467 | @@ -0,0 +1,46 @@ |
1468 | +# This is the cmake config file for the RemoteControl plugin |
1469 | +SET(REMOTECONTROL_VERSION "0.0.1") |
1470 | +ADD_DEFINITIONS(-DREMOTECONTROL_VERSION="${REMOTECONTROL_VERSION}") |
1471 | +SET(REMOTECONTROL_WEBROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/webroot/") |
1472 | +ADD_DEFINITIONS(-DREMOTECONTROL_WEBROOT_PATH="${REMOTECONTROL_WEBROOT_PATH}") |
1473 | + |
1474 | +ADD_SUBDIRECTORY( src ) |
1475 | + |
1476 | +# Custom target for updating the translationdata.js |
1477 | +find_package(PythonInterp) |
1478 | + |
1479 | +if(PYTHON_EXECUTABLE) |
1480 | + add_custom_target(RemoteControl-update-translationdata |
1481 | + COMMAND ${PYTHON_EXECUTABLE} util/update_translationdata.py |
1482 | + ${PROJECT_SOURCE_DIR}/po/stellarium-remotecontrol/stellarium-remotecontrol-js.pot ${REMOTECONTROL_WEBROOT_PATH}/js/translationdata.js |
1483 | + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} |
1484 | + COMMENT "Updating RemoteControl translation data" |
1485 | + VERBATIM |
1486 | + ) |
1487 | + |
1488 | + add_dependencies(RemoteControl-update-translationdata generate-pot-stellarium-remotecontrol-js) |
1489 | +endif() |
1490 | + |
1491 | +IF(APPLE) |
1492 | + SET(CMAKE_INSTALL_PREFIX $ENV{HOME}/Library/Application\ Support/Stellarium) |
1493 | +ElSE(APPLE) |
1494 | + SET(CMAKE_INSTALL_PREFIX $ENV{HOME}/.stellarium) |
1495 | +ENDIF(APPLE) |
1496 | +INSTALL(FILES DESTINATION "modules/RemoteControl") |
1497 | + |
1498 | + |
1499 | +########### install files ############### |
1500 | +# install webroot |
1501 | +INSTALL(DIRECTORY ${REMOTECONTROL_WEBROOT_PATH} DESTINATION share/${PACKAGE}/webroot FILES_MATCHING |
1502 | + PATTERN "*.png" |
1503 | + PATTERN "*.gif" |
1504 | + PATTERN "*.html" |
1505 | + PATTERN "*.js" |
1506 | + PATTERN "*.css" |
1507 | + PATTERN "*.eot" |
1508 | + PATTERN "*.svg" |
1509 | + PATTERN "*.ttf" |
1510 | + PATTERN "*.woff" |
1511 | + PATTERN "*.woff2" |
1512 | + PATTERN "translate_files" |
1513 | + PATTERN "*.ico") |
1514 | \ No newline at end of file |
1515 | |
1516 | === added file 'plugins/RemoteControl/COPYING' |
1517 | --- plugins/RemoteControl/COPYING 1970-01-01 00:00:00 +0000 |
1518 | +++ plugins/RemoteControl/COPYING 2016-06-03 22:29:41 +0000 |
1519 | @@ -0,0 +1,340 @@ |
1520 | + GNU GENERAL PUBLIC LICENSE |
1521 | + Version 2, June 1991 |
1522 | + |
1523 | + Copyright (C) 1989, 1991 Free Software Foundation, Inc. |
1524 | + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
1525 | + Everyone is permitted to copy and distribute verbatim copies |
1526 | + of this license document, but changing it is not allowed. |
1527 | + |
1528 | + Preamble |
1529 | + |
1530 | + The licenses for most software are designed to take away your |
1531 | +freedom to share and change it. By contrast, the GNU General Public |
1532 | +License is intended to guarantee your freedom to share and change free |
1533 | +software--to make sure the software is free for all its users. This |
1534 | +General Public License applies to most of the Free Software |
1535 | +Foundation's software and to any other program whose authors commit to |
1536 | +using it. (Some other Free Software Foundation software is covered by |
1537 | +the GNU Library General Public License instead.) You can apply it to |
1538 | +your programs, too. |
1539 | + |
1540 | + When we speak of free software, we are referring to freedom, not |
1541 | +price. Our General Public Licenses are designed to make sure that you |
1542 | +have the freedom to distribute copies of free software (and charge for |
1543 | +this service if you wish), that you receive source code or can get it |
1544 | +if you want it, that you can change the software or use pieces of it |
1545 | +in new free programs; and that you know you can do these things. |
1546 | + |
1547 | + To protect your rights, we need to make restrictions that forbid |
1548 | +anyone to deny you these rights or to ask you to surrender the rights. |
1549 | +These restrictions translate to certain responsibilities for you if you |
1550 | +distribute copies of the software, or if you modify it. |
1551 | + |
1552 | + For example, if you distribute copies of such a program, whether |
1553 | +gratis or for a fee, you must give the recipients all the rights that |
1554 | +you have. You must make sure that they, too, receive or can get the |
1555 | +source code. And you must show them these terms so they know their |
1556 | +rights. |
1557 | + |
1558 | + We protect your rights with two steps: (1) copyright the software, and |
1559 | +(2) offer you this license which gives you legal permission to copy, |
1560 | +distribute and/or modify the software. |
1561 | + |
1562 | + Also, for each author's protection and ours, we want to make certain |
1563 | +that everyone understands that there is no warranty for this free |
1564 | +software. If the software is modified by someone else and passed on, we |
1565 | +want its recipients to know that what they have is not the original, so |
1566 | +that any problems introduced by others will not reflect on the original |
1567 | +authors' reputations. |
1568 | + |
1569 | + Finally, any free program is threatened constantly by software |
1570 | +patents. We wish to avoid the danger that redistributors of a free |
1571 | +program will individually obtain patent licenses, in effect making the |
1572 | +program proprietary. To prevent this, we have made it clear that any |
1573 | +patent must be licensed for everyone's free use or not licensed at all. |
1574 | + |
1575 | + The precise terms and conditions for copying, distribution and |
1576 | +modification follow. |
1577 | + |
1578 | |
1579 | + GNU GENERAL PUBLIC LICENSE |
1580 | + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
1581 | + |
1582 | + 0. This License applies to any program or other work which contains |
1583 | +a notice placed by the copyright holder saying it may be distributed |
1584 | +under the terms of this General Public License. The "Program", below, |
1585 | +refers to any such program or work, and a "work based on the Program" |
1586 | +means either the Program or any derivative work under copyright law: |
1587 | +that is to say, a work containing the Program or a portion of it, |
1588 | +either verbatim or with modifications and/or translated into another |
1589 | +language. (Hereinafter, translation is included without limitation in |
1590 | +the term "modification".) Each licensee is addressed as "you". |
1591 | + |
1592 | +Activities other than copying, distribution and modification are not |
1593 | +covered by this License; they are outside its scope. The act of |
1594 | +running the Program is not restricted, and the output from the Program |
1595 | +is covered only if its contents constitute a work based on the |
1596 | +Program (independent of having been made by running the Program). |
1597 | +Whether that is true depends on what the Program does. |
1598 | + |
1599 | + 1. You may copy and distribute verbatim copies of the Program's |
1600 | +source code as you receive it, in any medium, provided that you |
1601 | +conspicuously and appropriately publish on each copy an appropriate |
1602 | +copyright notice and disclaimer of warranty; keep intact all the |
1603 | +notices that refer to this License and to the absence of any warranty; |
1604 | +and give any other recipients of the Program a copy of this License |
1605 | +along with the Program. |
1606 | + |
1607 | +You may charge a fee for the physical act of transferring a copy, and |
1608 | +you may at your option offer warranty protection in exchange for a fee. |
1609 | + |
1610 | + 2. You may modify your copy or copies of the Program or any portion |
1611 | +of it, thus forming a work based on the Program, and copy and |
1612 | +distribute such modifications or work under the terms of Section 1 |
1613 | +above, provided that you also meet all of these conditions: |
1614 | + |
1615 | + a) You must cause the modified files to carry prominent notices |
1616 | + stating that you changed the files and the date of any change. |
1617 | + |
1618 | + b) You must cause any work that you distribute or publish, that in |
1619 | + whole or in part contains or is derived from the Program or any |
1620 | + part thereof, to be licensed as a whole at no charge to all third |
1621 | + parties under the terms of this License. |
1622 | + |
1623 | + c) If the modified program normally reads commands interactively |
1624 | + when run, you must cause it, when started running for such |
1625 | + interactive use in the most ordinary way, to print or display an |
1626 | + announcement including an appropriate copyright notice and a |
1627 | + notice that there is no warranty (or else, saying that you provide |
1628 | + a warranty) and that users may redistribute the program under |
1629 | + these conditions, and telling the user how to view a copy of this |
1630 | + License. (Exception: if the Program itself is interactive but |
1631 | + does not normally print such an announcement, your work based on |
1632 | + the Program is not required to print an announcement.) |
1633 | + |
1634 | |
1635 | +These requirements apply to the modified work as a whole. If |
1636 | +identifiable sections of that work are not derived from the Program, |
1637 | +and can be reasonably considered independent and separate works in |
1638 | +themselves, then this License, and its terms, do not apply to those |
1639 | +sections when you distribute them as separate works. But when you |
1640 | +distribute the same sections as part of a whole which is a work based |
1641 | +on the Program, the distribution of the whole must be on the terms of |
1642 | +this License, whose permissions for other licensees extend to the |
1643 | +entire whole, and thus to each and every part regardless of who wrote it. |
1644 | + |
1645 | +Thus, it is not the intent of this section to claim rights or contest |
1646 | +your rights to work written entirely by you; rather, the intent is to |
1647 | +exercise the right to control the distribution of derivative or |
1648 | +collective works based on the Program. |
1649 | + |
1650 | +In addition, mere aggregation of another work not based on the Program |
1651 | +with the Program (or with a work based on the Program) on a volume of |
1652 | +a storage or distribution medium does not bring the other work under |
1653 | +the scope of this License. |
1654 | + |
1655 | + 3. You may copy and distribute the Program (or a work based on it, |
1656 | +under Section 2) in object code or executable form under the terms of |
1657 | +Sections 1 and 2 above provided that you also do one of the following: |
1658 | + |
1659 | + a) Accompany it with the complete corresponding machine-readable |
1660 | + source code, which must be distributed under the terms of Sections |
1661 | + 1 and 2 above on a medium customarily used for software interchange; or, |
1662 | + |
1663 | + b) Accompany it with a written offer, valid for at least three |
1664 | + years, to give any third party, for a charge no more than your |
1665 | + cost of physically performing source distribution, a complete |
1666 | + machine-readable copy of the corresponding source code, to be |
1667 | + distributed under the terms of Sections 1 and 2 above on a medium |
1668 | + customarily used for software interchange; or, |
1669 | + |
1670 | + c) Accompany it with the information you received as to the offer |
1671 | + to distribute corresponding source code. (This alternative is |
1672 | + allowed only for noncommercial distribution and only if you |
1673 | + received the program in object code or executable form with such |
1674 | + an offer, in accord with Subsection b above.) |
1675 | + |
1676 | +The source code for a work means the preferred form of the work for |
1677 | +making modifications to it. For an executable work, complete source |
1678 | +code means all the source code for all modules it contains, plus any |
1679 | +associated interface definition files, plus the scripts used to |
1680 | +control compilation and installation of the executable. However, as a |
1681 | +special exception, the source code distributed need not include |
1682 | +anything that is normally distributed (in either source or binary |
1683 | +form) with the major components (compiler, kernel, and so on) of the |
1684 | +operating system on which the executable runs, unless that component |
1685 | +itself accompanies the executable. |
1686 | + |
1687 | +If distribution of executable or object code is made by offering |
1688 | +access to copy from a designated place, then offering equivalent |
1689 | +access to copy the source code from the same place counts as |
1690 | +distribution of the source code, even though third parties are not |
1691 | +compelled to copy the source along with the object code. |
1692 | + |
1693 | |
1694 | + 4. You may not copy, modify, sublicense, or distribute the Program |
1695 | +except as expressly provided under this License. Any attempt |
1696 | +otherwise to copy, modify, sublicense or distribute the Program is |
1697 | +void, and will automatically terminate your rights under this License. |
1698 | +However, parties who have received copies, or rights, from you under |
1699 | +this License will not have their licenses terminated so long as such |
1700 | +parties remain in full compliance. |
1701 | + |
1702 | + 5. You are not required to accept this License, since you have not |
1703 | +signed it. However, nothing else grants you permission to modify or |
1704 | +distribute the Program or its derivative works. These actions are |
1705 | +prohibited by law if you do not accept this License. Therefore, by |
1706 | +modifying or distributing the Program (or any work based on the |
1707 | +Program), you indicate your acceptance of this License to do so, and |
1708 | +all its terms and conditions for copying, distributing or modifying |
1709 | +the Program or works based on it. |
1710 | + |
1711 | + 6. Each time you redistribute the Program (or any work based on the |
1712 | +Program), the recipient automatically receives a license from the |
1713 | +original licensor to copy, distribute or modify the Program subject to |
1714 | +these terms and conditions. You may not impose any further |
1715 | +restrictions on the recipients' exercise of the rights granted herein. |
1716 | +You are not responsible for enforcing compliance by third parties to |
1717 | +this License. |
1718 | + |
1719 | + 7. If, as a consequence of a court judgment or allegation of patent |
1720 | +infringement or for any other reason (not limited to patent issues), |
1721 | +conditions are imposed on you (whether by court order, agreement or |
1722 | +otherwise) that contradict the conditions of this License, they do not |
1723 | +excuse you from the conditions of this License. If you cannot |
1724 | +distribute so as to satisfy simultaneously your obligations under this |
1725 | +License and any other pertinent obligations, then as a consequence you |
1726 | +may not distribute the Program at all. For example, if a patent |
1727 | +license would not permit royalty-free redistribution of the Program by |
1728 | +all those who receive copies directly or indirectly through you, then |
1729 | +the only way you could satisfy both it and this License would be to |
1730 | +refrain entirely from distribution of the Program. |
1731 | + |
1732 | +If any portion of this section is held invalid or unenforceable under |
1733 | +any particular circumstance, the balance of the section is intended to |
1734 | +apply and the section as a whole is intended to apply in other |
1735 | +circumstances. |
1736 | + |
1737 | +It is not the purpose of this section to induce you to infringe any |
1738 | +patents or other property right claims or to contest validity of any |
1739 | +such claims; this section has the sole purpose of protecting the |
1740 | +integrity of the free software distribution system, which is |
1741 | +implemented by public license practices. Many people have made |
1742 | +generous contributions to the wide range of software distributed |
1743 | +through that system in reliance on consistent application of that |
1744 | +system; it is up to the author/donor to decide if he or she is willing |
1745 | +to distribute software through any other system and a licensee cannot |
1746 | +impose that choice. |
1747 | + |
1748 | +This section is intended to make thoroughly clear what is believed to |
1749 | +be a consequence of the rest of this License. |
1750 | + |
1751 | |
1752 | + 8. If the distribution and/or use of the Program is restricted in |
1753 | +certain countries either by patents or by copyrighted interfaces, the |
1754 | +original copyright holder who places the Program under this License |
1755 | +may add an explicit geographical distribution limitation excluding |
1756 | +those countries, so that distribution is permitted only in or among |
1757 | +countries not thus excluded. In such case, this License incorporates |
1758 | +the limitation as if written in the body of this License. |
1759 | + |
1760 | + 9. The Free Software Foundation may publish revised and/or new versions |
1761 | +of the General Public License from time to time. Such new versions will |
1762 | +be similar in spirit to the present version, but may differ in detail to |
1763 | +address new problems or concerns. |
1764 | + |
1765 | +Each version is given a distinguishing version number. If the Program |
1766 | +specifies a version number of this License which applies to it and "any |
1767 | +later version", you have the option of following the terms and conditions |
1768 | +either of that version or of any later version published by the Free |
1769 | +Software Foundation. If the Program does not specify a version number of |
1770 | +this License, you may choose any version ever published by the Free Software |
1771 | +Foundation. |
1772 | + |
1773 | + 10. If you wish to incorporate parts of the Program into other free |
1774 | +programs whose distribution conditions are different, write to the author |
1775 | +to ask for permission. For software which is copyrighted by the Free |
1776 | +Software Foundation, write to the Free Software Foundation; we sometimes |
1777 | +make exceptions for this. Our decision will be guided by the two goals |
1778 | +of preserving the free status of all derivatives of our free software and |
1779 | +of promoting the sharing and reuse of software generally. |
1780 | + |
1781 | + NO WARRANTY |
1782 | + |
1783 | + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY |
1784 | +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN |
1785 | +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES |
1786 | +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED |
1787 | +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
1788 | +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
1789 | +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE |
1790 | +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, |
1791 | +REPAIR OR CORRECTION. |
1792 | + |
1793 | + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
1794 | +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR |
1795 | +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, |
1796 | +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING |
1797 | +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED |
1798 | +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY |
1799 | +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER |
1800 | +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE |
1801 | +POSSIBILITY OF SUCH DAMAGES. |
1802 | + |
1803 | + END OF TERMS AND CONDITIONS |
1804 | + |
1805 | |
1806 | + How to Apply These Terms to Your New Programs |
1807 | + |
1808 | + If you develop a new program, and you want it to be of the greatest |
1809 | +possible use to the public, the best way to achieve this is to make it |
1810 | +free software which everyone can redistribute and change under these terms. |
1811 | + |
1812 | + To do so, attach the following notices to the program. It is safest |
1813 | +to attach them to the start of each source file to most effectively |
1814 | +convey the exclusion of warranty; and each file should have at least |
1815 | +the "copyright" line and a pointer to where the full notice is found. |
1816 | + |
1817 | + <one line to give the program's name and a brief idea of what it does.> |
1818 | + Copyright (C) <year> <name of author> |
1819 | + |
1820 | + This program is free software; you can redistribute it and/or modify |
1821 | + it under the terms of the GNU General Public License as published by |
1822 | + the Free Software Foundation; either version 2 of the License, or |
1823 | + (at your option) any later version. |
1824 | + |
1825 | + This program is distributed in the hope that it will be useful, |
1826 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
1827 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1828 | + GNU General Public License for more details. |
1829 | + |
1830 | + You should have received a copy of the GNU General Public License |
1831 | + along with this program; if not, write to the Free Software |
1832 | + Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
1833 | + |
1834 | + |
1835 | +Also add information on how to contact you by electronic and paper mail. |
1836 | + |
1837 | +If the program is interactive, make it output a short notice like this |
1838 | +when it starts in an interactive mode: |
1839 | + |
1840 | + Gnomovision version 69, Copyright (C) year name of author |
1841 | + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
1842 | + This is free software, and you are welcome to redistribute it |
1843 | + under certain conditions; type `show c' for details. |
1844 | + |
1845 | +The hypothetical commands `show w' and `show c' should show the appropriate |
1846 | +parts of the General Public License. Of course, the commands you use may |
1847 | +be called something other than `show w' and `show c'; they could even be |
1848 | +mouse-clicks or menu items--whatever suits your program. |
1849 | + |
1850 | +You should also get your employer (if you work as a programmer) or your |
1851 | +school, if any, to sign a "copyright disclaimer" for the program, if |
1852 | +necessary. Here is a sample; alter the names: |
1853 | + |
1854 | + Yoyodyne, Inc., hereby disclaims all copyright interest in the program |
1855 | + `Gnomovision' (which makes passes at compilers) written by James Hacker. |
1856 | + |
1857 | + <signature of Ty Coon>, 1 April 1989 |
1858 | + Ty Coon, President of Vice |
1859 | + |
1860 | +This General Public License does not permit incorporating your program into |
1861 | +proprietary programs. If your program is a subroutine library, you may |
1862 | +consider it more useful to permit linking proprietary applications with the |
1863 | +library. If this is what you want to do, use the GNU Library General |
1864 | +Public License instead of this License. |
1865 | |
1866 | === added file 'plugins/RemoteControl/ChangeLog' |
1867 | --- plugins/RemoteControl/ChangeLog 1970-01-01 00:00:00 +0000 |
1868 | +++ plugins/RemoteControl/ChangeLog 2016-06-03 22:29:41 +0000 |
1869 | @@ -0,0 +1,3 @@ |
1870 | + |
1871 | +0.0.0 [2015-04-25] |
1872 | +GZ: Created basic plugin (structure cloned from AngleMeasure, but only code fragments remain.) |
1873 | |
1874 | === added file 'plugins/RemoteControl/README' |
1875 | --- plugins/RemoteControl/README 1970-01-01 00:00:00 +0000 |
1876 | +++ plugins/RemoteControl/README 2016-06-03 22:29:41 +0000 |
1877 | @@ -0,0 +1,47 @@ |
1878 | +NetworkServer plugin for Stellarium |
1879 | +================================== |
1880 | + |
1881 | +A network server that allows remote control via the Stellarium Scripting API. |
1882 | + |
1883 | + |
1884 | +TODO |
1885 | +==== |
1886 | + |
1887 | +Start implementing! |
1888 | + |
1889 | +BUILDING THE PLUGIN |
1890 | +=================== |
1891 | + |
1892 | +Please note, these instructions are only directly applicable to Linux. |
1893 | +Windows and OSX targets will probably require modification of the |
1894 | +CMakeLists.txt file. |
1895 | + |
1896 | +0. Install and build the SVN version of Stellarium as per the |
1897 | +instructions on the Stellarium wiki: |
1898 | + |
1899 | + http://stellarium.org/wiki/index.php/Compilation_on_Linux |
1900 | + |
1901 | +NOTE: that the main program build must be set so that the libStelMain.so |
1902 | +file will be generated. This is achieved by setting the |
1903 | +GENERATE_STELMAINLIB variable in the main Stellarium CMakeLists.txt file |
1904 | +to 1, like so: |
1905 | + |
1906 | + SET(GENERATE_STELMAINLIB 1) |
1907 | + |
1908 | +1. Set the environment variable STELROOT to the root of the Stellarium |
1909 | +source tree. The Stellarium build directory is expected to be: |
1910 | + |
1911 | + $STELROOT/builds/unix |
1912 | + |
1913 | +2. Create a sub-directory builds/unix and change into that directory. |
1914 | + |
1915 | +3. Run: |
1916 | + |
1917 | + cmake ../.. |
1918 | + make |
1919 | + make install |
1920 | + |
1921 | +If all goes well, the relevant files should be built and copied to your |
1922 | +~/.stellarium/modules directory. |
1923 | + |
1924 | + |
1925 | |
1926 | === added file 'plugins/RemoteControl/RemoteControl.qrc' |
1927 | --- plugins/RemoteControl/RemoteControl.qrc 1970-01-01 00:00:00 +0000 |
1928 | +++ plugins/RemoteControl/RemoteControl.qrc 2016-06-03 22:29:41 +0000 |
1929 | @@ -0,0 +1,6 @@ |
1930 | +<RCC> |
1931 | + <qresource prefix="/RemoteControl"> |
1932 | + <file>resources/bt_remote_off.png</file> |
1933 | + <file>resources/bt_remote_on.png</file> |
1934 | + </qresource> |
1935 | +</RCC> |
1936 | |
1937 | === added directory 'plugins/RemoteControl/doc' |
1938 | === added file 'plugins/RemoteControl/doc/qtwebapp.doxygen' |
1939 | --- plugins/RemoteControl/doc/qtwebapp.doxygen 1970-01-01 00:00:00 +0000 |
1940 | +++ plugins/RemoteControl/doc/qtwebapp.doxygen 2016-06-03 22:29:41 +0000 |
1941 | @@ -0,0 +1,35 @@ |
1942 | +/* |
1943 | + * Stellarium |
1944 | + * Copyright (C) 2016 Florian Schaukowitsch |
1945 | + * |
1946 | + * This program is free software; you can redistribute it and/or |
1947 | + * modify it under the terms of the GNU General Public License |
1948 | + * as published by the Free Software Foundation; either version 2 |
1949 | + * of the License, or (at your option) any later version. |
1950 | + * |
1951 | + * This program is distributed in the hope that it will be useful, |
1952 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1953 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1954 | + * GNU General Public License for more details. |
1955 | + * |
1956 | + * You should have received a copy of the GNU General Public License |
1957 | + * along with this program; if not, write to the Free Software |
1958 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
1959 | + */ |
1960 | + |
1961 | +/*! |
1962 | + |
1963 | +@defgroup qtWebApp QtWebApp library |
1964 | + |
1965 | +The QtWebApp library is developed by Stefan Frings (http://stefanfrings.de/qtwebapp/index-en.html). |
1966 | +It is used by the Stellarium \ref remoteControl to provide the HTTP server that serves the plugin's API. |
1967 | + |
1968 | +Some changes have been made to the library to fit it better into Stellarium. The main differences are: |
1969 | +- The settings are no longer specified using QSettings, but with configuration structs (HttpListenerSettings, StaticFileControllerSettings, etc) |
1970 | +- The template engine supports translating strings at runtime through tags in pseudo-PHP style instead of just different files per language (ITemplateTranslationProvider, Template::translate) |
1971 | +- The Content-Type detection of the StaticFileController has been extended to use QMimeDatabase, if required. |
1972 | + |
1973 | +@author Stefan Frings, Florian Schaukowitsch |
1974 | +@copyright GNU Lesser General Public License (https://www.gnu.org/licenses/lgpl.html) |
1975 | + |
1976 | +*/ |
1977 | |
1978 | === added file 'plugins/RemoteControl/doc/remoteControl.doxygen' |
1979 | --- plugins/RemoteControl/doc/remoteControl.doxygen 1970-01-01 00:00:00 +0000 |
1980 | +++ plugins/RemoteControl/doc/remoteControl.doxygen 2016-06-03 22:29:41 +0000 |
1981 | @@ -0,0 +1,61 @@ |
1982 | +/* |
1983 | + * Stellarium |
1984 | + * Copyright (C) 2016 Florian Schaukowitsch |
1985 | + * |
1986 | + * This program is free software; you can redistribute it and/or |
1987 | + * modify it under the terms of the GNU General Public License |
1988 | + * as published by the Free Software Foundation; either version 2 |
1989 | + * of the License, or (at your option) any later version. |
1990 | + * |
1991 | + * This program is distributed in the hope that it will be useful, |
1992 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1993 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1994 | + * GNU General Public License for more details. |
1995 | + * |
1996 | + * You should have received a copy of the GNU General Public License |
1997 | + * along with this program; if not, write to the Free Software |
1998 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
1999 | + */ |
2000 | + |
2001 | +/*! |
2002 | +@defgroup remoteControl Remote Control Plug-in |
2003 | +@brief Control Stellarium through your web browser! For more information, see @ref remoteControlDoc. |
2004 | + |
2005 | +@page remoteControlDoc Remote Control Plug-in documentation |
2006 | +The %RemoteControl plugin provides a remote control using a webserver interface, usable for single or even synchronized cluster of clients (via the RemoteSync plugin). |
2007 | +You can simply connect via web browser to a |
2008 | +configurable port (default: 8090) of your computer. To use it locally, you can use |
2009 | +http://localhost:8090[/index.html] |
2010 | +or for a slightly modified GUI which may be better suited for smaller 7inch screens, try |
2011 | +http://localhost:8090/tablet7in.html. |
2012 | +Your web browser has to support JavaScript and HTML5 (recommended in 2016: <a href="https://mozilla.org/firefox">Firefox</a>, <a href="https://www.google.com/chrome/">Chrome</a>). |
2013 | + |
2014 | +The web data for the interface resides in the <tt>/data/webroot</tt> directory inside the installation directory (<tt>share/stellarium/data/webroot</tt> on Linux), and can be customized with |
2015 | +some knowledge of HTML, CSS and maybe JavaScript (not necessary for basic functionality, only when more complex additions are required). |
2016 | +Alternative or derived HTML control GUIs must be placed into the same folder, |
2017 | +the web server for now cannot read data from the private Stellarium user directory (<tt>~/.stellarium</tt>, <tt>\%APPDATA\%\\stellarium</tt>). |
2018 | + |
2019 | +This plugin makes extensive use of the StelProperty system introduced with it. This allows not only to trigger actions, |
2020 | +but also set QVariant values, which is enough to control many things in the program. |
2021 | +A few dedicated modules have been implemented closely following the existing GUI for view motion, location setting, |
2022 | +landscape and skyculture selection, searching objects, etc. |
2023 | +It is also possible to define interfaces that control plugins, and dynamically show them only when the plugin is enabled. |
2024 | + |
2025 | +Because the API is based on simple HTTP calls, it can also be called from command-line clients. For example, |
2026 | +to execute the script "double_stars.ssc", one could use one of the following lines: |
2027 | +@code |
2028 | +wget -q --post-data 'id=double_stars.ssc' http://localhost:8090/api/scripts/run >/dev/null 2>&1 |
2029 | +curl --data 'id=double_stars.ssc' http://localhost:8090/api/scripts/run >/dev/null 2>&1 |
2030 | +curl -d 'id=double_stars.ssc' http://localhost:8090/api/scripts/run >/dev/null 2>&1 |
2031 | +@endcode |
2032 | +This allows triggering automatic show setups for museums etc. |
2033 | + |
2034 | +The entry point of the plugin is the RemoteControl class. |
2035 | +- To see how the HTTP API looks like (i.e. if you want to extend it or access it without using the web interface), see @subpage remoteControlApi. |
2036 | +- To see how the web interface works (i.e. if you want to modify it or add new controls), see @subpage remoteControlWeb. |
2037 | + |
2038 | +@author Florian Schaukowitsch, Georg Zotti |
2039 | +@note This plugin includes parts of the \ref qtWebApp by Stefan Frings, used under the LGPL |
2040 | +@note This plugin has been developed as project of ESA SoCiS 2015 (http://sophia.estec.esa.int/socis/) |
2041 | + |
2042 | +*/ |
2043 | |
2044 | === added file 'plugins/RemoteControl/doc/remoteControlApi.doxygen' |
2045 | --- plugins/RemoteControl/doc/remoteControlApi.doxygen 1970-01-01 00:00:00 +0000 |
2046 | +++ plugins/RemoteControl/doc/remoteControlApi.doxygen 2016-06-03 22:29:41 +0000 |
2047 | @@ -0,0 +1,461 @@ |
2048 | +/* |
2049 | + * Stellarium |
2050 | + * Copyright (C) 2016 Florian Schaukowitsch |
2051 | + * |
2052 | + * This program is free software; you can redistribute it and/or |
2053 | + * modify it under the terms of the GNU General Public License |
2054 | + * as published by the Free Software Foundation; either version 2 |
2055 | + * of the License, or (at your option) any later version. |
2056 | + * |
2057 | + * This program is distributed in the hope that it will be useful, |
2058 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2059 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2060 | + * GNU General Public License for more details. |
2061 | + * |
2062 | + * You should have received a copy of the GNU General Public License |
2063 | + * along with this program; if not, write to the Free Software |
2064 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
2065 | + */ |
2066 | + |
2067 | +/*! |
2068 | + |
2069 | +\page remoteControlApi %RemoteControl plugin HTTP API description |
2070 | + |
2071 | +The \ref remoteControl "RemoteControl plugin" provides an HTTP-based interface to Stellarium, implemented on the server-side through implementations of AbstractAPIService. |
2072 | +The APIController maintains the list of registered services, and dispatches HTTP requests to the right service. |
2073 | +The API is accessible under the server path `/api/`. For example, if you have the server running on the default port of 8090, |
2074 | +you can access the operation \ref rcObjectServiceFind of the ObjectService to look for objects with \c moon in their name by accessing |
2075 | +\code |
2076 | +http://localhost:8090/api/objects/find?str=moon |
2077 | +|____________________|___|_______|____|_______| |
2078 | + | | | | |------ Standard HTTP query string for parameters (key=value) |
2079 | + | | | |------------ find operation (defined by service) |
2080 | + | | |------------------- service (e.g. ObjectService) |
2081 | + | |------------------------- API prefix (always /api/) |
2082 | + |-------------------------------------- server access (http://host:port) |
2083 | +\endcode |
2084 | + |
2085 | +Instead of the \ref remoteControlWeb "HTTP remote interface" you can also use tools like <a href="https://curl.haxx.se/">cURL</a> |
2086 | +to access the API remotely. For POST operations, you would use the flag \c -d to pass parameters. For GET operations, you should use |
2087 | +the additional flag \c -G if parameters are required. Examples: |
2088 | +@code{.sh} |
2089 | +# retrieve info about the script "double_stars.ssc" with a GET request |
2090 | +curl -G -d 'id=double_stars.ssc' http://localhost:8090/api/scripts/info |
2091 | +# run the script "double_stars.ssc" with a POST request |
2092 | +curl -d 'id=double_stars.ssc' http://localhost:8090/api/scripts/run |
2093 | +@endcode |
2094 | + |
2095 | +If authentication is enabled (see RemoteControl class), <a href="https://en.wikipedia.org/wiki/Basic_access_authentication">HTTP Basic access authentication</a> is expected, with an empty username. |
2096 | +HTTPS configuration is currently not implemented, even if the underlying \ref qtWebApp would allow it. |
2097 | + |
2098 | +Most operations return data in the <a href="http://www.json.org/">JSON</a> format, allowing it to be easily used in web applications. |
2099 | +The format of the returned JSON data is described for each operation below. |
2100 | +Some operations return plain text if only simple data is requested, or to confirm the success of an operation: |
2101 | +to indicate success "ok" may be returned, in an error case an HTTP error code may be returned together with a string "error: error message" in the response body. |
2102 | +Other operations may return HTML or even image data, you can check the returned Content-Type header if you are not sure what to expect. |
2103 | + |
2104 | +\tableofcontents |
2105 | + |
2106 | +\section rcExtendApi Extending the API |
2107 | + |
2108 | +The simplest way to expose new data through the API is by using the StelProperty system for a property you want to access. |
2109 | +In this way, the data is available through the MainService (allowing tracking of changes) and the StelPropertyService (giving a snapshot of current values, metadata information and allowing to change values). |
2110 | +You do not need to change/implement a new service in any way for this case. |
2111 | + |
2112 | +If you want to expose more complex behaviour, you may need to implement your own AbstractAPIService and register it with the APIController. |
2113 | +\todo Find out how to do this in plugin code |
2114 | + |
2115 | +\section rcApiReference API reference |
2116 | + |
2117 | +The default services are registered in the RequestHandler::RequestHandler() constructor. They are: |
2118 | + |
2119 | +Service | Path | Description |
2120 | +--------------------- | --------------------------------------------------- | ------------------------ |
2121 | +MainService | \ref rcMainService "main" | \copybrief MainService |
2122 | +ObjectService | \ref rcObjectService "objects" | \copybrief ObjectService |
2123 | +ScriptService | \ref rcScriptService "scripts" | \copybrief ScriptService |
2124 | +SimbadService | \ref rcSimbadService "simbad" | \copybrief SimbadService |
2125 | +StelActionService | \ref rcStelActionService "stelaction" | \copybrief StelActionService |
2126 | +StelPropertyService | \ref rcStelPropertyService "stelproperty" | \copybrief StelPropertyService |
2127 | +LocationService | \ref rcLocationService "location" | \copybrief LocationService |
2128 | +LocationSearchService | \ref rcLocationSearchService "locationsearch" | \copybrief LocationSearchService |
2129 | +ViewService | \ref rcViewService "view" | \copybrief ViewService |
2130 | + |
2131 | +\subsection rcMainService MainService operations (/api/main/) |
2132 | +\subsubsection rcMainServiceGET GET operations |
2133 | +Implemented by MainService::getImpl |
2134 | + |
2135 | +\paragraph rcMainServiceStatus status |
2136 | +Parameters: <tt>[actionId (Number)] [propId (Number)]</tt>\n |
2137 | +This operation can be polled every few moments to find out if some primary Stellarium state changed. It returns a JSON object with the following format: |
2138 | +\code{.js} |
2139 | +{ |
2140 | + //current location information, see StelLocation |
2141 | + location : { |
2142 | + name, |
2143 | + role, |
2144 | + planet, |
2145 | + latitude, |
2146 | + longitude, |
2147 | + altitude, |
2148 | + country, |
2149 | + state, |
2150 | + landscapeKey |
2151 | + }, |
2152 | + //current time information |
2153 | + time : { |
2154 | + jday, //current Julian day |
2155 | + deltaT, //current deltaT as determined by the current dT algorithm |
2156 | + gmtShift, //the timezone shift to GMT |
2157 | + timeZone, //the timezone name |
2158 | + utc, //the time in UTC time zone as ISO8601 time string |
2159 | + local, //the time in local time zone as ISO8601 time string |
2160 | + isTimeNow, //if true, the Stellarium time equals the current real-world time |
2161 | + timerate //the current time rate (in secs) |
2162 | + }, |
2163 | + selectioninfo, //string that contains the information of the currently selected object, as returned by StelObject::getInfoString |
2164 | + view : { |
2165 | + fov //current FOV |
2166 | + }, |
2167 | + |
2168 | + //the following is only inserted if an actionId parameter was given |
2169 | + //see below for more info |
2170 | + actionChanges : { |
2171 | + id, //currently valid action id, the interface should update its own id to this value |
2172 | + changes : { |
2173 | + //a list of boolean actions that changed since the actionId parameter |
2174 | + <actionName> : <actionValue> |
2175 | + } |
2176 | + }, |
2177 | + //the following is only inserted if an propId parameter was given |
2178 | + //see below for more info |
2179 | + propertyChanges : { |
2180 | + id, //currently valid prop id, the interface should update its own id to this value |
2181 | + changes : { |
2182 | + //a list of properties that changed since the propId parameter |
2183 | + <propName> : <propValue> |
2184 | + } |
2185 | + } |
2186 | +} |
2187 | +\endcode |
2188 | + |
2189 | +The \c actionChanges and \c propertyChanges sections allow a remote interface to track boolean StelAction and/or StelProperty changes. |
2190 | +On the initial poll, you should pass -2 as \p propId and \p actionId. This indicates to the service that you want a full |
2191 | +list of properties/actions and their current values. When receiving the answer, you should set your local \p propId /\p actionId to the id |
2192 | +contained in \c actionChanges and \c propertyChanges, and re-send it with the next request as parameter again. |
2193 | +This allows the MainService to find out which changes must be sent to you (it maintains a queue of action/property changes internally, incrementing |
2194 | +the ID with each change), and you only have to process the differences instead of everything. |
2195 | + |
2196 | +\paragraph rcMainServicePlugins plugins |
2197 | +Returns the list of all known plugins, as a JSON object of format: |
2198 | +\code{.js} |
2199 | +{ |
2200 | + //list of known plugins, in format: |
2201 | + <pluginName> : { |
2202 | + loadAtStartup, //if to load the plugin at startup |
2203 | + loaded, //if the plugin is currently loaded |
2204 | + //corresponds to the StelPluginInfo of the plugin |
2205 | + info : { |
2206 | + authors, |
2207 | + contact, |
2208 | + description, |
2209 | + displayedName, |
2210 | + startByDefault, |
2211 | + version |
2212 | + } |
2213 | + } |
2214 | +} |
2215 | +\endcode |
2216 | + |
2217 | +\subsubsection rcMainServicePOST POST operations |
2218 | +Implemented by MainService::postImpl |
2219 | + |
2220 | +\paragraph rcMainServiceTime time |
2221 | +Parameters: <tt>time (Number) timerate (Number)</tt>\n |
2222 | +Sets the current Stellarium simulation time and/or timerate. The \p time parameter defines the current time (Julian day) as passed to StelCore::setJD. |
2223 | +The \p timerate parameter allows to change the speed at which the simulation time moves (in JDay/sec) as passed to StelCore::setTimeRate. |
2224 | + |
2225 | +\paragraph rcMainServiceFocus focus |
2226 | +Parameters: <tt>[target (String) | position (JSON Number Array of size 3, i.e. Vec3d)]</tt>\n |
2227 | +Sets the current app focus/selection. If no parameters are given, the current selection is cleared. |
2228 | +If the \p target parameter was given, the object to be selected is looked up by name (first the localized name is tried, then the english name). |
2229 | +If the \p position parameter is used, it is interpreted as a coordinate in the J2000 frame, and focused using StelMovementMgr::moveToJ2000 |
2230 | + |
2231 | +\paragraph rcMainServiceMove move |
2232 | +Parameters: <tt>x (Number) y (Number)</tt>\n |
2233 | +Allows viewport movement, like using the arrow keys in the main program. This allows interfaces to create a "virtual joystick" to move the view manually. |
2234 | +This operation defines the intended move direction. \p x and \p y define the intended |
2235 | +move speed in azimuth and altitude (i.e. a negative \p x means left). Values of +-1.0 correspond to the same speed as used for the arrow keys. |
2236 | +This operation works in conjunction with the update() method - until the movement is stopped |
2237 | +(i.e. \p x and \p y are zero), or no \c move command has been received for a specified time (about a second), the movement is performed in the given directions. |
2238 | + |
2239 | +\paragraph rcMainServiceFov fov |
2240 | +Parameters: <tt>fov (Number)</tt>\n |
2241 | +Sets the current field-of-view using StelCore::setFov |
2242 | + |
2243 | +\subsection rcObjectService ObjectService operations (/api/objects/) |
2244 | +\subsubsection rcObjectServiceGET GET operations |
2245 | +Implemented by ObjectService::getImpl |
2246 | + |
2247 | +\paragraph rcObjectServiceFind find |
2248 | +Parameters: <tt>str (String)</tt>\n |
2249 | +Finds objects which match the search string \p str, which may contain greek/unicode characters like in the SearchDialog. |
2250 | +Returns a JSON String array of search matches |
2251 | + |
2252 | +\paragraph rcObjectServiceInfo info |
2253 | +Parameters: <tt>[name (String)]</tt>\n |
2254 | +Returns a HTML info string (StelObject::getInfoString) about the object identified by \p name. |
2255 | +If no parameter is given, the currently selected object is used. |
2256 | + |
2257 | +\paragraph rcObjectServiceListobjecttypes listobjecttypes |
2258 | +Returns all object types available in the internal catalogs as a JSON array of objects of format |
2259 | +@code{.js} |
2260 | +{ |
2261 | + key, //the internal key for the object type |
2262 | + name, //the english name of the type |
2263 | + name_i18n //the type name in the current language |
2264 | +} |
2265 | +@endcode |
2266 | + |
2267 | +\paragraph rcObjectServiceListobjectsbytype listobjectsbytype |
2268 | +Parameters: <tt>type (String) [english (Number)]</tt>\n |
2269 | +Returns all objects of the specified \p type. If \p english is given and it evaluates to a "true" value, the english names |
2270 | +will be returned, otherwise the localized names will be returned. Returns a JSON string array. |
2271 | + |
2272 | +\subsection rcScriptService ScriptService operations (/api/scripts/) |
2273 | +\subsubsection rcScriptServiceGET GET operations |
2274 | +Implemented by ScriptService::getImpl |
2275 | + |
2276 | +\paragraph rcScriptServiceList list |
2277 | +Lists all known script files, as a JSON string array. |
2278 | + |
2279 | +\paragraph rcScriptServiceInfo info |
2280 | +Parameters: <tt>id (String) [html (any type)] </tt>\n |
2281 | +Returns information about the script identified by \p id. |
2282 | +If the optional parameter \p html is present (its value is ignored), |
2283 | +the info is formatted using StelScriptMgr::getHtmlDescription and |
2284 | +suitable for inclusion into an \c iframe element, |
2285 | +otherwise this operation returns a JSON object of format: |
2286 | +@code{.js} |
2287 | +{ |
2288 | + id, //the script ID |
2289 | + name, //the english name of the script |
2290 | + name_localized, //the localized name of the script |
2291 | + description, //the english description of the script |
2292 | + description_localized, //the localized description of the script |
2293 | + author, //the author(s) of the script |
2294 | + license //the license of the script |
2295 | +} |
2296 | +@endcode |
2297 | + |
2298 | +\paragraph rcScriptServiceStatus status |
2299 | +Returns the current script status as a JSON object of format: |
2300 | +@code{.js} |
2301 | +{ |
2302 | + scriptIsRunning, //true if a script is running |
2303 | + runningScriptId //the currently running script ID |
2304 | +} |
2305 | +@endcode |
2306 | +@note The StelScriptMgr also provides a StelProperty \c StelScriptMgr.runningScriptId that |
2307 | +can be used to find out the active script. |
2308 | + |
2309 | +\subsubsection rcScriptServicePOST POST operations |
2310 | +Implemented by ScriptService::postImpl |
2311 | + |
2312 | +\paragraph rcScriptServiceRun run |
2313 | +Parameters: <tt>id (String)</tt>\n |
2314 | +Runs the script with the given \p id. Will fail if a script is currently running. |
2315 | + |
2316 | +\paragraph rcScriptServiceDirect direct |
2317 | +Parameters: <tt>code (String) [useIncludes (Bool)]</tt>\n |
2318 | +Directly executes the given script \p code. If \p useIncludes is given and evaluates to true, the standard |
2319 | +include folder will be used. Script execution will fail if a script is already running. |
2320 | + |
2321 | +\paragraph rcScriptServiceStop stop |
2322 | +Stops the execution of a running script. |
2323 | + |
2324 | +\subsection rcSimbadService SimbadService operations (/api/simbad/) |
2325 | +\subsubsection rcSimbadServiceGET GET operations |
2326 | +Implemented by SimbadService::getImpl |
2327 | + |
2328 | +\paragraph rcSimbadServiceLookup lookup |
2329 | +Parameters: <tt>str (String)</tt>\n |
2330 | +Performs a SIMBAD lookup for the string \p str using the Stellarium-configured server and returns the results as a JSON object of format |
2331 | +@code{.js} |
2332 | +{ |
2333 | + status, //the status of the lookup: either "empty" when nothing was found, "found" when at least 1 result was returned, and "error" if the lookup caused an error |
2334 | + status_i18n, //a localized status message for display |
2335 | + errorString, //if the status is "error", this contains more information about it |
2336 | + results: { |
2337 | + names : [ |
2338 | + //an array of object names |
2339 | + ], |
2340 | + positions : [ |
2341 | + //an array of object positions (i.e. first one corresponds to first name, etc.) |
2342 | + //format is an array of 3 numbers for each entry, i.e.: |
2343 | + [1,2,3],... |
2344 | + ] |
2345 | + } |
2346 | +} |
2347 | +@endcode |
2348 | + |
2349 | +\subsection rcStelActionService StelAction operations (/api/stelaction/) |
2350 | +\subsubsection rcStelActionServiceGET GET operations |
2351 | +Implemented by StelActionService::getImpl |
2352 | + |
2353 | +\paragraph rcStelActionServiceList list |
2354 | +Lists all registered StelActions, in the format |
2355 | +@code{.js} |
2356 | +{ |
2357 | + //translated StelAction group name |
2358 | + <groupName> : [ |
2359 | + //all StelActions in the group <groupName> |
2360 | + <actionName> : { |
2361 | + id, //the ID of the action |
2362 | + isCheckable, //true if the action represents a boolean value |
2363 | + isChecked, //if "isCheckable" is true, shows the current boolean state |
2364 | + text //the translated description of the action |
2365 | + } |
2366 | + ] |
2367 | +} |
2368 | +@endcode |
2369 | + |
2370 | +\subsubsection rcStelActionServicePOST POST operations |
2371 | +Implemented by StelActionService::postImpl |
2372 | + |
2373 | +\paragraph rcStelActionServiceDo do |
2374 | +Parameters: <tt>id (String)</tt>\n |
2375 | +Triggers or toggles the StelAction specified by \p id. If it was a boolean action, returns the new state of the action (strings "true"/"false"). |
2376 | + |
2377 | +\subsection rcStelPropertyService StelProperty operations (/api/stelproperty/) |
2378 | +\subsubsection rcStelPropertyServiceGET GET operations |
2379 | +Implemented by StelPropertyService::getImpl |
2380 | + |
2381 | +\paragraph rcStelPropertyServiceList list |
2382 | +Lists all registered StelProperties, in the format |
2383 | +@code{.js} |
2384 | +{ |
2385 | + <propId> : { |
2386 | + value, //the current value of the StelProperty |
2387 | + variantType, //the type string of the "value", as determined by QVariant::typeName |
2388 | + typeString, //the type string of the StelProperty, as determined by QMetaProperty::typeName (may not be equal to "variantType") |
2389 | + typeEnum, //the enum value of the type of the StelProperty, as determined by StelProperty::getType |
2390 | + } |
2391 | +} |
2392 | +@endcode |
2393 | +@note The generic type conversions are done by QJsonValue::fromVariant |
2394 | + |
2395 | +\subsubsection rcStelPropertyServicePOST POST operations |
2396 | +Implemented by StelPropertyService::postImpl |
2397 | + |
2398 | +\paragraph rcStelPropertyServiceSet set |
2399 | +Parameters: <tt>id (String) value (String)</tt>\n |
2400 | +Sets the StelProperty identified by \p id to the value \p value. The value is converted to the StelProperty type |
2401 | +using QVariant logic, an error is returned if this is somehow not possible. |
2402 | + |
2403 | +\subsection rcLocationService LocationService operations (/api/location/) |
2404 | +\subsubsection rcLocationServiceGET GET operations |
2405 | +Implemented by LocationService::getImpl |
2406 | + |
2407 | +\paragraph rcLocationServiceList list |
2408 | +Returns the list of all stored location IDs (keys of StelLocationMgr::getAllMap) as JSON string array |
2409 | + |
2410 | +\paragraph rcLocationServiceCountrylist countrylist |
2411 | +Returns the list of all known countries (StelLocaleMgr::getAllCountryNames), as a JSON array of objects of format |
2412 | +@code |
2413 | +{ |
2414 | + name, //the english country name |
2415 | + name_i18n //the localized country name (current language) |
2416 | +} |
2417 | +@endcode |
2418 | + |
2419 | +\paragraph rcLocationServicePlanetlist planetlist |
2420 | +Returns the list of all solar system planet names (SolarSystem::getAllPlanetEnglishNames), as a JSON array of objects of format |
2421 | +@code |
2422 | +{ |
2423 | + name, //the english planet |
2424 | + name_i18n //the localized planet name (current language) |
2425 | +} |
2426 | +@endcode |
2427 | + |
2428 | +\paragraph rcLocationServicePlanetimage planetimage |
2429 | +Parameters: <tt>planet (String)</tt>\n |
2430 | +Returns the planet texture image for the \p planet (english name) |
2431 | + |
2432 | +\subsubsection rcLocationServicePOST POST operations |
2433 | +Implemented by LocationService::postImpl |
2434 | + |
2435 | +\paragraph rcLocationServiceSetlocationfields setlocationfields |
2436 | +Parameters: <tt>id (String) | ( [latitude (Number)] [longitude (Number)] [altitude (Number)] [name (String)] [country (String)] [planet (String)] )</tt>\n |
2437 | +Changes and moves to a new location. |
2438 | +If \p id is given, all other parameters are ignored, and a location is searched from the named locations using StelLocationMgr::locationForString with the \p id. |
2439 | +Else, the other parameters change the specific field of the current StelLocation. |
2440 | + |
2441 | +\subsection rcLocationSearchService LocationSearchService operations (/api/locationsearch/) |
2442 | +\subsubsection rcLocationSearchServiceGET GET operations |
2443 | +Implemented by LocationSearchService::getImpl |
2444 | + |
2445 | +\paragraph rcLocationSearchServiceSearch search |
2446 | +Parameters: <tt>term (String)</tt>\n |
2447 | +Searches the \p term in the list of predefined locations of the StelLocationMgr, and returns a JSON string array of the results. |
2448 | + |
2449 | +\paragraph rcLocationSearchServiceNearby nearby |
2450 | +Parameters: <tt>[planet (String)] [latitude (Number)] [longitude (Number)] [radius (Number)]</tt>\n |
2451 | +Searches near the location defined by \p planet, \p latitude and \p longitude for predefined locations (inside the given \p radius) |
2452 | +using StelLocationMgr::pickLocationsNearby, returns a JSON string array. |
2453 | + |
2454 | +\subsection rcViewService ViewService operations (/api/view/) |
2455 | +\subsubsection rcViewServiceGET GET operations |
2456 | +Implemented by ViewService::getImpl |
2457 | + |
2458 | +\paragraph rcViewServiceListlandscape listlandscape |
2459 | +Lists the installed landscapes as a JSON object of format |
2460 | +@code{.js} |
2461 | +{ |
2462 | + <landscapeId> : <landscapeName>, //maps the landscape id to the translated landscape name |
2463 | + ... |
2464 | +} |
2465 | +@endcode |
2466 | + |
2467 | +\paragraph rcViewServiceLandscapedescription landscapedescription/ |
2468 | +<em>Note that the slash at the end is mandatory!</em>\n |
2469 | +Provides virtual filesystem access to the current landscape directory. |
2470 | +The operation can take a longer path in the URL. The remainder is used to access files in the landscape directory. |
2471 | +If no longer path is given, the current HTML landscape description (as per LandscapeMgr::getCurrentLandscapeHtmlDescription) |
2472 | +is returned. An example: `landscapedescription/image.png` returns `image.png` from the current landscape directory. |
2473 | + |
2474 | +This operation allows to set up an HTML \c iframe or similar for the landscape description, including all images, etc. embedded |
2475 | +in the HTML description. |
2476 | + |
2477 | +\paragraph rcViewServiceListskyculture listskyculture |
2478 | +Lists the installed sky cultures as a JSON object of format |
2479 | +@code{.js} |
2480 | +{ |
2481 | + <skycultureId> : <skycultureName>, //maps the id to the translated name |
2482 | + ... |
2483 | +} |
2484 | +@endcode |
2485 | + |
2486 | +\paragraph rcViewServiceSkyculturedescription skyculturedescription/ |
2487 | +<em>Note that the slash at the end is mandatory!</em>\n |
2488 | +Provides virtual filesystem access to the current skyculture directory. |
2489 | +The operation can take a longer path in the URL. The remainder is used to access files in the skyculture directory. |
2490 | +If no longer path is given, the current HTML skyculture description (as per StelSkyCultureMgr::getCurrentSkyCultureHtmlDescription) |
2491 | +is returned. An example: `skyculturedescription/image.png` returns `image.png` from the current skyculture directory. |
2492 | + |
2493 | +This operation allows to set up an HTML \c iframe or similar for the skycultures description, including all images, etc. embedded |
2494 | +in the HTML description. |
2495 | + |
2496 | +\paragraph rcViewServiceListprojection listprojection |
2497 | +Lists the available projection types as a JSON object of format |
2498 | +@code{.js} |
2499 | +{ |
2500 | + <projectionTypeKey> : <projectionName>, //maps the id to the translated name |
2501 | + ... |
2502 | +} |
2503 | +@endcode |
2504 | + |
2505 | +\paragraph rcViewServiceProjectiondescription projectiondescription |
2506 | +Returns the HTML description of the current projection (StelProjector::getHtmlSummary) |
2507 | + |
2508 | +*/ |
2509 | |
2510 | === added file 'plugins/RemoteControl/doc/remoteControlWeb.doxygen' |
2511 | --- plugins/RemoteControl/doc/remoteControlWeb.doxygen 1970-01-01 00:00:00 +0000 |
2512 | +++ plugins/RemoteControl/doc/remoteControlWeb.doxygen 2016-06-03 22:29:41 +0000 |
2513 | @@ -0,0 +1,564 @@ |
2514 | +/* |
2515 | + * Stellarium |
2516 | + * Copyright (C) 2016 Florian Schaukowitsch |
2517 | + * |
2518 | + * This program is free software; you can redistribute it and/or |
2519 | + * modify it under the terms of the GNU General Public License |
2520 | + * as published by the Free Software Foundation; either version 2 |
2521 | + * of the License, or (at your option) any later version. |
2522 | + * |
2523 | + * This program is distributed in the hope that it will be useful, |
2524 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2525 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2526 | + * GNU General Public License for more details. |
2527 | + * |
2528 | + * You should have received a copy of the GNU General Public License |
2529 | + * along with this program; if not, write to the Free Software |
2530 | + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
2531 | + */ |
2532 | + |
2533 | +/*! |
2534 | + |
2535 | +\page remoteControlWeb %RemoteControl plugin web interface |
2536 | + |
2537 | +\tableofcontents |
2538 | + |
2539 | +The \ref remoteControlDoc "RemoteControl plugin", by default, provides a HTML web interface through the same integrated HTTP |
2540 | +server that serves the \ref remoteControlApi "RemoteControl API". All content found in the <tt>data/webroot</tt> folder is served. |
2541 | +Note that the \c /api/ path is reserved for the \ref remoteControlApi "HTTP API", and therefore can not be used as a folder. |
2542 | +The <tt>index.html</tt> file is mapped to the root, so you can access it using http://localhost:8090 with the default port setting |
2543 | +of 8090. A slightly modified alternative interface (mainly larger buttons for now) for 7" tablets and other touch devices |
2544 | +is available at http://localhost:8090/tablet7in.html. |
2545 | + |
2546 | +A reasonably modern browser is required to access the interface. Some features of <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5">HTML5</a> |
2547 | +and <a href="https://developer.mozilla.org/en/docs/Web/CSS/CSS3">CSS3</a> are used. |
2548 | + |
2549 | +The interface heavily relies on <a href="https://jquery.com/">jQuery</a> for easier JavaScript coding. The code is structured into modules, |
2550 | +and loaded using <a href="http://requirejs.org/">require.js</a>, which automatically resolves dependencies and load order. |
2551 | + |
2552 | +\section remoteControlWebStructure File and directory structure |
2553 | + |
2554 | +Note that not all files are listed here, only those of special interest. |
2555 | + |
2556 | +- webroot/ - root directory |
2557 | + - index.html - Default interface, also mapped to the root folder |
2558 | + - style.css - Main stylesheet |
2559 | + - tablet7in.html - Modified interface for tablet devices |
2560 | + - style_tablet7in.css - Additional stylesheet for tablet7in.html |
2561 | + - translate_files - Defines which files are passed through StelTranslator, see \ref remoteControlWebTranslation |
2562 | + - iframestyle.css - defines the style for internal frames (landscape description, etc.) |
2563 | + - /js/ - Contains the JavaScript files required for the interfaces |
2564 | + - main.js - This is the configuration file for require.js. Loads \ref rcUiMainui as main module. |
2565 | + - settings.js - Contains some configuration options for the web interface |
2566 | + - translationdata.js - Auto-generated file containing strings to translate through StelTranslator, see \ref remoteControlWebTranslation |
2567 | + - /api/ - Contains .js modules that define the connection to the \ref remoteControlApi "RemoteControl API" |
2568 | + - \ref rcApiRemotecontrol |
2569 | + - \ref rcApiActions |
2570 | + - \ref rcApiFlags |
2571 | + - \ref rcApiLocation |
2572 | + - \ref rcApiProperties |
2573 | + - \ref rcApiScripts |
2574 | + - \ref rcApiSearch |
2575 | + - \ref rcApiTime |
2576 | + - \ref rcApiUpdatequeue |
2577 | + - \ref rcApiViewcontrol |
2578 | + - \ref rcApiViewoptions |
2579 | + - /ui/ - Contains UI-related .js modules which depend on the /api/ .js modules |
2580 | + - \ref rcUiMainui |
2581 | + - \ref rcUiActions |
2582 | + - \ref rcUiCombobox |
2583 | + - \ref rcUiJqueryuifixes |
2584 | + - \ref rcUiLocation |
2585 | + - \ref rcUiScripts |
2586 | + - \ref rcUiSearch |
2587 | + - \ref rcUiTime |
2588 | + - \ref rcUiViewcontrol |
2589 | + - \ref rcUiViewoptions |
2590 | + |
2591 | +\section remoteControlWebEdit Editing the interface |
2592 | + |
2593 | +With knowledge of HTML, CSS and JavaScript (the latter not required for basic modifications), the interface can be customized. |
2594 | + |
2595 | +\subsection remoteControlWebBasic Basic extension |
2596 | + |
2597 | +When using the standard JavaScript provided, they allow to use pre-defined CSS "marker" classes which do not style the element per-se (i.e. have no entries in the .css files), |
2598 | +but allow you to add functionality to HTML elements without editing the JavaScript code. |
2599 | +Some of these classes also allow you to add further attributes to the element |
2600 | +(usually <a href="https://developer.mozilla.org/en/docs/Web/Guide/HTML/Using_data_attributes">HTML5 data attributes</a>) |
2601 | +to further customize their behaviour. |
2602 | + |
2603 | +\subsubsection remoteControlWebUIClasses UI control classes |
2604 | + |
2605 | +Some classes allow generating UI controls that are similar to what you expect for desktop apps. These use <a href="https://jqueryui.com/">jQuery UI</a> with |
2606 | +some modifications. |
2607 | + |
2608 | +\paragraph remoteControlWebUIspinner spinner |
2609 | +If added to an HTML \c input element, it sets the control up as a numerical Spinner widget (using jQuery UI: https://api.jqueryui.com/spinner/). |
2610 | +It supports the following optional parameters: |
2611 | +- \p data-min - Defines the minimum value of the spinner |
2612 | +- \p data-max - Defines the maximum value of the spinner |
2613 | +- \p data-step - Defines the desired step size of the spinner, default is 1. May be different from the number format. |
2614 | +- \p data-numberformat - Defines how the number is formatted, using <a href="https://github.com/jquery/globalize/blob/v0.1.1/README.md#numbers">globalize.js 0.1.1 syntax</a> |
2615 | + |
2616 | +The element will emit the custom \c spinuserinput event whenever the value changes (either through the buttons or direct keyboard input). |
2617 | +An example, showing how a spinner is created and handled: |
2618 | +\code |
2619 | +//make a spinner from -50 to 50, always showing 2 decimal points and stepping 0.1 per click |
2620 | +<input id="myspinner" class="spinner" data-min="-50" data-max="50" data-step="0.1" data-numberformat="n2"/> |
2621 | + |
2622 | +//input handling in javascript |
2623 | +$("#myspinner").on("spinuserinput", function(evt,ui) { |
2624 | + //print the new value |
2625 | + console.log(ui.value); |
2626 | +}); |
2627 | +\endcode |
2628 | + |
2629 | +\paragraph remoteControlWebUIslider slider |
2630 | +If added to an HTML \c div element, it sets the control up as a numerical slider widget (using jQuery UI: https://api.jqueryui.com/slider/). |
2631 | +It supports the following optional parameters: |
2632 | +- \p data-min - Defines the minimum value of the slider |
2633 | +- \p data-max - Defines the maximum value of the slider |
2634 | +- \p data-step - Defines the desired step size of the slider, default is 1. May be different from the number format. |
2635 | + |
2636 | +The element will emit the \c slide event when the slider is moved. |
2637 | +\code |
2638 | +//make a slider from -50 to 50, stepsize 0.1 |
2639 | +<div id="myslider" class="slider" data-min="-50" data-max="50" data-step="0.1"/> |
2640 | + |
2641 | +//input handling in javascript |
2642 | +$("#myslider").on("slide", function(evt,ui) { |
2643 | + //print the new value |
2644 | + console.log(ui.value); |
2645 | +}); |
2646 | +\endcode |
2647 | + |
2648 | +\paragraph remoteControlWebUIjquerybutton jquerybutton |
2649 | +If added to an HTML \c button element, it converts it to a <a href="https://jqueryui.com/button/">jQuery UI button</a>. |
2650 | +This is mainly a cosmetic operation. |
2651 | + |
2652 | +\paragraph remoteControlWebUIselectmenu selectmenu |
2653 | +If added to an HTML \c select element, it creates a <a href="https://jqueryui.com/selectmenu/">jQuery UI selectmenu</a> from it. |
2654 | +This allows simple popup selection menus (like a QComboBox). |
2655 | + |
2656 | +\subsubsection remoteControlWebProp Special behaviour classes |
2657 | +These classes allow automatic connection to StelProperty and StelAction elements defined in Stellarium, allowing particularly easy |
2658 | +extension of the web interface. |
2659 | + |
2660 | +\paragraph remoteControlWebstelproperty stelproperty (Connection to StelProperty) |
2661 | +Allows direct connection of an element to a StelProperty, meaning the element is automatically updated |
2662 | +whenever the value in Stellarium changes --- regardless of the source of the change: it can come from the main GUI, scripting, or even |
2663 | +other RemoteControl web interface instances! Together with the \ref remoteControlWebUIClasses listed above, this allows closely and easily recreating |
2664 | +standard Stellarium interface elements. This is supported for: |
2665 | +- \c input elements with the \c spinner class (for numerical properties)\n |
2666 | + The StelProperty to use is identified by the standard \c input attribute \p name. |
2667 | + Updates the \p value property of the \c input when the StelProperty changes, and reacts to \c spinuserinput events to update the property |
2668 | + |
2669 | +- \c input elements of type \c checkbox (`<input type="checkbox">` (for boolean properties)\n |
2670 | + The StelProperty to use is identified by the standard \c input attribute \p name. |
2671 | + Uses the \p checked property and the \c click event. |
2672 | + |
2673 | +- \c div elements with the \c slider class (for numerical properties)\n |
2674 | + The StelProperty to use is identified by the custom attribute \p data-prop. |
2675 | + Connects to the \c slider widget property \p value. |
2676 | + |
2677 | +- \c select elements (also supports the optional \c selectmenu classs)\n |
2678 | + The StelProperty to use is identified by the standard \c select attribute \p name. |
2679 | + Sets the \c option that has the same \p value as the StelProperty value. |
2680 | + Useful for single selection out of a list of possibilities. |
2681 | + |
2682 | +- \c span elements, for read-only property display with optional number format\n |
2683 | + The StelProperty to use is identified by the custom attribute \p data-prop. |
2684 | + The value is displayed using the element's text content. |
2685 | + The optional \p data-numberformat attribute is used for the number format |
2686 | + using [globalize.js 0.1.1 syntax](https://github.com/jquery/globalize/blob/v0.1.1/README.md#numbers) |
2687 | + |
2688 | +- \c button or `input[type="button"]` elements, for write-only setting of a StelProperty to a pre-defined value when clicked\n |
2689 | + The StelProperty to use is identified by the standard attribute \p name, |
2690 | + and the value to set it to is defined by the attribute \p value. |
2691 | + |
2692 | +An example, setting up a spinner for the \c MilkyWay.intensity StelProperty: |
2693 | +\code{.html} |
2694 | +<!-- this is all that is required, the rest is done automatically --> |
2695 | +<input class="spinner stelproperty" name="MilkyWay.intensity" data-min="0" data-max="10" data-step="0.1" data-numberformat="n2"/> |
2696 | +\endcode |
2697 | + |
2698 | +Many more examples can be found by studying the `index.html` code. |
2699 | + |
2700 | +\paragraph remoteControlWebstelaction stelaction (Connection to StelAction) |
2701 | +When this class is added to \c button elements or \c input elements of `type="button"` or `type="checkbox"`, |
2702 | +this connects the control to a StelAction. The action is identified by the \p name attribute. |
2703 | +If the action is a boolean action (i.e. StelAction::isCheckable is true), checkboxes show the current state of the action, |
2704 | +and buttons get the \c active CSS class assigned if the action is currently true. |
2705 | + |
2706 | +Examples: |
2707 | +\code{.html} |
2708 | +<!-- This is how the main bottom button bar is defined --> |
2709 | +<ul class="ui-corner-all ui-widget-content button32list margin-vertical"> |
2710 | + <li><button class="stelaction icon32 btConstellationLines" name="actionShow_Constellation_Lines"></button></li> |
2711 | + <li><button class="stelaction icon32 btConstellationLabels" name="actionShow_Constellation_Labels"></button></li> |
2712 | + <li><button class="stelaction icon32 btConstellationArt" name="actionShow_Constellation_Art"></button></li> |
2713 | + <li><button class="stelaction icon32 btEquatorialGrid" name="actionShow_Equatorial_Grid"></button></li> |
2714 | + <li><button class="stelaction icon32 btAzimuthalGrid" name="actionShow_Azimuthal_Grid"></button></li> |
2715 | + <li><button class="stelaction icon32 btGround" name="actionShow_Ground"></button></li> |
2716 | + <li><button class="stelaction icon32 btCardinalPoints" name="actionShow_Cardinal_Points"></button></li> |
2717 | + <li><button class="stelaction icon32 btAtmosphere" name="actionShow_Atmosphere"></button></li> |
2718 | + <li><button class="stelaction icon32 btNebula" name="actionShow_Nebulas"></button></li> |
2719 | + <li><button class="stelaction icon32 btPlanets" name="actionShow_Planets_Labels"></button></li> |
2720 | + <li><button class="stelaction icon32 btEquatorialMount" name="actionSwitch_Equatorial_Mount"></button></li> |
2721 | + <li><button class="stelaction icon32 btGotoSelectedObject" name="actionSet_Tracking"></button></li> |
2722 | + <li><button class="stelaction icon32 btNightView" name="actionShow_Night_Mode"></button></li> |
2723 | + <li><button class="stelaction icon32 btFullScreen" name="actionSet_Full_Screen_Global"></button></li> |
2724 | +</ul> |
2725 | + |
2726 | +<!-- This is how to set up checkboxes --> |
2727 | +<label><input type="checkbox" class="stelaction" name="actionShow_Planets" /><?= tr("Show Solar System objects")?></label> |
2728 | +<label><input type="checkbox" class="stelaction" name="actionShow_Planets_Hints" /><?= tr("Show planet markers")?></label> |
2729 | +<label><input type="checkbox" class="stelaction" name="actionShow_Planets_Orbits" /><?= tr("Show planet orbits")?></label> |
2730 | +\endcode |
2731 | + |
2732 | +\paragraph remoteControlWebStelssc stelssc (Direct script execution) |
2733 | +This class allows you to define buttons that directly execute Stellarium \ref scripting code. |
2734 | +Supported for \c button and \c input elements of type \p button. The code to execute should be stored inside |
2735 | +the element's \p value property. If the custom attribute \p data-useincludes attribute is added (with any value), |
2736 | +the default include folder is added for optional includes, but this is not recommended unless necessary. |
2737 | + |
2738 | +An example: |
2739 | +\code{.html} |
2740 | +<!-- some buttons which move the view to predefined angles --> |
2741 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 0., 3.)">0°</button> |
2742 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 30., 3.)">30°</button> |
2743 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 60., 3.)">60°</button> |
2744 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 90., 3.)">90°</button> |
2745 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 120., 3.)">120°</button> |
2746 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 150., 3.)">150°</button> |
2747 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 180., 3.)">180°</button> |
2748 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 210., 3.)">210°</button> |
2749 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 240., 3.)">240°</button> |
2750 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 270., 3.)">270°</button> |
2751 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 300., 3.)">300°</button> |
2752 | +<button type="button" class="stelssc" value="core.moveToAltAzi(0., 330., 3.)">330°</button> |
2753 | +\endcode |
2754 | + |
2755 | +\warning |
2756 | +The \c stelssc approach has some disadvantages, so try to use it only when necessary: |
2757 | +- causes a larger overhead for Stellarium internally than other methods provided by the web interface |
2758 | +- the scripts can't be executed if another script is currently running, an error message will be shown in this case |
2759 | + - this also includes the user clicking too fast on any \c stelssc buttons! |
2760 | + |
2761 | +\paragraph remoteControlWebStelplugin stelplugin (Plugin-specific sections) |
2762 | +With the CSS class \c stelplugin, one can create special HTML sections that |
2763 | +are only shown when a specified [plugin](\ref plugins) is currently loaded by Stellarium. |
2764 | +If the plugin is not loaded, the whole element and all it's children are removed from the DOM. |
2765 | +This class can be added to any element. The plugin which is required is defined by the |
2766 | +\c data-plugin attribute, which should be set to the plugin ID. |
2767 | + |
2768 | +The optional \c data-pluginjs attribute can be used to define an additional JavaScript module that is only |
2769 | +loaded when the plugin is loaded. This can be used to implement additional behaviour through JS, if required. |
2770 | +It is recommended to put these modules into the `webroot/js/plugins` folder. |
2771 | + |
2772 | +An example, defining the plugin panel for the \ref archaeoLines : |
2773 | +\code |
2774 | +<div id="vo_archaeolines" class="smallblock stelplugin" data-plugin="ArchaeoLines" data-pluginjs="plugins/archaeolines"> |
2775 | + <h3><label><input type="checkbox" class="stelaction valign-middle" name="actionShow_Archaeo_Lines"/><?= tr("ArchaeoLines")?></label></h3> |
2776 | + <div class="inline-block blocklabel"> |
2777 | + <label><input type="checkbox" class="stelaction" name="actionAL_showEquinoxLine"/><?= tr("Equinox")?></label> |
2778 | + <label><input type="checkbox" class="stelaction" name="actionAL_showSolsticeLines"/><?= tr("Solstices")?></label> |
2779 | + <label><input type="checkbox" class="stelaction" name="actionAL_showCrossquarterLines"/><?= tr("Crossquarters")?></label> |
2780 | + <label><input type="checkbox" class="stelaction" name="actionAL_showMajorStandstillLines"/><?= tr("Major Standstill")?></label> |
2781 | + <label><input type="checkbox" class="stelaction" name="actionAL_showMinorStandstillLines"/><?= tr("Minor Standstill")?></label> |
2782 | + </div> |
2783 | + <div class="inline-block blocklabel"> |
2784 | + <label><input type="checkbox" class="stelaction" name="actionAL_showZenithPassageLine"/><?= tr("Zenith Passage")?></label> |
2785 | + <label><input type="checkbox" class="stelaction" name="actionAL_showNadirPassageLine"/><?= tr("Nadir Passage")?></label> |
2786 | + <label><input type="checkbox" class="stelaction" name="actionAL_showSelectedObjectLine"/><?= tr("Selected Object")?></label> |
2787 | + <label><input type="checkbox" class="stelaction" name="actionAL_showCurrentSunLine"/><?= tr("Current Sun")?></label> |
2788 | + <label><input type="checkbox" class="stelaction" name="actionAL_showCurrentMoonLine"/><?= tr("Current Moon")?></label> |
2789 | + </div> |
2790 | + <label class="display-block" for="select_ArchaeoLines_enumShowCurrentPlanet"><?= tr("Current Planet:")?></label> |
2791 | + <select id="select_ArchaeoLines_enumShowCurrentPlanet" class="selectmenu stelproperty display-block" name="ArchaeoLines.enumShowCurrentPlanet"> |
2792 | + <option value="10"><?= tr("None")?></option> |
2793 | + <option value="11"><?= tr("Mercury")?></option> |
2794 | + <option value="12"><?= tr("Venus")?></option> |
2795 | + <option value="13"><?= tr("Mars")?></option> |
2796 | + <option value="14"><?= tr("Jupiter")?></option> |
2797 | + <option value="15"><?= tr("Saturn")?></option> |
2798 | + </select> |
2799 | +</div> |
2800 | + |
2801 | +//the contents of plugins/archaeolines.js |
2802 | +define(["jquery"],function($){ |
2803 | + "use strict"; |
2804 | + |
2805 | + //this is just an example how to use additional dynamically loaded plugin files |
2806 | + console.log("Hello, this is a asynchronously loaded plugin javascript file!"); |
2807 | + |
2808 | +}); |
2809 | +\endcode |
2810 | + |
2811 | +\subsection remoteControlWebTranslation Translation information |
2812 | + |
2813 | +The interface can be translated using methods similar to the main program. |
2814 | +All strings in the HTML markup that should be translated can be written |
2815 | +between pseudo-PHP style tags and the \c tr function to achieve the same effect as the `q_()` macro in C++, like so: |
2816 | +\code |
2817 | +<label><input type="checkbox" class="stelaction" name="actionShow_Planets" /><?= tr("Show Solar System objects")?></label> |
2818 | +\endcode |
2819 | + |
2820 | +All files which are listed in the `webroot/translate_files` file will be parsed, and all `<?= tr("----")?>` tags will be |
2821 | +replaced using the StelTranslator for the current application language. |
2822 | + |
2823 | +If you require translated strings through JavaScript, you should use the `tr` method of the \ref rcApiRemotecontrol module, |
2824 | +which also works similar to the `q_()` macro. There is a special procedure for the JavaScript strings: the target |
2825 | +\c RemoteControl-update-translationdata should be run whenever new JavaScript strings have been added. |
2826 | +This updates the file `webroot/js/translationdata.js` with all current `tr()` strings. [Python](https://www.python.org/) |
2827 | +is required to be installed for this operation. |
2828 | + |
2829 | +Like the main program, the strings can be extracted from the HTML/JS code using gettext/xgettext. There are CMake targets for this like |
2830 | +for the C++ code (\c generate-pot-stellarium-remotecontrol, \c update-po-stellarium-remotecontrol, etc.) and they are also executed |
2831 | +with the combined targets (\c generate-pot, \c update-po etc.). |
2832 | + |
2833 | +\subsection remoteControlJS JavaScript module reference |
2834 | + |
2835 | +All interface code is developed using [require.js modules](http://requirejs.org/docs/api.html#define). |
2836 | +This allows defining the dependencies of each module, as well as easier maintainability. |
2837 | +Each module should be defined in its own .js file. The module ID corresponds to the .js file name |
2838 | +without the file extension. |
2839 | + |
2840 | +In short, to define a module, wrap it in a \c define call, and optionally add dependencies. |
2841 | +A basic example (for more ways to do it see the require.js doc): |
2842 | +\code |
2843 | +//myawesomemodule.js |
2844 | +//the IDs of the dependencies are listed in an array as first parameter |
2845 | +//the second parameter is usually a function which takes the actual instances of the dependencies as a parameter, |
2846 | +// in the same order as they are in the array! |
2847 | +define(["jquery", "api/remotecontrol"], function($,rc) { |
2848 | + "use strict"; //it is recommended to use strict mode for each module |
2849 | + |
2850 | + //do something as soon as this module is loaded |
2851 | + console.log("my awesome module is being loaded!"); |
2852 | + |
2853 | + //do something when the DOM is ready (because that is not guaranteed while the module is first bein loaded!) |
2854 | + $(function(){ |
2855 | + console.log("the document is ready, you can access the elements now!"); |
2856 | + //access an element and modifiy it |
2857 | + $("#myelement").text("hey, this is awesome"); |
2858 | + }); |
2859 | + |
2860 | + //react to the serverDataReceived event of the remotecontrol module |
2861 | + $(rc).on("serverDataReceived", function(evt,data) { |
2862 | + console.log("Stellarium just sent us new data!"); |
2863 | + console.log("The current jDay is " + data.time); |
2864 | + }); |
2865 | + |
2866 | + //provide some public methods that other modules may call |
2867 | + return { |
2868 | + myAwesomeMethod: function() { |
2869 | + console.log("Hello there!"); |
2870 | + } |
2871 | + }; |
2872 | +}); |
2873 | + |
2874 | +//another module (in another file) can now reference our module as dependency to load it and use its methods |
2875 | +define(["jquery", "myawesomemodule"],function($, awesome) { |
2876 | + |
2877 | + awesome.myAwesomeMethod(); //prints "Hello there!" |
2878 | +}); |
2879 | +\endcode |
2880 | + |
2881 | +The UI modules can depend on the API modules and other UI modules. |
2882 | +The API modules can depend on other API modules. |
2883 | +Circular dependencies should of course be avoided. |
2884 | + |
2885 | +\subsubsection rcApiRemotecontrol api/remotecontrol |
2886 | + |
2887 | +This is the main API module, with no further dependencies on other API modules. |
2888 | + |
2889 | +Its main function is that it provides automatic status updates by periodically polling (by default each second) the |
2890 | +\c status operation of the MainService. Whenever this poll succeeds, the \c serverDataReceived custom event is emitted, |
2891 | +with the JSON response of the server as \p data parameter. Other API modules should use this event, and process |
2892 | +the data in which they are interested. |
2893 | +It also keeps track of StelAction and StelProperty changes, |
2894 | +and emits \c stelActionsChanged and/or \c stelPropertiesChanged, if necessary. Note that it does not process them further, |
2895 | +this is the job of the \ref rcApiActions and \ref rcApiProperties modules, respectively. |
2896 | +When the connection to the server is lost (i.e. the polling returned an error), the \c serverDataError event is sent. |
2897 | + |
2898 | +The other main function is that it provides the \c postCmd method, which is a simple wrapper around an AJAX POST call |
2899 | +that is intended to be used by other modules to send commands to the server. It also includes the \c tr method used |
2900 | +for [translating JS strings](\ref remoteControlWebTranslation). |
2901 | + |
2902 | +Finally, this module also processes the [plugin-specific sections](\ref remoteControlWebStelplugin) on load. |
2903 | + |
2904 | +\subsubsection rcApiActions api/actions |
2905 | + |
2906 | +Processes StelAction related events. Whenever it detects that boolean StelAction was changed, it emits two events: |
2907 | +- A generic event \c stelActionChanged with the \c actionId as a parameter. This can be used when interested in ALL action changes |
2908 | + (like for a action list) |
2909 | +- A specialied event `stelActionChanged:<actionId>` with the \c actionId as part of the event name. |
2910 | + This can be used when listening for a specific action only. |
2911 | + |
2912 | +On the first load of the interface, it loads a list of all actions (using the ActionService \c list operation) and emits the |
2913 | +\c actionListLoaded event when this data is available. |
2914 | + |
2915 | +To execute/toggle an action, it provides the public \c executeAction method, which just requires the action ID as parameter. |
2916 | +To find out whether an action is currently checked, use the \c isChecked method. |
2917 | + |
2918 | +\subsubsection rcApiFlags api/flags |
2919 | + |
2920 | +This is a utility module, which can be used to implement checkboxes for enum flag types, where each checkbox sets a |
2921 | +specific bit of a single value. The module should be constructed with \c new, the constructor takes the parent element of a list of |
2922 | +checkboxes (\c input of type checkbox) and a method which is called back when the internal value changes (i.e. the user clicks a checkbox). It provides the |
2923 | +\c setValue method to set the current value and check the correct checkboxes. The bit value of each \c input should be specified |
2924 | +as its \p value property, in hexadecimal string format (for example `0x0004`) |
2925 | + |
2926 | +\subsubsection rcApiLocation api/location |
2927 | + |
2928 | +Module which connects to the LocationService and the LocationSearchService. |
2929 | +It emits the following events whenever the specified field changed: |
2930 | +\c planetChanged,\c nameChanged, \c countryChanged, \c altitudeChanged, \c latitudeChanged, \c longitudeChanged, \c positionChanged (emitted when either lat or lon changed) |
2931 | + |
2932 | +It also has \c set methods for these fields. |
2933 | +Furthermore, it provides \c performLocationSearch, which searches the predefined locations for a specific search string, |
2934 | +and \c performNearbySearch, which searches predefined locations near a given lat/lon on the current planet. |
2935 | +These methods take a callback parameter to notify the caller of the results. |
2936 | +The \c setLocationById method can then be used to set the location to a result of these 2 methods. |
2937 | + |
2938 | +It also provides a \c loadCountryList and a \c loadPlanetList which load the specified lists and return the results with a callback. |
2939 | + |
2940 | +\subsubsection rcApiProperties api/properties |
2941 | + |
2942 | +Processes StelProperty related things. Like the \ref rcApiActions module, it emits 2 events when it detects a StelProperty changed: |
2943 | +- A generic event \c stelPropertyChanged with the \c propertyId as a parameter. This can be used when interested in ALL property changes |
2944 | + (like for a list) |
2945 | +- A specialied event `stelPropertyChanged:<propertyId>` with the \c propertyId as part of the event name. |
2946 | + This can be used when listening for a specific property only. |
2947 | + |
2948 | +It provides \c getStelProp and \c setStelProp methods which retrieve and set the value of a StelProperty, |
2949 | +and also a \c setStelPropQueued convenience method to batch multiple fast interface changes (e.g. through a slider or spinner) |
2950 | +into a single \c setStelProp call which is only executed after a small time has passed with no changes. |
2951 | + |
2952 | +It also emits the \c propertyListLoaded event when it first loads the full list of StelProperties with their type information. |
2953 | + |
2954 | +\subsubsection rcApiScripts api/scripts |
2955 | + |
2956 | +This module handles script execution (i.e. connection to the ScriptService). It provides the following methods: |
2957 | +- \c loadScriptList - loads the list of all scripts, takes a callback to return this data |
2958 | +- \c runScript - runs the specified script id |
2959 | +- \c runDirectScript - directly runs the given script code |
2960 | +- \c stopScript - stops a currently running script |
2961 | + |
2962 | +It also emits the \c activeScriptChanged event whenever it detects that the current script has changed or started/stopped |
2963 | + |
2964 | +\subsubsection rcApiSearch api/search |
2965 | + |
2966 | +Implements object search functionality, connecting to the ObjectService and the SimbadService. The following methods are provided: |
2967 | +- \c loadObjectTypes - loads the list of object types, takes a callback |
2968 | +- \c loadObjectList - loads the list of objects of a specified type, can return english or localized names |
2969 | +- \c selectObjectByName - selects the object that matches the specified name |
2970 | +- \c focusPosition - focuses the given coordinate (array of 3 numbers) in the J2000 frame |
2971 | +- \c performSearch - performs an object lookup in Stellarium's internal catalog and Simbad. In addition to the search string, |
2972 | + 2 callbacks must be given as parameters: one for the catalog results, and one for the simbad results. If a search is currently running, |
2973 | + it is aborted (meaning the callbacks won't be called for the old searches), allowing this method to be repeatedly called while |
2974 | + the user is typing. The Simbad search is only started after a small interval without typing, to reduce the overhead of the |
2975 | + external web requests. |
2976 | + |
2977 | +While a search is running, it emits \c simbadStateChange events to notify the UI of the current state of the lookup. |
2978 | + |
2979 | +\subsubsection rcApiTime api/time |
2980 | + |
2981 | +Contains time-related functions and conversions, similar to what StelCore does. This module keeps it's own sense of Stellariums current time, |
2982 | +to provide an updated interface even between the \c status polls of the \ref rcApiRemotecontrol module. |
2983 | + |
2984 | +It provides following methods: |
2985 | +- \c getCurrentTime - calculates the best guess to the current Stellarium simulation time. This depends on the information received with the last \c status poll, |
2986 | + the time since the last data was received and the time the last time change was performed |
2987 | +- \c isRealTimeSpeed - true if the simulation time currently flows at the same rate as the real time (1 sec per sec). |
2988 | +- \c jdayToDate - converts a jDay (single number) to Day/Month/Year format, this returns a JS object with \p day, \p month, \p year fields instead |
2989 | + of a JS Date object because of its limitations. |
2990 | +- \c jdayToDate - returns the time component of the given jDay, as a JS object with \p hour, \p minute, \p second fields |
2991 | +- \c dateTimeToJd - converts a time given in Y/M/D-H/MIN/S format to a jDay |
2992 | +- \c dateTimeForRollover - like StelUtils::changeDateTimeForRollover |
2993 | +- \c isTimeUpdatePending - if true, there is a time change which has not yet been sent to the server |
2994 | +- \c increaseTimeRate - increases the Stellarium simulation time rate (like StelCore::increaseTimeSpeed) |
2995 | +- \c decreaseTimeRate - decreases the Stellarium simulation time rate (like StelCore::decreaseTimeSpeed) |
2996 | +- \c isRewind - returns true if the time currently flows backwards (at least at -0.99 sec / sec) |
2997 | +- \c isFastForward - returns true if time currently is flowing faster than real time |
2998 | +- \c isTimeNow - returns true if the current simulation time is very close to the actual system time |
2999 | +- \c isTimeStopped - returns true if the simulation time rate is zero |
3000 | +- \c togglePlayPause - toggles between timerates 0 and 1 sec/sec |
3001 | +- \c setDateNow - sets the simulation time to the current system time |
3002 | +- \c setJDay - sets the time to the specified JDay |
3003 | +- \c setTimeFromTimeObj - sets the time from a "time object", containing both date and time in the following format |
3004 | +\code |
3005 | +{ |
3006 | + date : { |
3007 | + year, month, day |
3008 | + }, |
3009 | + time : { |
3010 | + hour, minute, second |
3011 | + } |
3012 | +} |
3013 | +\endcode |
3014 | +- \c getTimeData - returns the current time data, containing the last response from the server (including timezone info, etc) |
3015 | + The event \c timeDataUpdated is sent whenever this changes. |
3016 | + |
3017 | +\subsubsection rcApiUpdatequeue api/updatequeue |
3018 | + |
3019 | +This implements a simple update queue class that updates the server after a specified interval if the user does nothing else inbetween. |
3020 | +This is used to limit the rate at which updates are sent to the server. The \c UpdateQueue constructor takes an url and a callback for the result, |
3021 | +and when the interface needs to send an update, \c enqueue can be called with the data to send. |
3022 | + |
3023 | +\subsubsection rcApiViewcontrol api/viewcontrol |
3024 | + |
3025 | +Implements the %FOV access and viewport movement methods. Use \c setFOV to set the %FOV, the \c fovChanged event is sent whenever the %FOV changes. |
3026 | +There are \c moveRight, \c moveUp, \c moveUpRight etc. methods that allow the user to move the viewport. To stop the movement, use \c stopMovement. |
3027 | + |
3028 | +\subsubsection rcApiViewoptions api/viewoptions |
3029 | + |
3030 | +Implements the loading of the projection, landscape and skyculture lists. |
3031 | + |
3032 | +\subsubsection rcUiMainui ui/mainui |
3033 | + |
3034 | +This is the main module of the interface. It lists all the other UI modules as a dependency. |
3035 | +It starts of the update look of the \c rcApiRemotecontrol module, handles the automatic generation |
3036 | +of the [special controls](\ref remoteControlWebUIClasses) and [connection of StelProperty controls](\ref remoteControlWebstelproperty), |
3037 | +and performs smooth animation of the time controls. It also keeps track of the current interface tab the user is on, and |
3038 | +restores it when the page is reloaded. |
3039 | + |
3040 | +\subsubsection rcUiActions ui/actions |
3041 | + |
3042 | +Implements the action list and the [StelAction buttons and checkboxes](\ref remoteControlWebstelaction). |
3043 | + |
3044 | +\subsubsection rcUiCombobox ui/combobox |
3045 | + |
3046 | +Implements a custom combobox control, on top of the jQuery UI \c autocomplete control. This is used for example in the location controls. |
3047 | + |
3048 | +\subsubsection rcUiJqueryuifixes ui/jqueryuifixes |
3049 | + |
3050 | +Includes some fixes to the standard jQuery UI control classes, especially for the spinner, to provide a unified |
3051 | +change event, prevent non-numeric input and better touch support. This module is automatically loaded whenever other modules |
3052 | +load the "jquery-ui" module. |
3053 | + |
3054 | +\subsubsection rcUiLocation ui/location |
3055 | + |
3056 | +Implements the location controls, such as the map which can be clicked and the comboboxes for the current location. |
3057 | + |
3058 | +\subsubsection rcUiScripts ui/scripts |
3059 | + |
3060 | +Implements the script list and shows the active script. |
3061 | + |
3062 | +\subsubsection rcUiSearch ui/search |
3063 | + |
3064 | +Implements the object search panel and the quick select buttons. |
3065 | + |
3066 | +\subsubsection rcUiTime ui/time |
3067 | + |
3068 | +Implements the time controls, the \c updateTimeDisplay method is called repeatedly as an animation by the \ref rcUiMainui module. |
3069 | + |
3070 | +\subsubsection rcUiViewcontrol ui/viewcontrol |
3071 | + |
3072 | +Implements the %FOV slider and the "virtual joystick" for the viewport movement. |
3073 | + |
3074 | +\subsubsection rcUiViewoptions ui/viewoptions |
3075 | + |
3076 | +Implements the projection, landscape and skyculture lists, and some minor things related to other view options. |
3077 | +*/ |
3078 | |
3079 | === added directory 'plugins/RemoteControl/resources' |
3080 | === added file 'plugins/RemoteControl/resources/bt_network_templates.tif' |
3081 | Binary files plugins/RemoteControl/resources/bt_network_templates.tif 1970-01-01 00:00:00 +0000 and plugins/RemoteControl/resources/bt_network_templates.tif 2016-06-03 22:29:41 +0000 differ |
3082 | === added file 'plugins/RemoteControl/resources/bt_remote_off.png' |
3083 | Binary files plugins/RemoteControl/resources/bt_remote_off.png 1970-01-01 00:00:00 +0000 and plugins/RemoteControl/resources/bt_remote_off.png 2016-06-03 22:29:41 +0000 differ |
3084 | === added file 'plugins/RemoteControl/resources/bt_remote_on.png' |
3085 | Binary files plugins/RemoteControl/resources/bt_remote_on.png 1970-01-01 00:00:00 +0000 and plugins/RemoteControl/resources/bt_remote_on.png 2016-06-03 22:29:41 +0000 differ |
3086 | === added directory 'plugins/RemoteControl/src' |
3087 | === added file 'plugins/RemoteControl/src/APIController.cpp' |
3088 | --- plugins/RemoteControl/src/APIController.cpp 1970-01-01 00:00:00 +0000 |
3089 | +++ plugins/RemoteControl/src/APIController.cpp 2016-06-03 22:29:41 +0000 |
3090 | @@ -0,0 +1,141 @@ |
3091 | +/* |
3092 | + * Stellarium Remote Control plugin |
3093 | + * Copyright (C) 2015 Florian Schaukowitsch |
3094 | + * |
3095 | + * This program is free software; you can redistribute it and/or |
3096 | + * modify it under the terms of the GNU General Public License |
3097 | + * as published by the Free Software Foundation; either version 2 |
3098 | + * of the License, or (at your option) any later version. |
3099 | + * |
3100 | + * This program is distributed in the hope that it will be useful, |
3101 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3102 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3103 | + * GNU General Public License for more details. |
3104 | + * |
3105 | + * You should have received a copy of the GNU General Public License |
3106 | + * along with this program; if not, write to the Free Software |
3107 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
3108 | + */ |
3109 | + |
3110 | +#include "APIController.hpp" |
3111 | +#include <QJsonDocument> |
3112 | + |
3113 | + |
3114 | +APIController::APIController(int prefixLength, QObject* parent) : HttpRequestHandler(parent), m_prefixLength(prefixLength) |
3115 | +{ |
3116 | + |
3117 | +} |
3118 | + |
3119 | +APIController::~APIController() |
3120 | +{ |
3121 | + |
3122 | +} |
3123 | + |
3124 | +void APIController::update(double deltaTime) |
3125 | +{ |
3126 | + mutex.lock(); |
3127 | + foreach(AbstractAPIService* service, m_serviceMap) |
3128 | + { |
3129 | + service->update(deltaTime); |
3130 | + } |
3131 | + mutex.unlock(); |
3132 | +} |
3133 | + |
3134 | +void APIController::registerService(AbstractAPIService *service) |
3135 | +{ |
3136 | + m_serviceMap.insert(service->serviceName(), service); |
3137 | +} |
3138 | + |
3139 | +void APIController::service(HttpRequest &request, HttpResponse &response) |
3140 | +{ |
3141 | + //disable caching by default for services |
3142 | + response.setHeader("Cache-Control","no-cache"); |
3143 | + //default content type is text |
3144 | + response.setHeader("Content-Type","text/plain"); |
3145 | + |
3146 | + //use the raw path here |
3147 | + QByteArray path = request.getRawPath(); |
3148 | + QByteArray pathWithoutPrefix = path.right(path.size()-m_prefixLength); |
3149 | + |
3150 | + int slashIdx = pathWithoutPrefix.indexOf('/'); |
3151 | + |
3152 | + QByteArray serviceString = pathWithoutPrefix; |
3153 | + QByteArray operation; |
3154 | + if(slashIdx>=0) |
3155 | + { |
3156 | + serviceString = pathWithoutPrefix.mid(0,slashIdx); |
3157 | + operation = pathWithoutPrefix.mid(slashIdx+1); |
3158 | + } |
3159 | + |
3160 | + //try to find service |
3161 | + //the mutex here is to prevent a very strange crash I had, in which sv is an invalid pointer (but m_serviceMap is ok) |
3162 | + //probably caused by the foreach loop in update in the main thread? |
3163 | + mutex.lock(); |
3164 | + ServiceMap::iterator it = m_serviceMap.find(serviceString); |
3165 | + if(it!=m_serviceMap.end()) |
3166 | + { |
3167 | + AbstractAPIService* sv = *it; |
3168 | + mutex.unlock(); |
3169 | + |
3170 | + //create the response object |
3171 | + APIServiceResponse apiresponse; |
3172 | + if(request.getMethod()=="GET") |
3173 | + { |
3174 | +#ifdef FORCE_THREADED_SERVICES |
3175 | + apiresponse = sv->get(operation, request.getParameterMap()); |
3176 | +#else |
3177 | + if(sv->supportsThreadedOperation()) |
3178 | + { |
3179 | + apiresponse = sv->get(operation, request.getParameterMap()); |
3180 | + } |
3181 | + else |
3182 | + { |
3183 | + //invoke it in the main thread! |
3184 | + QMetaObject::invokeMethod(sv,"get",Qt::BlockingQueuedConnection, |
3185 | + Q_RETURN_ARG(APIServiceResponse, apiresponse), |
3186 | + Q_ARG(QByteArray, operation), |
3187 | + Q_ARG(APIParameters, request.getParameterMap())); |
3188 | + } |
3189 | +#endif |
3190 | + apiresponse.applyResponse(&response); |
3191 | + } |
3192 | + else if (request.getMethod()=="POST") |
3193 | + { |
3194 | +#ifdef FORCE_THREADED_SERVICES |
3195 | + apiresponse = sv->post(operation, request.getParameterMap(), request.getBody()); |
3196 | +#else |
3197 | + if(sv->supportsThreadedOperation()) |
3198 | + { |
3199 | + apiresponse = sv->post(operation, request.getParameterMap(), request.getBody()); |
3200 | + } |
3201 | + else |
3202 | + { |
3203 | + QMetaObject::invokeMethod(sv,"post",Qt::BlockingQueuedConnection, |
3204 | + Q_RETURN_ARG(APIServiceResponse, apiresponse), |
3205 | + Q_ARG(QByteArray, operation), |
3206 | + Q_ARG(APIParameters, request.getParameterMap()), |
3207 | + Q_ARG(QByteArray, request.getBody())); |
3208 | + } |
3209 | +#endif |
3210 | + apiresponse.applyResponse(&response); |
3211 | + } |
3212 | + else |
3213 | + { |
3214 | + response.setStatus(405,"Method Not allowed"); |
3215 | + QString str(QStringLiteral("Method %1 not allowed for service %2")); |
3216 | + response.write(str.arg(QString::fromLatin1(request.getMethod())).arg(QString::fromUtf8(pathWithoutPrefix)).toUtf8(),true); |
3217 | + } |
3218 | + } |
3219 | + else |
3220 | + { |
3221 | + mutex.unlock(); |
3222 | + response.setStatus(400,"Bad Request"); |
3223 | + QString str(QStringLiteral("Unknown service: '%1'\n\nAvailable services:\n").arg(QString::fromUtf8(pathWithoutPrefix))); |
3224 | + for(ServiceMap::iterator it = m_serviceMap.begin();it!=m_serviceMap.end();++it) |
3225 | + { |
3226 | + str.append(QString::fromUtf8(it.key())); |
3227 | + str.append("\n"); |
3228 | + } |
3229 | + response.write(str.toUtf8(),true); |
3230 | + } |
3231 | +} |
3232 | |
3233 | === added file 'plugins/RemoteControl/src/APIController.hpp' |
3234 | --- plugins/RemoteControl/src/APIController.hpp 1970-01-01 00:00:00 +0000 |
3235 | +++ plugins/RemoteControl/src/APIController.hpp 2016-06-03 22:29:41 +0000 |
3236 | @@ -0,0 +1,64 @@ |
3237 | +/* |
3238 | + * Stellarium Remote Control plugin |
3239 | + * Copyright (C) 2015 Florian Schaukowitsch |
3240 | + * |
3241 | + * This program is free software; you can redistribute it and/or |
3242 | + * modify it under the terms of the GNU General Public License |
3243 | + * as published by the Free Software Foundation; either version 2 |
3244 | + * of the License, or (at your option) any later version. |
3245 | + * |
3246 | + * This program is distributed in the hope that it will be useful, |
3247 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3248 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3249 | + * GNU General Public License for more details. |
3250 | + * |
3251 | + * You should have received a copy of the GNU General Public License |
3252 | + * along with this program; if not, write to the Free Software |
3253 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
3254 | + */ |
3255 | + |
3256 | +#ifndef APIHANDLER_HPP_ |
3257 | +#define APIHANDLER_HPP_ |
3258 | + |
3259 | +#include "httpserver/httprequesthandler.h" |
3260 | +#include "AbstractAPIService.hpp" |
3261 | + |
3262 | +#include <QMutex> |
3263 | + |
3264 | +//! @ingroup remoteControl |
3265 | +//! This class handles the API-specific requests and dispatches them to the correct AbstractAPISerice implementation. |
3266 | +//! Services are registered using registerService(). |
3267 | +//! To see the default services used, see the RequestHandler::RequestHandler constructor. |
3268 | +class APIController : public HttpRequestHandler |
3269 | +{ |
3270 | + Q_OBJECT |
3271 | +public: |
3272 | + //! Constructs an APIController |
3273 | + //! @param prefixLength Determines how many characters to strip from the front of the request path |
3274 | + //! @param parent passed on to QObject constructor |
3275 | + APIController(int prefixLength, QObject* parent = 0); |
3276 | + virtual ~APIController(); |
3277 | + |
3278 | + //! Should be called each frame from the main thread, like from StelModule::update. |
3279 | + //! Passed on to each AbstractAPIService::update method for optional processing. |
3280 | + void update(double deltaTime); |
3281 | + |
3282 | + //! Handles an API-specific request. It finds out which AbstractAPIService to use |
3283 | + //! depending on the service name (first part of path until slash). An error is returned for invalid requests. |
3284 | + //! If a service was found, the request is passed on to its AbstractAPIService::get or AbstractAPIService::post |
3285 | + //! method depending on the HTTP request type. |
3286 | + //! If AbstractAPIService::supportsThreadedOperation is false, these methods are called in the Stellarium main thread |
3287 | + //! using QMetaObject::invokeMethod, otherwise they are directly executed in the current thread (HTTP worker thread). |
3288 | + virtual void service(HttpRequest& request, HttpResponse& response); |
3289 | + |
3290 | + //! Registers a service with the APIController. |
3291 | + //! The AbstractAPIService::serviceName() determines the request path of the service. |
3292 | + void registerService(AbstractAPIService* service); |
3293 | +private: |
3294 | + int m_prefixLength; |
3295 | + typedef QMap<QByteArray,AbstractAPIService*> ServiceMap; |
3296 | + ServiceMap m_serviceMap; |
3297 | + QMutex mutex; |
3298 | +}; |
3299 | + |
3300 | +#endif |
3301 | |
3302 | === added file 'plugins/RemoteControl/src/AbstractAPIService.cpp' |
3303 | --- plugins/RemoteControl/src/AbstractAPIService.cpp 1970-01-01 00:00:00 +0000 |
3304 | +++ plugins/RemoteControl/src/AbstractAPIService.cpp 2016-06-03 22:29:41 +0000 |
3305 | @@ -0,0 +1,159 @@ |
3306 | +/* |
3307 | + * Stellarium Remote Control plugin |
3308 | + * Copyright (C) 2015 Florian Schaukowitsch |
3309 | + * |
3310 | + * This program is free software; you can redistribute it and/or |
3311 | + * modify it under the terms of the GNU General Public License |
3312 | + * as published by the Free Software Foundation; either version 2 |
3313 | + * of the License, or (at your option) any later version. |
3314 | + * |
3315 | + * This program is distributed in the hope that it will be useful, |
3316 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3317 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3318 | + * GNU General Public License for more details. |
3319 | + * |
3320 | + * You should have received a copy of the GNU General Public License |
3321 | + * along with this program; if not, write to the Free Software |
3322 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
3323 | + */ |
3324 | + |
3325 | +#include "AbstractAPIService.hpp" |
3326 | +#include <QJsonDocument> |
3327 | + |
3328 | +#include "httpserver/httpresponse.h" |
3329 | + |
3330 | +int APIServiceResponse::metaTypeId = qRegisterMetaType<APIServiceResponse>(); |
3331 | +int APIServiceResponse::parametersMetaTypeId = qRegisterMetaType<APIParameters>(); |
3332 | + |
3333 | +void APIServiceResponse::setHeader(const QByteArray &name, const QByteArray &val) |
3334 | +{ |
3335 | + headers.insert(name,val); |
3336 | +} |
3337 | + |
3338 | +void APIServiceResponse::setHeader(const QByteArray &name, const int val) |
3339 | +{ |
3340 | + headers.insert(name,QByteArray::number(val)); |
3341 | +} |
3342 | + |
3343 | +void APIServiceResponse::setStatus(int status, const QByteArray &text) |
3344 | +{ |
3345 | + this->status = status; |
3346 | + this->statusText = text; |
3347 | +} |
3348 | + |
3349 | +void APIServiceResponse::applyResponse(HttpResponse *response) const |
3350 | +{ |
3351 | + if(status != -1) |
3352 | + { |
3353 | + response->setStatus(status,statusText); |
3354 | + } |
3355 | + |
3356 | + //apply headers |
3357 | + response->getHeaders().unite(headers); |
3358 | + |
3359 | + //send response data, if any |
3360 | + if(responseData.isEmpty()) |
3361 | + { |
3362 | + response->getHeaders().clear(); |
3363 | + response->setStatus(500,"Internal Server Error"); |
3364 | + response->write("Service provided no response",true); |
3365 | + } |
3366 | + response->write(responseData,true); |
3367 | +} |
3368 | + |
3369 | +void APIServiceResponse::setData(const QByteArray &data) |
3370 | +{ |
3371 | + this->responseData = data; |
3372 | +} |
3373 | + |
3374 | +void APIServiceResponse::appendData(const QByteArray &data) |
3375 | +{ |
3376 | + this->responseData.append(data); |
3377 | +} |
3378 | + |
3379 | +void APIServiceResponse::writeRequestError(const QByteArray &msg) |
3380 | +{ |
3381 | + setStatus(400,"Bad Request"); |
3382 | + responseData = msg; |
3383 | +} |
3384 | + |
3385 | +void APIServiceResponse::writeJSON(const QJsonDocument &doc) |
3386 | +{ |
3387 | +#ifdef QT_NO_DEBUG |
3388 | + //Use compact JSON format for release builds for smaller files |
3389 | + QByteArray data = doc.toJson(QJsonDocument::Compact); |
3390 | +#else |
3391 | + //Use indented JSON format in debug builds for easier human reading |
3392 | + QByteArray data = doc.toJson(QJsonDocument::Indented); |
3393 | +#endif |
3394 | + //setHeader("Content-Length",data.size()); |
3395 | + setHeader("Content-Type","application/json; charset=utf-8"); |
3396 | + setData(data); |
3397 | +} |
3398 | + |
3399 | + |
3400 | +void AbstractAPIService::update(double deltaTime) |
3401 | +{ |
3402 | + Q_UNUSED(deltaTime); |
3403 | +} |
3404 | + |
3405 | +bool AbstractAPIService::supportsThreadedOperation() const |
3406 | +{ |
3407 | + return false; |
3408 | +} |
3409 | + |
3410 | +APIServiceResponse AbstractAPIService::get(const QByteArray &operation, const APIParameters ¶meters) |
3411 | +{ |
3412 | + APIServiceResponse response; |
3413 | + getImpl(operation,parameters,response); |
3414 | + return response; |
3415 | +} |
3416 | + |
3417 | +APIServiceResponse AbstractAPIService::post(const QByteArray &operation, const APIParameters ¶meters, const QByteArray &data) |
3418 | +{ |
3419 | + APIServiceResponse response; |
3420 | + postImpl(operation,parameters,data,response); |
3421 | + return response; |
3422 | +} |
3423 | + |
3424 | +#ifdef FORCE_THREADED_SERVICES |
3425 | +const Qt::ConnectionType AbstractAPIService::SERVICE_DEFAULT_INVOKETYPE = Qt::BlockingQueuedConnection; |
3426 | +#else |
3427 | +const Qt::ConnectionType AbstractAPIService::SERVICE_DEFAULT_INVOKETYPE = Qt::DirectConnection; |
3428 | +#endif |
3429 | + |
3430 | +void AbstractAPIService::getImpl(const QByteArray& operation, const QMultiMap<QByteArray, QByteArray> ¶meters, APIServiceResponse &response) |
3431 | +{ |
3432 | + Q_UNUSED(operation); |
3433 | + Q_UNUSED(parameters); |
3434 | + |
3435 | + response.setStatus(405,"Method Not allowed"); |
3436 | + QString str(QStringLiteral("Method GET not allowed for service %2")); |
3437 | + |
3438 | + response.setData(str.arg(QString::fromLatin1(serviceName())).toLatin1()); |
3439 | +} |
3440 | + |
3441 | +void AbstractAPIService::postImpl(const QByteArray& operation, const QMultiMap<QByteArray, QByteArray> ¶meters, const QByteArray &data, APIServiceResponse &response) |
3442 | +{ |
3443 | + Q_UNUSED(operation); |
3444 | + Q_UNUSED(parameters); |
3445 | + Q_UNUSED(data); |
3446 | + |
3447 | + response.setStatus(405,"Method Not allowed"); |
3448 | + QString str(QStringLiteral("Method POST not allowed for service %2")); |
3449 | + response.setData(str.arg(QString::fromLatin1(serviceName())).toLatin1()); |
3450 | +} |
3451 | + |
3452 | + |
3453 | +QString AbstractAPIService::wrapHtml(QString &text, const QString &title) const |
3454 | +{ |
3455 | + const QString head = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n" |
3456 | + "<html><head>\n" |
3457 | + "<title>" + title + "</title>\n" |
3458 | + "<link type=\"text/css\" rel=\"stylesheet\" href=\"/iframestyle.css\">\n" |
3459 | + "<base target=\"_blank\">\n" |
3460 | + "</head><body>\n"; |
3461 | + const QString tail = "</body></html>"; |
3462 | + |
3463 | + return text.prepend(head).append(tail); |
3464 | +} |
3465 | |
3466 | === added file 'plugins/RemoteControl/src/AbstractAPIService.hpp' |
3467 | --- plugins/RemoteControl/src/AbstractAPIService.hpp 1970-01-01 00:00:00 +0000 |
3468 | +++ plugins/RemoteControl/src/AbstractAPIService.hpp 2016-06-03 22:29:41 +0000 |
3469 | @@ -0,0 +1,160 @@ |
3470 | +/* |
3471 | + * Stellarium Remote Control plugin |
3472 | + * Copyright (C) 2015 Florian Schaukowitsch |
3473 | + * |
3474 | + * This program is free software; you can redistribute it and/or |
3475 | + * modify it under the terms of the GNU General Public License |
3476 | + * as published by the Free Software Foundation; either version 2 |
3477 | + * of the License, or (at your option) any later version. |
3478 | + * |
3479 | + * This program is distributed in the hope that it will be useful, |
3480 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3481 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3482 | + * GNU General Public License for more details. |
3483 | + * |
3484 | + * You should have received a copy of the GNU General Public License |
3485 | + * along with this program; if not, write to the Free Software |
3486 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
3487 | + */ |
3488 | + |
3489 | +#ifndef ABSTRACTAPISERVICE_HPP_ |
3490 | +#define ABSTRACTAPISERVICE_HPP_ |
3491 | + |
3492 | +#include <QByteArray> |
3493 | +#include <QMap> |
3494 | +#include <QObject> |
3495 | + |
3496 | +//Uncomment to force each service to run in the HTTP handling threads themselves, like the initial versions |
3497 | +//#define FORCE_THREADED_SERVICES |
3498 | + |
3499 | +class HttpResponse; |
3500 | +class APIController; |
3501 | + |
3502 | +//! \addtogroup remoteControl |
3503 | +//! @{ |
3504 | + |
3505 | +//! Thread-safe version of HttpResponse that can be passed around through QMetaObject::invokeMethod. |
3506 | +//! It contains the data that will be sent back to the client in the HTTP thread, when control returns to the APIController. |
3507 | +struct APIServiceResponse |
3508 | +{ |
3509 | +public: |
3510 | + //! Constructs an invalid response |
3511 | + APIServiceResponse() : status(-1) |
3512 | + { |
3513 | + |
3514 | + } |
3515 | + |
3516 | + //! Sets a specific HTTP header to the specified value |
3517 | + void setHeader(const QByteArray& name, const QByteArray& val); |
3518 | + //! Shortcut for int header values |
3519 | + void setHeader(const QByteArray& name, const int val); |
3520 | + //! Sets the HTTP status type and status text |
3521 | + void setStatus(int status, const QByteArray& text); |
3522 | + |
3523 | + //! Replaces the current return data |
3524 | + void setData(const QByteArray& data); |
3525 | + //! Appends to the current return data |
3526 | + void appendData(const QByteArray& data); |
3527 | + |
3528 | + //! Sets the HTTP status to 400, and sets the response data to the message |
3529 | + void writeRequestError(const QByteArray& msg); |
3530 | + //! Sets the Content-Type to "application/json" and serializes the given document |
3531 | + //! into JSON text format |
3532 | + void writeJSON(const QJsonDocument& doc); |
3533 | + |
3534 | +private: |
3535 | + int status; |
3536 | + QByteArray statusText; |
3537 | + QMap<QByteArray,QByteArray> headers; |
3538 | + QByteArray responseData; |
3539 | + |
3540 | + //! Applies the data in this APIServiceResponse onto the HttpResponse |
3541 | + //! Must be called in the HTTP thread, done by APIController |
3542 | + void applyResponse(HttpResponse* response) const; |
3543 | + |
3544 | + static int metaTypeId; |
3545 | + static int parametersMetaTypeId; |
3546 | + friend class APIController; |
3547 | + |
3548 | +}; |
3549 | + |
3550 | +//! Defines the HTTP request parameters for the service |
3551 | +typedef QMultiMap<QByteArray, QByteArray> APIParameters; |
3552 | + |
3553 | +Q_DECLARE_METATYPE(APIServiceResponse) |
3554 | +Q_DECLARE_METATYPE(APIParameters) |
3555 | + |
3556 | +//! Abstract base class for all \ref remoteControl service implementations. Different implementations of this class are mapped to |
3557 | +//! different HTTP request paths. For each API request, the APIController finds out which service to use, and calls its get() or post() method. |
3558 | +class AbstractAPIService : public QObject |
3559 | +{ |
3560 | + Q_OBJECT |
3561 | +public: |
3562 | + //! Abstract constructor. The service name is used by the APIController for request path mapping. |
3563 | + AbstractAPIService(const QByteArray& serviceName, QObject* parent = 0) : QObject(parent), m_serviceName(serviceName) |
3564 | + { |
3565 | + |
3566 | + } |
3567 | + |
3568 | + virtual ~AbstractAPIService() { } |
3569 | + |
3570 | + //! Returns the service name, used for request path mapping by the APIController |
3571 | + QByteArray serviceName() { return m_serviceName; } |
3572 | + |
3573 | + //! Return true if the service can safely be run in the HTTP handler thread, |
3574 | + //! instead of having to queue it into the Stellarium main thread. |
3575 | + //! Default implementation returns false, i.e. no special threading precautions have to be used |
3576 | + //! in the get() and post() implementation. |
3577 | + //! @warning If the macro \c FORCE_THREADED_SERVICES is set, all services will be run |
3578 | + //! in the HTTP threads for testing, and this method will be ignored. |
3579 | + virtual bool supportsThreadedOperation() const; |
3580 | + |
3581 | + //! Called in the main thread each frame. Default implementation does nothing. |
3582 | + //! Can be used for ongoing actions, for example movement control. |
3583 | + virtual void update(double deltaTime); |
3584 | + |
3585 | + //! Wrapper around getImpl(), constructs an APIServiceResponse object for the response and passes it on |
3586 | + //! @note The thread this is called in depends on the supportThreadedOperation() return value |
3587 | + Q_INVOKABLE APIServiceResponse get(const QByteArray &operation, const APIParameters ¶meters); |
3588 | + //! Wrapper around postImpl(), constructs an APIServiceResponse object for the response and passes it on |
3589 | + //! @note The thread this is called in depends on the supportThreadedOperation() return value |
3590 | + Q_INVOKABLE APIServiceResponse post(const QByteArray &operation, const APIParameters ¶meters, const QByteArray& data); |
3591 | + |
3592 | +protected: |
3593 | + //! Subclasses should implement this to define reactions to HTTP GET requests. |
3594 | + //! GET requests generally should only query data or program state, and not change it. |
3595 | + //! If there is an error with the request, use APIServiceResponse::writeRequestError to notify the client. |
3596 | + //! @param operation The operation string of the request (i.e. the part of the request URL after the service name, without parameters) |
3597 | + //! @param parameters The extracted service parameters (extracted from the URL) |
3598 | + //! @param response The response object, write your response into this |
3599 | + //! @note The thread this is called in depends on the supportThreadedOperation() return value |
3600 | + virtual void getImpl(const QByteArray& operation, const APIParameters& parameters, APIServiceResponse& response); |
3601 | + //! Subclasses should implement this to define reactions to HTTP POST requests. |
3602 | + //! POST requests generally should change data or perform some action. |
3603 | + //! If there is an error with the request, use APIServiceResponse::writeRequestError to notify the client. |
3604 | + //! @param operation The operation string of the request (i.e. the part of the request URL after the service name, without parameters) |
3605 | + //! @param parameters The extracted service parameters (extracted from the URL, and form data, if applicable) |
3606 | + //! @param data The unmodified data as sent from the client |
3607 | + //! @param response The response object, write your response into this |
3608 | + //! @note The thread this is called in depends on the supportThreadedOperation() return value |
3609 | + virtual void postImpl(const QByteArray& operation, const APIParameters& parameters, const QByteArray& data, APIServiceResponse& response); |
3610 | + |
3611 | + //! This defines the connection type QMetaObject::invokeMethod has to use inside a service: either Qt::DirectConnection for main thread handling, or |
3612 | + //! Qt::BlockingQueuedConnection for HTTP thread handling |
3613 | + static const Qt::ConnectionType SERVICE_DEFAULT_INVOKETYPE; |
3614 | + |
3615 | + //! Because the HTML descriptions in Stellarium are often not compatible |
3616 | + //! with "clean" HTML5 which is used for the main interface, |
3617 | + //! this method can be used to explicitely set the doctype |
3618 | + //! to 4.01 transitional for better results, and include the stylesheet |
3619 | + //! \c iframestyle.css |
3620 | + //! @param text The text to wrap with HTML document tags |
3621 | + //! @param title The title of the page |
3622 | + QString wrapHtml(QString& text, const QString& title) const; |
3623 | +private: |
3624 | + QByteArray m_serviceName; |
3625 | +}; |
3626 | + |
3627 | +//! @} |
3628 | + |
3629 | +#endif |
3630 | |
3631 | === added file 'plugins/RemoteControl/src/CMakeLists.txt' |
3632 | --- plugins/RemoteControl/src/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
3633 | +++ plugins/RemoteControl/src/CMakeLists.txt 2016-06-03 22:29:41 +0000 |
3634 | @@ -0,0 +1,78 @@ |
3635 | +INCLUDE_DIRECTORIES(. gui qtwebapp) |
3636 | +LINK_DIRECTORIES(${BUILD_DIR}/src) |
3637 | + |
3638 | +SET(QtWebApp_SRCS |
3639 | + qtwebapp/httpserver/httpconnectionhandler.cpp |
3640 | + qtwebapp/httpserver/httpconnectionhandler.h |
3641 | + qtwebapp/httpserver/httpconnectionhandlerpool.cpp |
3642 | + qtwebapp/httpserver/httpconnectionhandlerpool.h |
3643 | + qtwebapp/httpserver/httpcookie.cpp |
3644 | + qtwebapp/httpserver/httpcookie.h |
3645 | + qtwebapp/httpserver/httpglobal.cpp |
3646 | + qtwebapp/httpserver/httpglobal.h |
3647 | + qtwebapp/httpserver/httplistener.cpp |
3648 | + qtwebapp/httpserver/httplistener.h |
3649 | + qtwebapp/httpserver/httprequest.cpp |
3650 | + qtwebapp/httpserver/httprequest.h |
3651 | + qtwebapp/httpserver/httprequesthandler.cpp |
3652 | + qtwebapp/httpserver/httprequesthandler.h |
3653 | + qtwebapp/httpserver/httpresponse.cpp |
3654 | + qtwebapp/httpserver/httpresponse.h |
3655 | + qtwebapp/httpserver/staticfilecontroller.cpp |
3656 | + qtwebapp/httpserver/staticfilecontroller.h |
3657 | + |
3658 | + qtwebapp/templateengine/template.cpp |
3659 | + qtwebapp/templateengine/template.h |
3660 | + qtwebapp/templateengine/templateglobal.h |
3661 | +) |
3662 | + |
3663 | +SET(RemoteControl_SRCS |
3664 | + AbstractAPIService.hpp |
3665 | + AbstractAPIService.cpp |
3666 | + APIController.hpp |
3667 | + APIController.cpp |
3668 | + MainService.hpp |
3669 | + MainService.cpp |
3670 | + ObjectService.hpp |
3671 | + ObjectService.cpp |
3672 | + LocationService.hpp |
3673 | + LocationService.cpp |
3674 | + LocationSearchService.hpp |
3675 | + LocationSearchService.cpp |
3676 | + RemoteControl.hpp |
3677 | + RemoteControl.cpp |
3678 | + RequestHandler.hpp |
3679 | + RequestHandler.cpp |
3680 | + ScriptService.hpp |
3681 | + ScriptService.cpp |
3682 | + SimbadService.hpp |
3683 | + SimbadService.cpp |
3684 | + StelActionService.hpp |
3685 | + StelActionService.cpp |
3686 | + StelPropertyService.hpp |
3687 | + StelPropertyService.cpp |
3688 | + ViewService.hpp |
3689 | + ViewService.cpp |
3690 | + gui/RemoteControlDialog.hpp |
3691 | + gui/RemoteControlDialog.cpp |
3692 | +) |
3693 | + |
3694 | +SET(RemoteControl_UIS |
3695 | + gui/remoteControlDialog.ui |
3696 | +) |
3697 | + |
3698 | +QT5_WRAP_UI(RemoteControl_UIS_H ${RemoteControl_UIS}) |
3699 | + |
3700 | +################# compiles resources files ############ |
3701 | +SET(RemoteControl_RES ../RemoteControl.qrc) |
3702 | +QT5_ADD_RESOURCES(RemoteControl_RES_CXX ${RemoteControl_RES}) |
3703 | + |
3704 | +SET(extLinkerOption ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${OPENGL_LIBRARIES}) |
3705 | + |
3706 | +ADD_LIBRARY(RemoteControl-static STATIC ${RemoteControl_SRCS} ${RemoteControl_RES_CXX} ${RemoteControl_UIS_H} ${QtWebApp_SRCS}) |
3707 | +QT5_USE_MODULES(RemoteControl-static Core Network Widgets) |
3708 | +# The library target "RemoteControl-static" has a default OUTPUT_NAME of "RemoteControl-static", so change it. |
3709 | +SET_TARGET_PROPERTIES(RemoteControl-static PROPERTIES OUTPUT_NAME "RemoteControl") |
3710 | +TARGET_LINK_LIBRARIES(RemoteControl-static ${extLinkerOption}) |
3711 | +SET_TARGET_PROPERTIES(RemoteControl-static PROPERTIES COMPILE_FLAGS "-DQT_STATICPLUGIN") |
3712 | +ADD_DEPENDENCIES(AllStaticPlugins RemoteControl-static) |
3713 | |
3714 | === added file 'plugins/RemoteControl/src/LocationSearchService.cpp' |
3715 | --- plugins/RemoteControl/src/LocationSearchService.cpp 1970-01-01 00:00:00 +0000 |
3716 | +++ plugins/RemoteControl/src/LocationSearchService.cpp 2016-06-03 22:29:41 +0000 |
3717 | @@ -0,0 +1,104 @@ |
3718 | +/* |
3719 | + * Stellarium Remote Control plugin |
3720 | + * Copyright (C) 2015 Florian Schaukowitsch |
3721 | + * |
3722 | + * This program is free software; you can redistribute it and/or |
3723 | + * modify it under the terms of the GNU General Public License |
3724 | + * as published by the Free Software Foundation; either version 2 |
3725 | + * of the License, or (at your option) any later version. |
3726 | + * |
3727 | + * This program is distributed in the hope that it will be useful, |
3728 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3729 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3730 | + * GNU General Public License for more details. |
3731 | + * |
3732 | + * You should have received a copy of the GNU General Public License |
3733 | + * along with this program; if not, write to the Free Software |
3734 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
3735 | + */ |
3736 | + |
3737 | +#include "LocationSearchService.hpp" |
3738 | + |
3739 | +#include "StelApp.hpp" |
3740 | +#include "StelCore.hpp" |
3741 | +#include "StelModuleMgr.hpp" |
3742 | +#include "StelLocationMgr.hpp" |
3743 | + |
3744 | +#include <QJsonArray> |
3745 | +#include <QJsonDocument> |
3746 | +#include <QJsonObject> |
3747 | +#include <QRegExp> |
3748 | + |
3749 | +LocationSearchService::LocationSearchService(const QByteArray &serviceName, QObject *parent) |
3750 | + : AbstractAPIService(serviceName,parent), locMgr(LocationList()) |
3751 | +{ |
3752 | + //this is run in the main thread |
3753 | + connect(&StelApp::getInstance().getLocationMgr(), SIGNAL(locationListChanged()), this, SLOT(mainLocationManagerUpdated())); |
3754 | + mainLocationManagerUpdated(); |
3755 | +} |
3756 | + |
3757 | +void LocationSearchService::mainLocationManagerUpdated() |
3758 | +{ |
3759 | + //this is run in the main thread |
3760 | + locMgrMutex.lock(); |
3761 | + //copy the contents of the location manager |
3762 | + locMgr.setLocations(StelApp::getInstance().getLocationMgr().getAll()); |
3763 | + locMgrMutex.unlock(); |
3764 | +} |
3765 | + |
3766 | +void LocationSearchService::getImpl(const QByteArray& operation, const APIParameters ¶meters, APIServiceResponse &response) |
3767 | +{ |
3768 | + if(operation=="search") |
3769 | + { |
3770 | + //parameter must be named "term" to be compatible with jQuery UI autocomplete without further JS code |
3771 | + QString term = QString::fromUtf8(parameters.value("term")); |
3772 | + |
3773 | + if(term.isEmpty()) |
3774 | + { |
3775 | + response.writeRequestError("needs non-empty 'term' parameter"); |
3776 | + return; |
3777 | + } |
3778 | + |
3779 | + //the filtering in the app is provided by QSortFilterProxyModel in the view |
3780 | + //we dont have that luxury, but we make sure the filtering happens in the separate HTTP thread |
3781 | + locMgrMutex.lock(); |
3782 | + LocationMap allItems = locMgr.getAllMap(); |
3783 | + locMgrMutex.unlock(); |
3784 | + |
3785 | + QJsonArray results; |
3786 | + const QList<QString>& list = allItems.keys(); |
3787 | + |
3788 | + //use a regexp in wildcard mode, the app does the same |
3789 | + QRegExp exp(term,Qt::CaseInsensitive, QRegExp::Wildcard); |
3790 | + |
3791 | + for(QList<QString>::const_iterator it = list.begin();it!=list.end();++it) |
3792 | + { |
3793 | + if(it->contains(exp)) |
3794 | + results.append(*it); |
3795 | + } |
3796 | + |
3797 | + response.writeJSON(QJsonDocument(results)); |
3798 | + } |
3799 | + else if(operation=="nearby") |
3800 | + { |
3801 | + QString sPlanet = QString::fromUtf8(parameters.value("planet")); |
3802 | + QString sLatitude = QString::fromUtf8(parameters.value("latitude")); |
3803 | + QString sLongitude = QString::fromUtf8(parameters.value("longitude")); |
3804 | + QString sRadius = QString::fromUtf8(parameters.value("radius")); |
3805 | + |
3806 | + float latitude = sLatitude.toFloat(); |
3807 | + float longitude = sLongitude.toFloat(); |
3808 | + float radius = sRadius.toFloat(); |
3809 | + |
3810 | + locMgrMutex.lock(); |
3811 | + LocationMap results = locMgr.pickLocationsNearby(sPlanet,longitude,latitude,radius); |
3812 | + locMgrMutex.unlock(); |
3813 | + |
3814 | + response.writeJSON(QJsonDocument(QJsonArray::fromStringList(results.keys()))); |
3815 | + } |
3816 | + else |
3817 | + { |
3818 | + //TODO some sort of service description? |
3819 | + response.writeRequestError("unsupported operation. GET: search,nearby"); |
3820 | + } |
3821 | +} |
3822 | |
3823 | === added file 'plugins/RemoteControl/src/LocationSearchService.hpp' |
3824 | --- plugins/RemoteControl/src/LocationSearchService.hpp 1970-01-01 00:00:00 +0000 |
3825 | +++ plugins/RemoteControl/src/LocationSearchService.hpp 2016-06-03 22:29:41 +0000 |
3826 | @@ -0,0 +1,58 @@ |
3827 | +/* |
3828 | + * Stellarium Remote Control plugin |
3829 | + * Copyright (C) 2015 Florian Schaukowitsch |
3830 | + * |
3831 | + * This program is free software; you can redistribute it and/or |
3832 | + * modify it under the terms of the GNU General Public License |
3833 | + * as published by the Free Software Foundation; either version 2 |
3834 | + * of the License, or (at your option) any later version. |
3835 | + * |
3836 | + * This program is distributed in the hope that it will be useful, |
3837 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3838 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3839 | + * GNU General Public License for more details. |
3840 | + * |
3841 | + * You should have received a copy of the GNU General Public License |
3842 | + * along with this program; if not, write to the Free Software |
3843 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
3844 | + */ |
3845 | + |
3846 | +#ifndef LOCATIONSEARCHSERVICE_HPP_ |
3847 | +#define LOCATIONSEARCHSERVICE_HPP_ |
3848 | + |
3849 | +#include "AbstractAPIService.hpp" |
3850 | +#include "StelLocationMgr.hpp" |
3851 | +#include <QMutex> |
3852 | + |
3853 | +//! @ingroup remoteControl |
3854 | +//! Provides predefined location search functionality, using the StelLocationMgr. |
3855 | +//! |
3856 | +//! @see \ref rcLocationSearchService, LocationService |
3857 | +//! @note This service supports threaded operation |
3858 | +class LocationSearchService : public AbstractAPIService |
3859 | +{ |
3860 | + Q_OBJECT |
3861 | +public: |
3862 | + LocationSearchService(const QByteArray& serviceName, QObject* parent = 0); |
3863 | + |
3864 | + virtual ~LocationSearchService() {} |
3865 | + |
3866 | + //! We work on a copy of the StelLocationMgr, to prevent hitches as the web user is typing |
3867 | + //! @returns true |
3868 | + bool supportsThreadedOperation() const Q_DECL_OVERRIDE { return true; } |
3869 | +protected: |
3870 | + //! @brief Implements the GET method. |
3871 | + //! @see \ref rcLocationSearchServiceGET |
3872 | + virtual void getImpl(const QByteArray& operation,const APIParameters& parameters, APIServiceResponse& response) Q_DECL_OVERRIDE; |
3873 | +private slots: |
3874 | + // connected to the main location manager in the main thread |
3875 | + void mainLocationManagerUpdated(); |
3876 | +private: |
3877 | + //the location mgr is actually copied to be used in HTTP threads without blocking the main app |
3878 | + StelLocationMgr locMgr; |
3879 | + QMutex locMgrMutex; |
3880 | +}; |
3881 | + |
3882 | + |
3883 | + |
3884 | +#endif |
3885 | |
3886 | === added file 'plugins/RemoteControl/src/LocationService.cpp' |
3887 | --- plugins/RemoteControl/src/LocationService.cpp 1970-01-01 00:00:00 +0000 |
3888 | +++ plugins/RemoteControl/src/LocationService.cpp 2016-06-03 22:29:41 +0000 |
3889 | @@ -0,0 +1,258 @@ |
3890 | +/* |
3891 | + * Stellarium Remote Control plugin |
3892 | + * Copyright (C) 2015 Florian Schaukowitsch |
3893 | + * |
3894 | + * This program is free software; you can redistribute it and/or |
3895 | + * modify it under the terms of the GNU General Public License |
3896 | + * as published by the Free Software Foundation; either version 2 |
3897 | + * of the License, or (at your option) any later version. |
3898 | + * |
3899 | + * This program is distributed in the hope that it will be useful, |
3900 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
3901 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3902 | + * GNU General Public License for more details. |
3903 | + * |
3904 | + * You should have received a copy of the GNU General Public License |
3905 | + * along with this program; if not, write to the Free Software |
3906 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
3907 | + */ |
3908 | + |
3909 | +#include "LocationService.hpp" |
3910 | + |
3911 | +#include "StelApp.hpp" |
3912 | +#include "StelCore.hpp" |
3913 | +#include "StelFileMgr.hpp" |
3914 | +#include "StelModuleMgr.hpp" |
3915 | +#include "StelLocationMgr.hpp" |
3916 | +#include "StelLocaleMgr.hpp" |
3917 | +#include "StelTranslator.hpp" |
3918 | +#include "SolarSystem.hpp" |
3919 | + |
3920 | +#include <QFileInfo> |
3921 | +#include <QMimeDatabase> |
3922 | +#include <QJsonArray> |
3923 | +#include <QJsonDocument> |
3924 | +#include <QJsonObject> |
3925 | +#include <QStringListModel> |
3926 | + |
3927 | +LocationService::LocationService(const QByteArray &serviceName, QObject *parent) : AbstractAPIService(serviceName,parent) |
3928 | +{ |
3929 | + //this is run in the main thread |
3930 | + core = StelApp::getInstance().getCore(); |
3931 | + locMgr = &StelApp::getInstance().getLocationMgr(); |
3932 | + ssys = GETSTELMODULE(SolarSystem); |
3933 | +} |
3934 | + |
3935 | +void LocationService::getImpl(const QByteArray& operation, const APIParameters ¶meters, APIServiceResponse &response) |
3936 | +{ |
3937 | + if(operation=="list") |
3938 | + { |
3939 | + //for now, this does not return location objects (which would require a much larger data transfer), but only the location strings |
3940 | + //same as in the LocationDialog list |
3941 | + |
3942 | + //TODO not fully thread safe |
3943 | + QJsonArray list = QJsonArray::fromStringList(QStringList(locMgr->getAllMap().keys())); |
3944 | + |
3945 | + response.writeJSON(QJsonDocument(list)); |
3946 | + } |
3947 | + else if(operation == "countrylist") |
3948 | + { |
3949 | + const StelTranslator& trans = *StelTranslator::globalTranslator; |
3950 | + |
3951 | + QStringList allCountries = StelApp::getInstance().getLocaleMgr().getAllCountryNames(); |
3952 | + QJsonArray list; |
3953 | + foreach(QString str, allCountries) |
3954 | + { |
3955 | + QJsonObject obj; |
3956 | + obj.insert("name",str); |
3957 | + obj.insert("name_i18n",trans.qtranslate(str)); |
3958 | + list.append(obj); |
3959 | + } |
3960 | + |
3961 | + response.writeJSON(QJsonDocument(list)); |
3962 | + } |
3963 | + else if(operation == "planetlist") |
3964 | + { |
3965 | + const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator(); |
3966 | + |
3967 | + QStringList allPlanets = ssys->getAllPlanetEnglishNames(); |
3968 | + QJsonArray list; |
3969 | + foreach(QString str, allPlanets) |
3970 | + { |
3971 | + QJsonObject obj; |
3972 | + obj.insert("name",str); |
3973 | + obj.insert("name_i18n",trans.qtranslate(str)); |
3974 | + list.append(obj); |
3975 | + } |
3976 | + |
3977 | + response.writeJSON(QJsonDocument(list)); |
3978 | + } |
3979 | + else if(operation=="planetimage") |
3980 | + { |
3981 | + //return the image file for the specified planet |
3982 | + //logic from LocationDialog |
3983 | + |
3984 | + QString planet = QString::fromUtf8(parameters.value("planet")); |
3985 | + |
3986 | + if(planet.isEmpty()) |
3987 | + { |
3988 | + response.writeRequestError("requires 'planet' parameter"); |
3989 | + return; |
3990 | + } |
3991 | + |
3992 | + |
3993 | + SolarSystem* ssm = GETSTELMODULE(SolarSystem); |
3994 | + PlanetP p = ssm->searchByEnglishName(planet); |
3995 | + if (p) |
3996 | + { |
3997 | + QString path = StelFileMgr::findFile("textures/"+p->getTextMapName()); |
3998 | + QFile file(path); |
3999 | + if (path.isEmpty() || !file.exists()) |
4000 | + { |
4001 | + response.setStatus(404,"not found"); |
4002 | + response.setData("planet image not available"); |
4003 | + qWarning() << "ERROR - could not find planet map for " << planet; |
4004 | + return; |
4005 | + } |
4006 | + |
4007 | + QMimeType mime = QMimeDatabase().mimeTypeForFile(path); |
4008 | + |
4009 | + if(file.open(QIODevice::ReadOnly)) |
4010 | + { |
4011 | + //allow the image to be cached by browser (1 hour) |
4012 | + response.setHeader("Cache-Control","max-age="+QByteArray::number(60*60)); |
4013 | + //response.setHeader("Content-Length",static_cast<int>(file.size())); |
4014 | + if(!mime.isDefault()) |
4015 | + { |
4016 | + response.setHeader("Content-Type", mime.name().toLatin1()); |
4017 | + } |
4018 | + |
4019 | + //load and write data |
4020 | + response.setData(file.readAll()); |
4021 | + } |
4022 | + else |
4023 | + { |
4024 | + response.setStatus(500,"internal server error"); |
4025 | + response.setData("could not open image file"); |
4026 | + } |
4027 | + } |
4028 | + else |
4029 | + { |
4030 | + response.setStatus(404,"not found"); |
4031 | + response.setData("planet id not found"); |
4032 | + qWarning() << "ERROR - could not find planet " << planet; |
4033 | + return; |
4034 | + } |
4035 | + } |
4036 | + else |
4037 | + { |
4038 | + //TODO some sort of service description? |
4039 | + response.writeRequestError("unsupported operation. GET: list, countrylist, planetlist, planetimage"); |
4040 | + } |
4041 | +} |
4042 | + |
4043 | +void LocationService::postImpl(const QByteArray& operation, const APIParameters ¶meters, const QByteArray &data, APIServiceResponse &response) |
4044 | +{ |
4045 | + Q_UNUSED(data); |
4046 | + |
4047 | + if (operation == "setlocationfields") |
4048 | + { |
4049 | + QString id = QString::fromUtf8(parameters.value("id")); |
4050 | + |
4051 | + StelLocation loc; |
4052 | + if(!id.isEmpty()) |
4053 | + { |
4054 | + //if an id is set, ignore everything else |
4055 | + //use an invoke here for reasons |
4056 | + QMetaObject::invokeMethod(locMgr,"locationForString",SERVICE_DEFAULT_INVOKETYPE, |
4057 | + Q_RETURN_ARG(StelLocation, loc), |
4058 | + Q_ARG(QString,id)); |
4059 | + |
4060 | + if(loc.isValid()) |
4061 | + { |
4062 | + //set location |
4063 | + QMetaObject::invokeMethod(core, "moveObserverTo", SERVICE_DEFAULT_INVOKETYPE, |
4064 | + Q_ARG(StelLocation, loc), |
4065 | + Q_ARG(double,0.0) ); |
4066 | + |
4067 | + response.setData("ok"); |
4068 | + return; |
4069 | + } |
4070 | + else |
4071 | + { |
4072 | + response.writeRequestError("invalid location id"); |
4073 | + return; |
4074 | + } |
4075 | + } |
4076 | + |
4077 | + //copy current loc |
4078 | + loc = core->getCurrentLocation(); |
4079 | + |
4080 | + //similar to StelScriptMainAPI::setObserverLocation |
4081 | + QString sLatitude = QString::fromUtf8(parameters.value("latitude")); |
4082 | + QString sLongitude = QString::fromUtf8(parameters.value("longitude")); |
4083 | + QString sAltitude = QString::fromUtf8(parameters.value("altitude")); |
4084 | + |
4085 | + QString name = QString::fromUtf8(parameters.value("name")); |
4086 | + QString country = QString::fromUtf8(parameters.value("country")); |
4087 | + QString planet = QString::fromUtf8(parameters.value("planet")); |
4088 | + |
4089 | + //check each field |
4090 | + bool doneSomething = false; |
4091 | + bool ok = false; |
4092 | + float latitude = sLatitude.toFloat(&ok); |
4093 | + if(ok && latitude != loc.latitude) |
4094 | + { |
4095 | + loc.latitude = latitude; |
4096 | + doneSomething = true; |
4097 | + } |
4098 | + float longitude = sLongitude.toFloat(&ok); |
4099 | + if(ok && longitude != loc.longitude) |
4100 | + { |
4101 | + loc.longitude = longitude; |
4102 | + doneSomething = true; |
4103 | + } |
4104 | + int altitude = sAltitude.toInt(&ok); |
4105 | + if(ok && altitude != loc.altitude) |
4106 | + { |
4107 | + loc.altitude = altitude; |
4108 | + doneSomething = true; |
4109 | + } |
4110 | + if(parameters.contains("name") && name != loc.name) |
4111 | + { |
4112 | + loc.name = name; |
4113 | + doneSomething = true; |
4114 | + } |
4115 | + if(!country.isEmpty() && country != loc.country) |
4116 | + { |
4117 | + loc.country = country; |
4118 | + doneSomething = true; |
4119 | + } |
4120 | + |
4121 | + if(!planet.isEmpty() && loc.planetName != planet) |
4122 | + { |
4123 | + if(ssys->searchByName(planet)) |
4124 | + { |
4125 | + //set planet |
4126 | + loc.planetName = planet; |
4127 | + doneSomething = true; |
4128 | + } |
4129 | + } |
4130 | + |
4131 | + if(doneSomething) |
4132 | + { |
4133 | + //update the core |
4134 | + QMetaObject::invokeMethod(core,"moveObserverTo", SERVICE_DEFAULT_INVOKETYPE, |
4135 | + Q_ARG(StelLocation, loc), |
4136 | + Q_ARG(double, 0.0), |
4137 | + Q_ARG(double, 0.0)); |
4138 | + } |
4139 | + |
4140 | + response.setData("ok"); |
4141 | + } |
4142 | + else |
4143 | + { |
4144 | + //TODO some sort of service description? |
4145 | + response.writeRequestError("unsupported operation. POST: setlocation, setlocationfields"); |
4146 | + } |
4147 | +} |
4148 | |
4149 | === added file 'plugins/RemoteControl/src/LocationService.hpp' |
4150 | --- plugins/RemoteControl/src/LocationService.hpp 1970-01-01 00:00:00 +0000 |
4151 | +++ plugins/RemoteControl/src/LocationService.hpp 2016-06-03 22:29:41 +0000 |
4152 | @@ -0,0 +1,56 @@ |
4153 | +/* |
4154 | + * Stellarium Remote Control plugin |
4155 | + * Copyright (C) 2015 Florian Schaukowitsch |
4156 | + * |
4157 | + * This program is free software; you can redistribute it and/or |
4158 | + * modify it under the terms of the GNU General Public License |
4159 | + * as published by the Free Software Foundation; either version 2 |
4160 | + * of the License, or (at your option) any later version. |
4161 | + * |
4162 | + * This program is distributed in the hope that it will be useful, |
4163 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4164 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4165 | + * GNU General Public License for more details. |
4166 | + * |
4167 | + * You should have received a copy of the GNU General Public License |
4168 | + * along with this program; if not, write to the Free Software |
4169 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
4170 | + */ |
4171 | + |
4172 | +#ifndef LOCATIONSERVICE_HPP_ |
4173 | +#define LOCATIONSERVICE_HPP_ |
4174 | + |
4175 | +#include "AbstractAPIService.hpp" |
4176 | + |
4177 | +class StelCore; |
4178 | +class StelLocationMgr; |
4179 | +class SolarSystem; |
4180 | + |
4181 | +//! @ingroup remoteControl |
4182 | +//! Provides methods to look up location-related information, and change the current location |
4183 | +//! |
4184 | +//! @see \ref rcLocationService, LocationService |
4185 | +class LocationService : public AbstractAPIService |
4186 | +{ |
4187 | + Q_OBJECT |
4188 | +public: |
4189 | + LocationService(const QByteArray& serviceName, QObject* parent = 0); |
4190 | + |
4191 | + virtual ~LocationService() {} |
4192 | + |
4193 | +protected: |
4194 | + //! @brief Implements the HTTP GET requests |
4195 | + //! @see \ref rcLocationServiceGET |
4196 | + virtual void getImpl(const QByteArray& operation,const APIParameters& parameters, APIServiceResponse& response) Q_DECL_OVERRIDE; |
4197 | + //! @brief Implements the HTTP POST requests |
4198 | + //! @see \ref rcLocationServicePOST |
4199 | + virtual void postImpl(const QByteArray &operation, const APIParameters& parameters, const QByteArray &data, APIServiceResponse &response) Q_DECL_OVERRIDE; |
4200 | +private: |
4201 | + StelCore* core; |
4202 | + StelLocationMgr* locMgr; |
4203 | + SolarSystem* ssys; |
4204 | +}; |
4205 | + |
4206 | + |
4207 | + |
4208 | +#endif |
4209 | |
4210 | === added file 'plugins/RemoteControl/src/MainService.cpp' |
4211 | --- plugins/RemoteControl/src/MainService.cpp 1970-01-01 00:00:00 +0000 |
4212 | +++ plugins/RemoteControl/src/MainService.cpp 2016-06-03 22:29:41 +0000 |
4213 | @@ -0,0 +1,622 @@ |
4214 | +/* |
4215 | + * Stellarium Remote Control plugin |
4216 | + * Copyright (C) 2015 Florian Schaukowitsch |
4217 | + * |
4218 | + * This program is free software; you can redistribute it and/or |
4219 | + * modify it under the terms of the GNU General Public License |
4220 | + * as published by the Free Software Foundation; either version 2 |
4221 | + * of the License, or (at your option) any later version. |
4222 | + * |
4223 | + * This program is distributed in the hope that it will be useful, |
4224 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4225 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4226 | + * GNU General Public License for more details. |
4227 | + * |
4228 | + * You should have received a copy of the GNU General Public License |
4229 | + * along with this program; if not, write to the Free Software |
4230 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
4231 | + */ |
4232 | + |
4233 | +#include "MainService.hpp" |
4234 | + |
4235 | +#include "StelApp.hpp" |
4236 | +#include "StelActionMgr.hpp" |
4237 | +#include "StelCore.hpp" |
4238 | +#include "LandscapeMgr.hpp" |
4239 | +#include "StelLocaleMgr.hpp" |
4240 | +#include "StelMainView.hpp" |
4241 | +#include "StelModuleMgr.hpp" |
4242 | +#include "StelMovementMgr.hpp" |
4243 | +#include "StelObjectMgr.hpp" |
4244 | +#include "StelPropertyMgr.hpp" |
4245 | +#include "StelScriptMgr.hpp" |
4246 | +#include "StelSkyCultureMgr.hpp" |
4247 | +#include "StelTranslator.hpp" |
4248 | +#include "StelUtils.hpp" |
4249 | + |
4250 | +#include <QJsonDocument> |
4251 | + |
4252 | + |
4253 | +MainService::MainService(const QByteArray &serviceName, QObject *parent) |
4254 | + : AbstractAPIService(serviceName,parent), |
4255 | + moveX(0),moveY(0),lastMoveUpdateTime(0) |
4256 | +{ |
4257 | + //100 should be more than enough |
4258 | + //this only has to emcompass events that occur between 2 status updates |
4259 | + actionCache.setCapacity(100); |
4260 | + propCache.setCapacity(100); |
4261 | + |
4262 | + //this is run in the main thread |
4263 | + core = StelApp::getInstance().getCore(); |
4264 | + actionMgr = StelApp::getInstance().getStelActionManager(); |
4265 | + lsMgr = GETSTELMODULE(LandscapeMgr); |
4266 | + localeMgr = &StelApp::getInstance().getLocaleMgr(); |
4267 | + objMgr = &StelApp::getInstance().getStelObjectMgr(); |
4268 | + mvmgr = GETSTELMODULE(StelMovementMgr); |
4269 | + propMgr = StelApp::getInstance().getStelPropertyManager(); |
4270 | + scriptMgr = &StelApp::getInstance().getScriptMgr(); |
4271 | + skyCulMgr = &StelApp::getInstance().getSkyCultureMgr(); |
4272 | + |
4273 | + connect(actionMgr,SIGNAL(actionToggled(QString,bool)),this,SLOT(actionToggled(QString,bool))); |
4274 | + connect(propMgr,SIGNAL(stelPropChanged(QString,QVariant)),this,SLOT(propertyChanged(QString,QVariant))); |
4275 | + |
4276 | + Q_ASSERT(this->thread()==objMgr->thread()); |
4277 | +} |
4278 | + |
4279 | +void MainService::update(double deltaTime) |
4280 | +{ |
4281 | + bool xZero = qFuzzyIsNull(moveX); |
4282 | + bool yZero = qFuzzyIsNull(moveY); |
4283 | + |
4284 | + //prevent sudden disconnects from moving endlessly |
4285 | + if((QDateTime::currentMSecsSinceEpoch() - lastMoveUpdateTime) > 1000) |
4286 | + { |
4287 | + if(!xZero || !yZero) |
4288 | + qDebug()<<"[MainService] move timeout"; |
4289 | + moveX = moveY = .0f; |
4290 | + } |
4291 | + |
4292 | + //Similar to StelMovementMgr::updateMotion |
4293 | + |
4294 | + if(!xZero || !yZero) |
4295 | + { |
4296 | + double currentFov = mvmgr->getCurrentFov(); |
4297 | + // the more it is zoomed, the lower the moving speed is (in angle) |
4298 | + double depl=0.00025*deltaTime*1000*currentFov; |
4299 | + |
4300 | + float deltaAz = moveX; |
4301 | + float deltaAlt = moveY; |
4302 | + |
4303 | + if (deltaAz<0) |
4304 | + { |
4305 | + deltaAz = -depl/30; |
4306 | + if (deltaAz<-0.2) |
4307 | + deltaAz = -0.2; |
4308 | + } |
4309 | + else |
4310 | + { |
4311 | + if (deltaAz>0) |
4312 | + { |
4313 | + deltaAz = (depl/30); |
4314 | + if (deltaAz>0.2) |
4315 | + deltaAz = 0.2; |
4316 | + } |
4317 | + } |
4318 | + |
4319 | + if (deltaAlt<0) |
4320 | + { |
4321 | + deltaAlt = -depl/30; |
4322 | + if (deltaAlt<-0.2) |
4323 | + deltaAlt = -0.2; |
4324 | + } |
4325 | + else |
4326 | + { |
4327 | + if (deltaAlt>0) |
4328 | + { |
4329 | + deltaAlt = depl/30; |
4330 | + if (deltaAlt>0.2) |
4331 | + deltaAlt = 0.2; |
4332 | + } |
4333 | + } |
4334 | + |
4335 | + mvmgr->panView(deltaAz,deltaAlt); |
4336 | + |
4337 | + //this is required to enable maximal fps for smoothness |
4338 | + StelMainView::getInstance().thereWasAnEvent(); |
4339 | + } |
4340 | +} |
4341 | + |
4342 | +void MainService::getImpl(const QByteArray& operation, const APIParameters ¶meters, APIServiceResponse &response) |
4343 | +{ |
4344 | + if(operation=="status") |
4345 | + { |
4346 | + //a listing of the most common stuff that can change often |
4347 | + |
4348 | + QString sActionId = QString::fromUtf8(parameters.value("actionId")); |
4349 | + bool actionOk; |
4350 | + int actionId = sActionId.toInt(&actionOk); |
4351 | + |
4352 | + QString sPropId = QString::fromUtf8(parameters.value("propId")); |
4353 | + bool propOk; |
4354 | + int propId = sPropId.toInt(&propOk); |
4355 | + |
4356 | + QJsonObject obj; |
4357 | + |
4358 | + //// Location |
4359 | + const StelLocation& loc = core->getCurrentLocation(); |
4360 | + { |
4361 | + QJsonObject obj2; |
4362 | + obj2.insert("name",loc.name); |
4363 | + obj2.insert("role",QString(loc.role)); |
4364 | + obj2.insert("planet",loc.planetName); |
4365 | + obj2.insert("latitude",loc.latitude); |
4366 | + obj2.insert("longitude",loc.longitude); |
4367 | + obj2.insert("altitude",loc.altitude); |
4368 | + obj2.insert("country",loc.country); |
4369 | + obj2.insert("state",loc.state); |
4370 | + obj2.insert("landscapeKey",loc.landscapeKey); |
4371 | + obj.insert("location",obj2); |
4372 | + } |
4373 | + |
4374 | + //// Time related stuff |
4375 | + { |
4376 | + double jday = core->getJD(); |
4377 | + double deltaT = core->getDeltaT() * StelCore::JD_SECOND; |
4378 | + |
4379 | + double gmtShift = localeMgr->getGMTShift(jday) / 24.0; |
4380 | + |
4381 | + QString utcIso = StelUtils::julianDayToISO8601String(jday,true).append('Z'); |
4382 | + QString localIso = StelUtils::julianDayToISO8601String(jday+gmtShift,true); |
4383 | + |
4384 | + //time zone string |
4385 | + QString timeZone = localeMgr->getPrintableTimeZoneLocal(jday); |
4386 | + |
4387 | + QJsonObject obj2; |
4388 | + obj2.insert("jday",jday); |
4389 | + obj2.insert("deltaT",deltaT); |
4390 | + obj2.insert("gmtShift",gmtShift); |
4391 | + obj2.insert("timeZone",timeZone); |
4392 | + obj2.insert("utc",utcIso); |
4393 | + obj2.insert("local",localIso); |
4394 | + obj2.insert("isTimeNow",core->getIsTimeNow()); |
4395 | + obj2.insert("timerate",core->getTimeRate()); |
4396 | + obj.insert("time",obj2); |
4397 | + } |
4398 | + |
4399 | + //// Info about selected object (only primary) |
4400 | + { |
4401 | + QString infoStr; |
4402 | + QMetaObject::invokeMethod(this,"getInfoString",SERVICE_DEFAULT_INVOKETYPE, |
4403 | + Q_RETURN_ARG(QString,infoStr)); |
4404 | + obj.insert("selectioninfo",infoStr); |
4405 | + } |
4406 | + |
4407 | + //// Info about current view |
4408 | + { |
4409 | + QJsonObject obj2; |
4410 | + |
4411 | + // the aim fov may lie outside the min/max bounds, so constrain it |
4412 | + double fov = mvmgr->getAimFov(); |
4413 | + if(fov < mvmgr->getMinFov()) |
4414 | + fov = mvmgr->getMinFov(); |
4415 | + else if (fov>mvmgr->getMaxFov()) |
4416 | + fov = mvmgr->getMaxFov(); |
4417 | + |
4418 | + obj2.insert("fov",fov); |
4419 | + |
4420 | + obj.insert("view",obj2); |
4421 | + } |
4422 | + |
4423 | + //// Info about changed actions & props (if requested) |
4424 | + { |
4425 | + if(actionOk) |
4426 | + obj.insert("actionChanges",getActionChangesSinceID(actionId)); |
4427 | + if(propOk) |
4428 | + obj.insert("propertyChanges",getPropertyChangesSinceID(propId)); |
4429 | + } |
4430 | + |
4431 | + response.writeJSON(QJsonDocument(obj)); |
4432 | + } |
4433 | + else if(operation=="plugins") |
4434 | + { |
4435 | + // Retrieve list of plugins |
4436 | + |
4437 | + QJsonObject mainObj; |
4438 | + |
4439 | + StelModuleMgr& modMgr = StelApp::getInstance().getModuleMgr(); |
4440 | + foreach(const StelModuleMgr::PluginDescriptor& desc, modMgr.getPluginsList()) |
4441 | + { |
4442 | + QJsonObject pluginObj,infoObj; |
4443 | + pluginObj.insert("loadAtStartup", desc.loadAtStartup); |
4444 | + pluginObj.insert("loaded", desc.loaded); |
4445 | + |
4446 | + infoObj.insert("authors", desc.info.authors); |
4447 | + infoObj.insert("contact", desc.info.contact); |
4448 | + infoObj.insert("description", desc.info.description); |
4449 | + infoObj.insert("displayedName", desc.info.displayedName); |
4450 | + infoObj.insert("startByDefault", desc.info.startByDefault); |
4451 | + infoObj.insert("version", desc.info.version); |
4452 | + |
4453 | + pluginObj.insert("info",infoObj); |
4454 | + mainObj.insert(desc.info.id, pluginObj); |
4455 | + } |
4456 | + |
4457 | + response.writeJSON(QJsonDocument(mainObj)); |
4458 | + } |
4459 | + else |
4460 | + { |
4461 | + //TODO some sort of service description? |
4462 | + response.writeRequestError("unsupported operation. GET: status, plugins"); |
4463 | + } |
4464 | +} |
4465 | + |
4466 | +void MainService::postImpl(const QByteArray& operation, const APIParameters ¶meters, const QByteArray &data, APIServiceResponse &response) |
4467 | +{ |
4468 | + Q_UNUSED(data); |
4469 | + |
4470 | + if(operation == "time") |
4471 | + { |
4472 | + bool doneSomething = false; |
4473 | + bool ok; |
4474 | + |
4475 | + //set the time + timerate |
4476 | + { |
4477 | + const QByteArray& raw = parameters.value("time"); |
4478 | + if(!raw.isEmpty()) |
4479 | + { |
4480 | + //parse time and set it |
4481 | + double jday = QString(raw).toDouble(&ok); |
4482 | + if(ok) |
4483 | + { |
4484 | + //check for invalid double (NaN, inf...) |
4485 | + //this will crash the app if it is allowed |
4486 | + if(qIsNaN(jday) || qIsInf(jday)) |
4487 | + { |
4488 | + qWarning()<<"[RemoteControl] Prevented setting invalid time"<<jday<<", does the web interface have a bug?"; |
4489 | + response.setData("error: invalid time value"); |
4490 | + return; |
4491 | + } |
4492 | + |
4493 | + doneSomething = true; |
4494 | + //set new time |
4495 | + QMetaObject::invokeMethod(core,"setJD", SERVICE_DEFAULT_INVOKETYPE, |
4496 | + Q_ARG(double,jday)); |
4497 | + } |
4498 | + } |
4499 | + } |
4500 | + { |
4501 | + const QByteArray& raw = parameters.value("timerate"); |
4502 | + if(!raw.isEmpty()) |
4503 | + { |
4504 | + //parse timerate and set it |
4505 | + double rate = QString(raw).toDouble(&ok); |
4506 | + if(ok) |
4507 | + { |
4508 | + doneSomething = true; |
4509 | + //set new time rate |
4510 | + QMetaObject::invokeMethod(core,"setTimeRate", SERVICE_DEFAULT_INVOKETYPE, |
4511 | + Q_ARG(double,rate)); |
4512 | + } |
4513 | + } |
4514 | + } |
4515 | + |
4516 | + if(doneSomething) |
4517 | + response.setData("ok"); |
4518 | + else |
4519 | + response.setData("error: invalid parameters, use time/timerate as double values"); |
4520 | + } |
4521 | + else if(operation == "focus") |
4522 | + { |
4523 | + QString target = QString::fromUtf8(parameters.value("target")); |
4524 | + |
4525 | + //check target string first |
4526 | + if(target.isEmpty()) |
4527 | + { |
4528 | + if(parameters.value("position").isEmpty()) |
4529 | + { |
4530 | + //no parameters = clear focus |
4531 | + target = ""; |
4532 | + } |
4533 | + else |
4534 | + { |
4535 | + //parse position |
4536 | + QJsonDocument doc = QJsonDocument::fromJson(parameters.value("position")); |
4537 | + QJsonArray arr = doc.array(); |
4538 | + if(arr.size() == 3) |
4539 | + { |
4540 | + Vec3d pos; |
4541 | + pos[0] = arr.at(0).toDouble(); |
4542 | + pos[1] = arr.at(1).toDouble(); |
4543 | + pos[2] = arr.at(2).toDouble(); |
4544 | + |
4545 | + //deselect and move |
4546 | + QMetaObject::invokeMethod(this,"focusPosition", SERVICE_DEFAULT_INVOKETYPE, |
4547 | + Q_ARG(Vec3d,pos)); |
4548 | + response.setData("ok"); |
4549 | + return; |
4550 | + } |
4551 | + |
4552 | + response.writeRequestError("invalid position format"); |
4553 | + return; |
4554 | + } |
4555 | + } |
4556 | + |
4557 | + bool result; |
4558 | + QMetaObject::invokeMethod(this,"focusObject",SERVICE_DEFAULT_INVOKETYPE, |
4559 | + Q_RETURN_ARG(bool,result), |
4560 | + Q_ARG(QString,target)); |
4561 | + |
4562 | + response.setData(result ? "true" : "false"); |
4563 | + } |
4564 | + else if(operation == "move") |
4565 | + { |
4566 | + QString xs = QString::fromUtf8(parameters.value("x")); |
4567 | + QString ys = QString::fromUtf8(parameters.value("y")); |
4568 | + |
4569 | + bool xOk,yOk; |
4570 | + float x = xs.toInt(&xOk); |
4571 | + float y = ys.toInt(&yOk); |
4572 | + |
4573 | + if(xOk || yOk) |
4574 | + { |
4575 | + QMetaObject::invokeMethod(this,"updateMovement", SERVICE_DEFAULT_INVOKETYPE, |
4576 | + Q_ARG(float,x), |
4577 | + Q_ARG(float,y), |
4578 | + Q_ARG(bool,xOk), |
4579 | + Q_ARG(bool,yOk)); |
4580 | + |
4581 | + response.setData("ok"); |
4582 | + } |
4583 | + else |
4584 | + response.writeRequestError("requires x or y parameter"); |
4585 | + } |
4586 | + else if (operation == "fov") |
4587 | + { |
4588 | + QString fov = QString::fromUtf8(parameters.value("fov")); |
4589 | + bool ok; |
4590 | + double dFov = fov.toDouble(&ok); |
4591 | + |
4592 | + if(fov.isEmpty() || !ok) |
4593 | + { |
4594 | + response.writeRequestError("requires fov parameter"); |
4595 | + return; |
4596 | + } |
4597 | + |
4598 | + QMetaObject::invokeMethod(this,"setFov",SERVICE_DEFAULT_INVOKETYPE, |
4599 | + Q_ARG(double,dFov)); |
4600 | + |
4601 | + response.setData("ok"); |
4602 | + } |
4603 | + else |
4604 | + { |
4605 | + //TODO some sort of service description? |
4606 | + response.writeRequestError("unsupported operation. POST: time,focus,move,fov"); |
4607 | + } |
4608 | +} |
4609 | + |
4610 | +StelObjectP MainService::getSelectedObject() |
4611 | +{ |
4612 | + const QList<StelObjectP>& list = objMgr->getSelectedObject(); |
4613 | + if(list.isEmpty()) |
4614 | + return StelObjectP(); |
4615 | + return list.first(); |
4616 | +} |
4617 | + |
4618 | +QString MainService::getInfoString() |
4619 | +{ |
4620 | + StelObjectP selectedObject = getSelectedObject(); |
4621 | + if(selectedObject.isNull()) |
4622 | + return QString(); |
4623 | + return selectedObject->getInfoString(core,StelObject::AllInfo | StelObject::NoFont); |
4624 | +} |
4625 | + |
4626 | +bool MainService::focusObject(const QString &name) |
4627 | +{ |
4628 | + //StelDialog::gotoObject |
4629 | + |
4630 | + //if name is empty, unselect |
4631 | + if(name.isEmpty()) |
4632 | + { |
4633 | + objMgr->unSelect(); |
4634 | + return true; |
4635 | + } |
4636 | + |
4637 | + bool result = false; |
4638 | + if (objMgr->findAndSelectI18n(name) || objMgr->findAndSelect(name)) |
4639 | + { |
4640 | + const QList<StelObjectP> newSelected = objMgr->getSelectedObject(); |
4641 | + if (!newSelected.empty()) |
4642 | + { |
4643 | + // Can't point to home planet |
4644 | + if (newSelected[0]->getEnglishName()!=core->getCurrentLocation().planetName) |
4645 | + { |
4646 | + mvmgr->moveToObject(newSelected[0], mvmgr->getAutoMoveDuration()); |
4647 | + mvmgr->setFlagTracking(true); |
4648 | + result = true; |
4649 | + } |
4650 | + else |
4651 | + { |
4652 | + objMgr->unSelect(); |
4653 | + } |
4654 | + } |
4655 | + } |
4656 | + return result; |
4657 | +} |
4658 | + |
4659 | +void MainService::focusPosition(const Vec3d &pos) |
4660 | +{ |
4661 | + objMgr->unSelect(); |
4662 | + mvmgr->moveToJ2000(pos, mvmgr->getAutoMoveDuration()); |
4663 | +} |
4664 | + |
4665 | +void MainService::updateMovement(float x, float y, bool xUpdated, bool yUpdated) |
4666 | +{ |
4667 | + if(xUpdated) |
4668 | + { |
4669 | + this->moveX = x; |
4670 | + } |
4671 | + if(yUpdated) |
4672 | + { |
4673 | + this->moveY = y; |
4674 | + } |
4675 | + qint64 curTime = QDateTime::currentMSecsSinceEpoch(); |
4676 | + //qDebug()<<"updateMove"<<x<<y<<(curTime-lastMoveUpdateTime); |
4677 | + lastMoveUpdateTime = curTime; |
4678 | +} |
4679 | + |
4680 | +void MainService::setFov(double fov) |
4681 | +{ |
4682 | + //TODO calculate a better move duration here |
4683 | + mvmgr->zoomTo(fov,0.25f); |
4684 | +} |
4685 | + |
4686 | +void MainService::actionToggled(const QString &id, bool val) |
4687 | +{ |
4688 | + actionMutex.lock(); |
4689 | + actionCache.append(ActionCacheEntry(id,val)); |
4690 | + if(!actionCache.areIndexesValid()) |
4691 | + { |
4692 | + //in theory, this can happen, but practically not so much |
4693 | + qWarning()<<"Action cache indices invalid"; |
4694 | + actionCache.clear(); |
4695 | + } |
4696 | + actionMutex.unlock(); |
4697 | +} |
4698 | + |
4699 | +void MainService::propertyChanged(const QString &id, const QVariant &val) |
4700 | +{ |
4701 | + propMutex.lock(); |
4702 | + propCache.append(PropertyCacheEntry(id,val)); |
4703 | + if(!propCache.areIndexesValid()) |
4704 | + { |
4705 | + //in theory, this can happen, but practically not so much |
4706 | + qWarning()<<"Property cache indices invalid"; |
4707 | + propCache.clear(); |
4708 | + } |
4709 | + propMutex.unlock(); |
4710 | +} |
4711 | + |
4712 | +QJsonObject MainService::getActionChangesSinceID(int changeId) |
4713 | +{ |
4714 | + //changeId is the last id the interface is available |
4715 | + //or -2 if the interface just started |
4716 | + // -1 means the initial state was set |
4717 | + |
4718 | + QJsonObject obj; |
4719 | + QJsonObject changes; |
4720 | + int newId = changeId; |
4721 | + |
4722 | + |
4723 | + actionMutex.lock(); |
4724 | + if(actionCache.isEmpty()) |
4725 | + { |
4726 | + if(changeId!=-1) |
4727 | + { |
4728 | + //this is either the initial state (-2) or |
4729 | + //something is "broken", probably from an existing web interface that reconnected after restart |
4730 | + //force a full reload |
4731 | + |
4732 | + foreach(StelAction* ac, actionMgr->getActionList()) |
4733 | + { |
4734 | + if(ac->isCheckable()) |
4735 | + { |
4736 | + changes.insert(ac->getId(),ac->isChecked()); |
4737 | + } |
4738 | + } |
4739 | + newId = -1; |
4740 | + } |
4741 | + } |
4742 | + else |
4743 | + { |
4744 | + if(changeId > actionCache.lastIndex() || changeId < (actionCache.firstIndex()-1)) |
4745 | + { |
4746 | + //this is either the initial state (-2) or |
4747 | + //"broken" state again, force full reload |
4748 | + foreach(StelAction* ac, actionMgr->getActionList()) |
4749 | + { |
4750 | + if(ac->isCheckable()) |
4751 | + { |
4752 | + changes.insert(ac->getId(),ac->isChecked()); |
4753 | + } |
4754 | + } |
4755 | + newId = actionCache.lastIndex(); |
4756 | + } |
4757 | + else if(changeId < actionCache.lastIndex()) |
4758 | + { |
4759 | + //create a "diff" between changeId to lastIndex |
4760 | + for(int i = changeId+1;i<=actionCache.lastIndex();++i) |
4761 | + { |
4762 | + const ActionCacheEntry& e = actionCache.at(i); |
4763 | + changes.insert(e.action,e.val); |
4764 | + } |
4765 | + newId = actionCache.lastIndex(); |
4766 | + } |
4767 | + //else no changes happened, interface is at current state! |
4768 | + } |
4769 | + actionMutex.unlock(); |
4770 | + |
4771 | + obj.insert("changes",changes); |
4772 | + obj.insert("id",newId); |
4773 | + |
4774 | + return obj; |
4775 | +} |
4776 | + |
4777 | +QJsonObject MainService::getPropertyChangesSinceID(int changeId) |
4778 | +{ |
4779 | + //changeId is the last id the interface is available |
4780 | + //or -2 if the interface just started |
4781 | + // -1 means the initial state was set |
4782 | + QJsonObject obj; |
4783 | + QJsonObject changes; |
4784 | + int newId = changeId; |
4785 | + |
4786 | + propMutex.lock(); |
4787 | + if(propCache.isEmpty()) |
4788 | + { |
4789 | + if(changeId!=-1) |
4790 | + { |
4791 | + //this is either the initial state (-2) or |
4792 | + //something is "broken", probably from an existing web interface that reconnected after restart |
4793 | + //force a full reload |
4794 | + const StelPropertyMgr::StelPropertyMap& map = propMgr->getPropertyMap(); |
4795 | + for(StelPropertyMgr::StelPropertyMap::const_iterator it = map.constBegin(); |
4796 | + it!=map.constEnd();++it) |
4797 | + { |
4798 | + changes.insert(it.key(), QJsonValue::fromVariant((*it)->getValue())); |
4799 | + } |
4800 | + newId = -1; |
4801 | + } |
4802 | + } |
4803 | + else |
4804 | + { |
4805 | + if(changeId > propCache.lastIndex() || changeId < (propCache.firstIndex()-1)) |
4806 | + { |
4807 | + //this is either the initial state (-2) or |
4808 | + //"broken" state again, force full reload |
4809 | + const StelPropertyMgr::StelPropertyMap& map = propMgr->getPropertyMap(); |
4810 | + for(StelPropertyMgr::StelPropertyMap::const_iterator it = map.constBegin(); |
4811 | + it!=map.constEnd();++it) |
4812 | + { |
4813 | + changes.insert(it.key(), QJsonValue::fromVariant((*it)->getValue())); |
4814 | + } |
4815 | + newId = propCache.lastIndex(); |
4816 | + } |
4817 | + else if(changeId < propCache.lastIndex()) |
4818 | + { |
4819 | + //create a "diff" between changeId to lastIndex |
4820 | + for(int i = changeId+1;i<=propCache.lastIndex();++i) |
4821 | + { |
4822 | + const PropertyCacheEntry& e = propCache.at(i); |
4823 | + changes.insert(e.id,QJsonValue::fromVariant(e.val)); |
4824 | + } |
4825 | + newId = propCache.lastIndex(); |
4826 | + } |
4827 | + //else no changes happened, interface is at current state! |
4828 | + } |
4829 | + propMutex.unlock(); |
4830 | + |
4831 | + obj.insert("changes",changes); |
4832 | + obj.insert("id",newId); |
4833 | + |
4834 | + return obj; |
4835 | +} |
4836 | |
4837 | === added file 'plugins/RemoteControl/src/MainService.hpp' |
4838 | --- plugins/RemoteControl/src/MainService.hpp 1970-01-01 00:00:00 +0000 |
4839 | +++ plugins/RemoteControl/src/MainService.hpp 2016-06-03 22:29:41 +0000 |
4840 | @@ -0,0 +1,122 @@ |
4841 | +/* |
4842 | + * Stellarium Remote Control plugin |
4843 | + * Copyright (C) 2015 Florian Schaukowitsch |
4844 | + * |
4845 | + * This program is free software; you can redistribute it and/or |
4846 | + * modify it under the terms of the GNU General Public License |
4847 | + * as published by the Free Software Foundation; either version 2 |
4848 | + * of the License, or (at your option) any later version. |
4849 | + * |
4850 | + * This program is distributed in the hope that it will be useful, |
4851 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4852 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4853 | + * GNU General Public License for more details. |
4854 | + * |
4855 | + * You should have received a copy of the GNU General Public License |
4856 | + * along with this program; if not, write to the Free Software |
4857 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
4858 | + */ |
4859 | + |
4860 | +#ifndef MAINSERVICE_HPP_ |
4861 | +#define MAINSERVICE_HPP_ |
4862 | + |
4863 | +#include "AbstractAPIService.hpp" |
4864 | + |
4865 | +#include "StelObjectType.hpp" |
4866 | +#include "VecMath.hpp" |
4867 | + |
4868 | +#include <QContiguousCache> |
4869 | +#include <QJsonObject> |
4870 | +#include <QMutex> |
4871 | + |
4872 | +class StelCore; |
4873 | +class StelActionMgr; |
4874 | +class LandscapeMgr; |
4875 | +class StelLocaleMgr; |
4876 | +class StelMovementMgr; |
4877 | +class StelObjectMgr; |
4878 | +class StelPropertyMgr; |
4879 | +class StelScriptMgr; |
4880 | +class StelSkyCultureMgr; |
4881 | + |
4882 | +//! @ingroup remoteControl |
4883 | +//! Implements the main API services, including the \c status operation which can be repeatedly polled to find the current state of the main program, |
4884 | +//! including time, view, location, StelAction and StelProperty state changes, movement, script status ... |
4885 | +//! |
4886 | +//! @see @ref rcMainService |
4887 | +class MainService : public AbstractAPIService |
4888 | +{ |
4889 | + Q_OBJECT |
4890 | +public: |
4891 | + MainService(const QByteArray& serviceName, QObject* parent = 0); |
4892 | + |
4893 | + virtual ~MainService() {} |
4894 | + |
4895 | + //! Used to implement move functionality |
4896 | + virtual void update(double deltaTime) Q_DECL_OVERRIDE; |
4897 | + |
4898 | +protected: |
4899 | + //! @brief Implements the GET operations |
4900 | + //! @see @ref rcMainServiceGET |
4901 | + virtual void getImpl(const QByteArray& operation,const APIParameters ¶meters, APIServiceResponse& response) Q_DECL_OVERRIDE; |
4902 | + //! @brief Implements the HTTP POST operations |
4903 | + //! @see @ref rcMainServicePOST |
4904 | + virtual void postImpl(const QByteArray &operation, const APIParameters ¶meters, const QByteArray &data, APIServiceResponse &response) Q_DECL_OVERRIDE; |
4905 | + |
4906 | +private slots: |
4907 | + StelObjectP getSelectedObject(); |
4908 | + |
4909 | + //! Returns the info string of the currently selected object |
4910 | + QString getInfoString(); |
4911 | + |
4912 | + //! Like StelDialog::gotoObject |
4913 | + bool focusObject(const QString& name); |
4914 | + void focusPosition(const Vec3d& pos); |
4915 | + |
4916 | + void updateMovement(float x, float y, bool xUpdated, bool yUpdated); |
4917 | + void setFov(double fov); |
4918 | + |
4919 | + void actionToggled(const QString& id, bool val); |
4920 | + void propertyChanged(const QString& id, const QVariant& val); |
4921 | + |
4922 | +private: |
4923 | + StelCore* core; |
4924 | + StelActionMgr* actionMgr; |
4925 | + LandscapeMgr* lsMgr; |
4926 | + StelLocaleMgr* localeMgr; |
4927 | + StelMovementMgr* mvmgr; |
4928 | + StelObjectMgr* objMgr; |
4929 | + StelPropertyMgr* propMgr; |
4930 | + StelScriptMgr* scriptMgr; |
4931 | + StelSkyCultureMgr* skyCulMgr; |
4932 | + |
4933 | + float moveX,moveY; |
4934 | + qint64 lastMoveUpdateTime; |
4935 | + |
4936 | + struct ActionCacheEntry |
4937 | + { |
4938 | + ActionCacheEntry(const QString& str,bool val) : action(str),val(val) {} |
4939 | + QString action; |
4940 | + bool val; |
4941 | + }; |
4942 | + |
4943 | + //lists the recently toggled actions - this is a pseudo-circular buffer |
4944 | + QContiguousCache<ActionCacheEntry> actionCache; |
4945 | + QMutex actionMutex; |
4946 | + QJsonObject getActionChangesSinceID(int changeId); |
4947 | + |
4948 | + struct PropertyCacheEntry |
4949 | + { |
4950 | + PropertyCacheEntry(const QString& str, const QVariant& val) : id(str),val(val) {} |
4951 | + QString id; |
4952 | + QVariant val; |
4953 | + }; |
4954 | + QContiguousCache<PropertyCacheEntry> propCache; |
4955 | + QMutex propMutex; |
4956 | + QJsonObject getPropertyChangesSinceID(int changeId); |
4957 | + |
4958 | +}; |
4959 | + |
4960 | + |
4961 | + |
4962 | +#endif |
4963 | |
4964 | === added file 'plugins/RemoteControl/src/ObjectService.cpp' |
4965 | --- plugins/RemoteControl/src/ObjectService.cpp 1970-01-01 00:00:00 +0000 |
4966 | +++ plugins/RemoteControl/src/ObjectService.cpp 2016-06-03 22:29:41 +0000 |
4967 | @@ -0,0 +1,216 @@ |
4968 | +/* |
4969 | + * Stellarium Remote Control plugin |
4970 | + * Copyright (C) 2015 Florian Schaukowitsch |
4971 | + * |
4972 | + * This program is free software; you can redistribute it and/or |
4973 | + * modify it under the terms of the GNU General Public License |
4974 | + * as published by the Free Software Foundation; either version 2 |
4975 | + * of the License, or (at your option) any later version. |
4976 | + * |
4977 | + * This program is distributed in the hope that it will be useful, |
4978 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
4979 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
4980 | + * GNU General Public License for more details. |
4981 | + * |
4982 | + * You should have received a copy of the GNU General Public License |
4983 | + * along with this program; if not, write to the Free Software |
4984 | + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. |
4985 | + */ |
4986 | + |
4987 | +#include "ObjectService.hpp" |
4988 | + |
4989 | +#include "SearchDialog.hpp" |
4990 | +#include "StelApp.hpp" |
4991 | +#include "StelCore.hpp" |
4992 | +#include "StelObjectMgr.hpp" |
4993 | +#include "StelTranslator.hpp" |
4994 | + |
4995 | +#include <QEventLoop> |
4996 | +#include <QJsonArray> |
4997 | +#include <QJsonDocument> |
4998 | +#include <QJsonObject> |
4999 | +#include <QSettings> |
5000 | +#include <QMutex> |
Hi Florian, Georg,
thanks, that's huge amount of work that you did! I haven't checked the code in a (too) long time, so it took me time to sort out your changes from the ones of the trunk!
General comment: the code is very clean and very well documented, thanks! That's really professional work :)
Comments on the StelProperty: StelPropertyMgr for scripting and more generally GUI/remote controller etc... it is definitely something missing from the current trunk propertyname you may more or less be able to avoid it I think. The property manager would then simply manage the collection of QObject containing the properties to expose and you could use a more standard approach, which will match the scripting language API. There is somehow a merge to do with the existing scripting API. QProperty and remove the other kind of binding to functions? I think it would make sense.
- I understand the need for StelProperty/
- I am not quite sure about creating a new StelProperty class though, as it doesn't seem brings much more than the regular Qt property. If you would adopt the convention used in QtScript of designing a property by the qobjectname.
- Also I'm a bit concerned with the partial duplication of features with StelAction, or at least the additional complexity to grasp the difference and when to use which. Did you consider forcing StelAction to use a StelProperty/
On the RemoteControl plugin: RemoteControl/ folder)
- it would be good to move all related data inside the plugin folder instead of keeping them in data/ (i.e. move data/webroot stuff in the plguing/
- did you double check all third parties libraries licenses?
- this plugin should also not be activated by default for security reasons (I didn't check if it's the case)