Merge lp:~daggerstab/stellarium/comets-asteroids-importer into lp:stellarium

Proposed by Bogdan Marinov
Status: Merged
Merged at revision: 4799
Proposed branch: lp:~daggerstab/stellarium/comets-asteroids-importer
Merge into: lp:stellarium
Diff against target: 7637 lines (+7199/-32)
36 files modified
CMakeLists.txt (+1/-0)
Doxyfile.cmake (+1/-1)
data/gui/nightStyle.css (+8/-0)
data/gui/normalStyle.css (+8/-0)
data/ssystem.ini (+10/-5)
plugins/CMakeLists.txt (+3/-0)
plugins/SolarSystemEditor/CMakeLists.txt (+19/-0)
plugins/SolarSystemEditor/UnpackProvisionalDesignation.pro (+12/-0)
plugins/SolarSystemEditor/src/CMakeLists.txt (+76/-0)
plugins/SolarSystemEditor/src/SolarSystemEditor.cpp (+1535/-0)
plugins/SolarSystemEditor/src/SolarSystemEditor.hpp (+312/-0)
plugins/SolarSystemEditor/src/gui/MPCImporterDialogPrototype02.ui (+171/-0)
plugins/SolarSystemEditor/src/gui/ManualImportWindow.cpp (+257/-0)
plugins/SolarSystemEditor/src/gui/ManualImportWindow.hpp (+79/-0)
plugins/SolarSystemEditor/src/gui/MpcImportWindow.cpp (+958/-0)
plugins/SolarSystemEditor/src/gui/MpcImportWindow.hpp (+135/-0)
plugins/SolarSystemEditor/src/gui/SolarSystemManagerWindow.cpp (+170/-0)
plugins/SolarSystemEditor/src/gui/SolarSystemManagerWindow.hpp (+73/-0)
plugins/SolarSystemEditor/src/gui/manualImportWindow.ui (+890/-0)
plugins/SolarSystemEditor/src/gui/mpcImportWindow.ui (+679/-0)
plugins/SolarSystemEditor/src/gui/solarSystemManagerWindow.ui (+426/-0)
plugins/SolarSystemEditor/src/gui/solarSystemManagerWindow_prototype01.ui (+130/-0)
plugins/SolarSystemEditor/ssystem_ini format.txt (+76/-0)
plugins/SolarSystemEditor/unpackProvisionalDesignationTest.cpp (+180/-0)
src/CMakeLists.txt (+9/-0)
src/StelMainGraphicsView.cpp (+4/-0)
src/core/StelFileMgr.cpp (+52/-0)
src/core/StelFileMgr.hpp (+7/-0)
src/core/modules/Comet.cpp (+171/-0)
src/core/modules/Comet.hpp (+83/-0)
src/core/modules/MinorPlanet.cpp (+296/-0)
src/core/modules/MinorPlanet.hpp (+113/-0)
src/core/modules/Planet.hpp (+1/-1)
src/core/modules/SolarSystem.cpp (+215/-24)
src/core/modules/SolarSystem.hpp (+15/-1)
src/translations.h (+24/-0)
To merge this branch: bzr merge lp:~daggerstab/stellarium/comets-asteroids-importer
Reviewer Review Type Date Requested Status
Fabien Chéreau Approve
Matthew Gates usage Pending
Review via email: mp+41004@code.launchpad.net

This proposal supersedes a proposal from 2010-11-12.

Description of the change

This is the first version (0.0.1) of the Solar System Editor plug-in (formerly the Comets and Asteroids Importer plug-in).

It's not a complete Solar System editor yet - the window that would allow manual editing of all parameters of Solar System objects is not finished yet, so it is hidden in this release. You can open manualImportWindow.ui in QtDesigner for a preview of what it will look like.

In addition to the plug-in itself, the branch contains changes to Stellarium's core (SolarSystem + 2 new classes derived from Planet) that allow better handling of asteroids and comets, including name rendering and visual magnitude calculation.

Feel free to comment on the interface and the texts used in it. :)

Update: I've made several changes. The countdown has been removed (it's still used internally, but for connection timeout). The Solar System class now can skip invalid planet entries and does not crash when trying to load an invalid ssystem.ini file. See the summaries of the revisions for more information on what has been changed since the first merge proposal.

(I will look into using JSON for the Solar System, but I think this should happen after we release 0.10.6.)

To post a comment you must log in.
Revision history for this message
Fabien Chéreau (xalioth) wrote : Posted in a previous version of this proposal

At some point Mike Storm worked on an experimental JSON format for solar system objects. I think this was never merged, but it was superior to the old .ini format in that it could reflect natively nesting of objects.

See the mailing list archive thread:

http://sourceforge.net/mailarchive/forum.php?thread_name=c3fc7ff0812080257we37817fq7bb5e9f874c3a7ba%40mail.gmail.com&forum_name=stellarium-pubdevel

Revision history for this message
Matthew Gates (matthew-porpoisehead) wrote : Posted in a previous version of this proposal

First impressions - really good plugin - I think a lot of people will appreciate this one.

GUI:
1 Not sure if we need the path of the ssystem.ini printed. Perhaps just a "reset" option to delete user copy. I realize this won't if the ssystem.ini is messed up so much the program won't start, but then this message can't be seen, and for sure users won't remember it.

(2) If we don't have to have the big warning and path of user ssystem.ini, maybe we can also dispense with the Copy / Restore thing?

(3) Internet search timer somewhat annoying. It makes user wait for a minute if they /didn't/ find what they were looking for (at which point they will probably want to re-search straight away). Unless we get complaints of overloading from the search server people, I don't think we need the limit, although maybe we should set the user agent to something they can use to throttle us if they want rather than have a generic user agent (assuming we use http to connect).

(4) Maybe the search can just be a tab in the main window rather than a separate tab (if (1) & (2) are accepted, the first tab is not really necessary - just a restore button somewhere.

Just my 2 pence worth!

-

Minor bugs noticed:
- long names of downloaded objects get truncated to 20 characters.

review: Abstain (usage)
Revision history for this message
barrykgerdes (barrygastro) wrote : Posted in a previous version of this proposal

Hi

I compiled 4786 last night in Widows (4782 was OK). I causes a major lock up. It reaches the stellarium display and
then stops nothing but a total shut down unlocks the computer. As a restart then takes about 7 minutes I have not got very far but I suspect it may be in the config.ini or ssystem.ini files. The log.txt gives no indication

Barry Gerdes
Beaumont Hills Observatory
S 33' 41' 44" E 150' 56' 32"

> To: <email address hidden>
> From: <email address hidden>
> Subject: [Merge] lp:~daggerstab/stellarium/comets-asteroids-importer into lp:stellarium
> Date: Fri, 12 Nov 2010 17:23:10 +0000
>
> Bogdan Marinov has proposed merging lp:~daggerstab/stellarium/comets-asteroids-importer into lp:stellarium.
>
> Requested reviews:
> Stellarium (stellarium)
>
>
> This is the first version (0.0.1) of the Solar System Editor plug-in (formerly the Comets and Asteroids Importer plug-in).
>
> It's not a complete Solar System editor yet - the window that would allow manual editing of all parameters of Solar System objects is not finished yet, so it is hidden in this release. You can open manualImportWindow.ui in QtDesigner for a preview of what it will look like.
>
> In addition to the plug-in itself, the branch contains changes to Stellarium's core (SolarSystem + 2 new classes derived from Planet) that allow better handling of asteroids and comets, including name rendering and visual magnitude calculation.
>
> Feel free to comment on the interface and the texts used in it. :)
> --
> https://code.launchpad.net/~daggerstab/stellarium/comets-asteroids-importer/+merge/40744
> Your team Stellarium is requested to review the proposed merge of lp:~daggerstab/stellarium/comets-asteroids-importer into lp:stellarium.

Revision history for this message
Fabien Chéreau (xalioth) wrote :

Excellent and amazingly complete! I really like that you thought about the merge tool when importing new objects!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2010-11-08 15:26:58 +0000
+++ CMakeLists.txt 2010-11-16 20:06:17 +0000
@@ -136,6 +136,7 @@
136SET(USE_PLUGIN_TEXTUSERINTERFACE 1 CACHE BOOL "Define whether the TextUserInterface plugin should be created.")136SET(USE_PLUGIN_TEXTUSERINTERFACE 1 CACHE BOOL "Define whether the TextUserInterface plugin should be created.")
137SET(USE_PLUGIN_TIMEZONECONFIGURATION 1 CACHE BOOL "Define whether the TimeZoneConfiguration plugin should be created.")137SET(USE_PLUGIN_TIMEZONECONFIGURATION 1 CACHE BOOL "Define whether the TimeZoneConfiguration plugin should be created.")
138SET(USE_PLUGIN_VIRGO 0 CACHE BOOL "Define whether the VirGO plugin should be created.")138SET(USE_PLUGIN_VIRGO 0 CACHE BOOL "Define whether the VirGO plugin should be created.")
139SET(USE_PLUGIN_SOLARSYSTEMEDITOR 1 CACHE BOOL "Define whether the Solar System Editor should be built.")
139140
140########## Static plugins need to define includes and libraries141########## Static plugins need to define includes and libraries
141########## for the compilation of Stellarium itself142########## for the compilation of Stellarium itself
142143
=== modified file 'Doxyfile.cmake'
--- Doxyfile.cmake 2010-09-03 09:54:30 +0000
+++ Doxyfile.cmake 2010-11-16 20:06:17 +0000
@@ -463,7 +463,7 @@
463# disable (NO) the deprecated list. This list is created by putting463# disable (NO) the deprecated list. This list is created by putting
464# \deprecated commands in the documentation.464# \deprecated commands in the documentation.
465465
466GENERATE_DEPRECATEDLIST= NO466GENERATE_DEPRECATEDLIST= YES
467467
468# The ENABLED_SECTIONS tag can be used to enable conditional468# The ENABLED_SECTIONS tag can be used to enable conditional
469# documentation sections, marked by \if sectionname ... \endif.469# documentation sections, marked by \if sectionname ... \endif.
470470
=== modified file 'data/gui/nightStyle.css'
--- data/gui/nightStyle.css 2010-11-16 19:33:22 +0000
+++ data/gui/nightStyle.css 2010-11-16 20:06:17 +0000
@@ -514,6 +514,14 @@
514 image: url(:/graphicGui/nv_checkbox-unchecked.png);514 image: url(:/graphicGui/nv_checkbox-unchecked.png);
515}515}
516516
517QListWidget::indicator::checked {
518 image: url(:/graphicGui/nv_checkbox-checked.png);
519}
520
521QListWidget::indicator:unchecked {
522 image: url(:/graphicGui/nv_checkbox-unchecked.png);
523}
524
517/*QCheckBox:disabled {525/*QCheckBox:disabled {
518 color: rgb(210, 0, 0);526 color: rgb(210, 0, 0);
519 font-weight: 500;527 font-weight: 500;
520528
=== modified file 'data/gui/normalStyle.css'
--- data/gui/normalStyle.css 2010-11-14 03:12:37 +0000
+++ data/gui/normalStyle.css 2010-11-16 20:06:17 +0000
@@ -513,6 +513,14 @@
513 image: url(:/graphicGui/checkbox-unchecked.png);513 image: url(:/graphicGui/checkbox-unchecked.png);
514}514}
515515
516QListWidget::indicator::checked {
517 image: url(:/graphicGui/checkbox-checked.png);
518}
519
520QListWidget::indicator:unchecked {
521 image: url(:/graphicGui/checkbox-unchecked.png);
522}
523
516/*QCheckBox:disabled {524/*QCheckBox:disabled {
517 color: rgb(210, 0, 0);525 color: rgb(210, 0, 0);
518 font-weight: 500;526 font-weight: 500;
519527
=== modified file 'data/ssystem.ini'
--- data/ssystem.ini 2010-07-16 14:09:25 +0000
+++ data/ssystem.ini 2010-11-16 20:06:17 +0000
@@ -586,8 +586,9 @@
586albedo = 1586albedo = 1
587orbit_visualization_period = 365.25587orbit_visualization_period = 365.25
588588
589[ceres]589[1ceres]
590name = Ceres590name = Ceres
591minor_planet_number = 1
591parent = Sun592parent = Sun
592radius = 470593radius = 470
593oblateness = 0.0594oblateness = 0.0
@@ -607,8 +608,9 @@
607orbit_AscendingNode = 80.40696608orbit_AscendingNode = 80.40696
608orbit_Inclination = 10.58671609orbit_Inclination = 10.58671
609610
610[pallas]611[2pallas]
611name = Pallas612name = Pallas
613minor_planet_number = 2
612parent = Sun614parent = Sun
613radius = 220615radius = 220
614oblateness = 0.0616oblateness = 0.0
@@ -628,8 +630,9 @@
628orbit_AscendingNode = 173.13579630orbit_AscendingNode = 173.13579
629orbit_Inclination = 34.84182631orbit_Inclination = 34.84182
630632
631[juno]633[3juno]
632name = Juno634name = Juno
635minor_planet_number = 3
633parent = Sun636parent = Sun
634radius = 130637radius = 130
635oblateness = 0.0638oblateness = 0.0
@@ -649,8 +652,9 @@
649orbit_AscendingNode = 170.12007652orbit_AscendingNode = 170.12007
650orbit_Inclination = 12.97036653orbit_Inclination = 12.97036
651654
652[vesta]655[4vesta]
653name = Vesta656name = Vesta
657minor_planet_number = 4
654parent = Sun658parent = Sun
655radius = 280659radius = 280
656oblateness = 0.0660oblateness = 0.0
@@ -670,8 +674,9 @@
670orbit_AscendingNode = 103.91841674orbit_AscendingNode = 103.91841
671orbit_Inclination = 7.13380675orbit_Inclination = 7.13380
672676
673[eris]677[136199eris]
674name = Eris678name = Eris
679minor_planet_number = 136199
675parent = Sun680parent = Sun
676radius = 1300681radius = 1300
677oblateness = 0.0682oblateness = 0.0
678683
=== modified file 'plugins/CMakeLists.txt'
--- plugins/CMakeLists.txt 2010-11-08 15:24:12 +0000
+++ plugins/CMakeLists.txt 2010-11-16 20:06:17 +0000
@@ -41,3 +41,6 @@
41 SET(VIRGO_PROJECT_PATH "../extmodules/VirGO/" CACHE PATH "The location of the VirGO plugin main directory i.e. the one containing the top level CMakeLists.txt")41 SET(VIRGO_PROJECT_PATH "../extmodules/VirGO/" CACHE PATH "The location of the VirGO plugin main directory i.e. the one containing the top level CMakeLists.txt")
42 ADD_SUBDIRECTORY( ${VIRGO_PROJECT_PATH} VirGO )42 ADD_SUBDIRECTORY( ${VIRGO_PROJECT_PATH} VirGO )
43ENDIF()43ENDIF()
44IF (USE_PLUGIN_SOLARSYSTEMEDITOR)
45 ADD_SUBDIRECTORY( SolarSystemEditor )
46ENDIF()
4447
=== added directory 'plugins/SolarSystemEditor'
=== added file 'plugins/SolarSystemEditor/CMakeLists.txt'
--- plugins/SolarSystemEditor/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/CMakeLists.txt 2010-11-16 20:06:17 +0000
@@ -0,0 +1,19 @@
1
2SET(SOLARSYSTEMEDITOR_MAJOR "0")
3SET(SOLARSYSTEMEDITOR_MINOR "0")
4SET(SOLARSYSTEMEDITOR_PATCH "1")
5SET(SOLARSYSTEMEDITOR_VERSION "${SOLARSYSTEMEDITOR_MAJOR}.${SOLARSYSTEMEDITOR_MINOR}.${SOLARSYSTEMEDITOR_PATCH}")
6
7IF(APPLE)
8 SET(CMAKE_INSTALL_PREFIX $ENV{HOME}/Library/Application\ Support/Stellarium)
9ElSE(APPLE)
10 SET(CMAKE_INSTALL_PREFIX $ENV{HOME}/.stellarium)
11ENDIF(APPLE)
12
13ADD_DEFINITIONS(-DPLUGIN_VERSION="${SOLARSYSTEMEDITOR_VERSION}")
14
15ADD_SUBDIRECTORY( src )
16
17INSTALL(FILES DESTINATION "modules/SolarSystemEditor")
18
19
020
=== added file 'plugins/SolarSystemEditor/UnpackProvisionalDesignation.pro'
--- plugins/SolarSystemEditor/UnpackProvisionalDesignation.pro 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/UnpackProvisionalDesignation.pro 2010-11-16 20:06:17 +0000
@@ -0,0 +1,12 @@
1#-------------------------------------------------
2#
3# Project created by QtCreator 2010-09-18T15:18:26
4#
5#-------------------------------------------------
6
7TARGET = UnpackProvisionalDesignation
8CONFIG += qtestlib
9CONFIG -= app_bundle
10
11
12SOURCES += unpackProvisionalDesignationTest.cpp
013
=== added directory 'plugins/SolarSystemEditor/src'
=== added file 'plugins/SolarSystemEditor/src/CMakeLists.txt'
--- plugins/SolarSystemEditor/src/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/CMakeLists.txt 2010-11-16 20:06:17 +0000
@@ -0,0 +1,76 @@
1
2INCLUDE_DIRECTORIES(
3 ${CMAKE_BINARY_DIR}
4 ${CMAKE_BINARY_DIR}/plugins/SolarSystemEditor/src
5 ${CMAKE_BINARY_DIR}/plugins/SolarSystemEditor/src/gui
6 . gui)
7
8LINK_DIRECTORIES(/src)
9
10SET(SolarSystemEditor_SRCS
11 SolarSystemEditor.hpp
12 SolarSystemEditor.cpp
13 gui/SolarSystemManagerWindow.hpp
14 gui/SolarSystemManagerWindow.cpp
15 gui/MpcImportWindow.hpp
16 gui/MpcImportWindow.cpp
17 gui/ManualImportWindow.hpp
18 gui/ManualImportWindow.cpp
19 )
20
21SET(SolarSystemEditor_UIS
22 gui/solarSystemManagerWindow.ui
23 gui/mpcImportWindow.ui
24 gui/manualImportWindow.ui
25)
26
27QT4_WRAP_UI(SolarSystemEditor_UIS_H ${SolarSystemEditor_UIS})
28
29#SET(SolarSystemEditor_RES ../resources/resources.qrc)
30#QT4_ADD_RESOURCES(SolarSystemEditor_RES_CXX ${SolarSystemEditor_RES})
31
32SET(SolarSystemEditor_MOC_HDRS
33 gui/SolarSystemManagerWindow.hpp
34 gui/MpcImportWindow.hpp
35 gui/ManualImportWindow.hpp
36 SolarSystemEditor.hpp
37 )
38
39QT4_WRAP_CPP(SolarSystemEditor_MOC_SRCS ${SolarSystemEditor_MOC_HDRS})
40
41SET(extLinkerOption ${QT_LIBRARIES} ${OPENGL_LIBRARIES} ${ICONV_LIBRARIES} ${INTL_LIBRARIES})
42
43#Dynamic library
44IF(BUILD_DYNAMIC_PLUGINS)
45 ADD_LIBRARY(SolarSystemEditor MODULE ${SolarSystemEditor_SRCS} ${SolarSystemEditor_MOC_SRCS} ${SolarSystemEditor_RES_CXX} ${SolarSystemEditor_UIS_H})
46
47 IF(APPLE)
48 FIND_LIBRARY(OPENGL_LIBRARY OpenGL)
49 MARK_AS_ADVANCED(OPENGL_LIBRARY)
50 SET_TARGET_PROPERTIES(SolarSystemEditor PROPERTIES LINK_FLAGS "-undefined dynamic_lookup" SUFFIX ".dylib")
51 ENDIF(APPLE)
52
53 IF(WIN32)
54 SET_TARGET_PROPERTIES(SolarSystemEditor PROPERTIES LINK_FLAGS "-enable-runtime-pseudo-reloc -Wl,--allow-multiple-definition" )
55 SET(StelMain stelMain)
56 ELSE(WIN32)
57 SET(StelMain )
58 ENDIF(WIN32)
59
60 TARGET_LINK_LIBRARIES(SolarSystemEditor ${StelMain} ${extLinkerOption})
61
62 INSTALL(TARGETS SolarSystemEditor DESTINATION "modules/SolarSystemEditor")
63ENDIF()
64
65#Static library
66IF(BUILD_STATIC_PLUGINS)
67 ADD_LIBRARY(SolarSystemEditor-static STATIC ${SolarSystemEditor_SRCS} ${SolarSystemEditor_MOC_SRCS} ${SolarSystemEditor_RES_CXX} ${SolarSystemEditor_UIS_H})
68 SET_TARGET_PROPERTIES(SolarSystemEditor-static PROPERTIES OUTPUT_NAME "SolarSystemEditor")
69 TARGET_LINK_LIBRARIES(SolarSystemEditor-static ${extLinkerOption})
70 IF(WIN32)
71 SET_TARGET_PROPERTIES(SolarSystemEditor-static PROPERTIES COMPILE_FLAGS "-DQT_STATICPLUGIN")
72 ELSE()
73 SET_TARGET_PROPERTIES(SolarSystemEditor-static PROPERTIES COMPILE_FLAGS "-fPIC -DQT_STATICPLUGIN")
74 ENDIF()
75 ADD_DEPENDENCIES(AllStaticPlugins SolarSystemEditor-static)
76ENDIF()
077
=== added file 'plugins/SolarSystemEditor/src/SolarSystemEditor.cpp'
--- plugins/SolarSystemEditor/src/SolarSystemEditor.cpp 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/SolarSystemEditor.cpp 2010-11-16 20:06:17 +0000
@@ -0,0 +1,1535 @@
1/*
2 * Solar System editor plug-in for Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include "SolarSystemEditor.hpp"
22#include "SolarSystemManagerWindow.hpp"
23
24#include "StelApp.hpp"
25#include "StelGui.hpp"
26#include "StelGuiItems.hpp"
27#include "StelFileMgr.hpp"
28#include "StelIniParser.hpp"
29#include "StelLocaleMgr.hpp"
30#include "StelModuleMgr.hpp"
31#include "StelObjectMgr.hpp"
32#include "SolarSystem.hpp"
33
34#include <QDate>
35#include <QDebug>
36#include <QDir>
37#include <QFile>
38#include <QSettings>
39#include <QString>
40
41#include <cmath>
42#include <stdexcept>
43
44
45StelModule* SolarSystemEditorStelPluginInterface::getStelModule() const
46{
47 return new SolarSystemEditor();
48}
49
50StelPluginInfo SolarSystemEditorStelPluginInterface::getPluginInfo() const
51{
52 //Q_INIT_RESOURCE(solarSystemEditor);
53
54 StelPluginInfo info;
55 info.id = "SolarSystemEditor";
56 info.displayedName = "Solar System Editor";
57 info.authors = "Bogdan Marinov";
58 info.contact = "http://stellarium.org";
59 info.description = "An interface for adding asteroids and comets to Stellarium. It can download object lists from the Minor Planet Center's website and perform searches in its online database. Still a work in progress.";
60 return info;
61}
62
63Q_EXPORT_PLUGIN2(SolarSystemEditor, SolarSystemEditorStelPluginInterface)
64
65SolarSystemEditor::SolarSystemEditor()
66{
67 setObjectName("SolarSystemEditor");
68
69 isInitialized = false;
70 mainWindow = NULL;
71 solarSystemConfigurationFile = NULL;
72 solarSystemManager = GETSTELMODULE(SolarSystem);
73
74 //I really hope that the file manager is instantiated before this
75 defaultSolarSystemFilePath = QFileInfo(StelFileMgr::getInstallationDir() + "/data/ssystem.ini").absoluteFilePath();
76 customSolarSystemFilePath = QFileInfo(StelFileMgr::getUserDir() + "/data/ssystem.ini").absoluteFilePath();
77}
78
79SolarSystemEditor::~SolarSystemEditor()
80{
81 if (solarSystemConfigurationFile != NULL)
82 {
83 delete solarSystemConfigurationFile;
84 }
85}
86
87void SolarSystemEditor::init()
88{
89 //Get a list of the "default" Solar System objects' names:
90 //TODO: Use it as validation for the loading of the plug-in
91 if (QFile::exists(defaultSolarSystemFilePath))
92 {
93 defaultSsoIdentifiers = listAllLoadedObjectsInFile(defaultSolarSystemFilePath);
94 }
95 else
96 {
97 //TODO: Better error message
98 qDebug() << "Something is horribly wrong:" << StelFileMgr::getInstallationDir();
99 return;
100 }
101
102 try
103 {
104 //Make sure that a user ssystem.ini actually exists
105 if (!cloneSolarSystemConfigurationFile())
106 return;
107
108 mainWindow = new SolarSystemManagerWindow();
109 }
110 catch (std::runtime_error &e)
111 {
112 qWarning() << "init() error: " << e.what();
113 return;
114 }
115
116 isInitialized = true;
117}
118
119void SolarSystemEditor::deinit()
120{
121 //
122}
123
124void SolarSystemEditor::update(double) //deltaTime
125{
126 //
127}
128
129void SolarSystemEditor::draw(StelCore*) //core
130{
131 //
132}
133
134double SolarSystemEditor::getCallOrder(StelModuleActionName) const// actionName
135{
136 return 0.;
137}
138
139bool SolarSystemEditor::configureGui(bool show)
140{
141 //If the plug-in has failed to initialize, disable the button
142 //TODO: Display a message in the window instead.
143 if (!isInitialized)
144 return false;
145
146 if(show)
147 {
148 mainWindow->setVisible(true);
149
150 //Debugging block
151 //if (cloneSolarSystemConfigurationFile())
152 {
153 //Import Encke for a start
154 /*SsoElements SSO = readMpcOneLineCometElements("0002P 2010 08 6.5102 0.336152 0.848265 186.5242 334.5718 11.7843 20100104 11.5 6.0 2P/Encke MPC 59600");
155 if (!appendToSolarSystemConfigurationFile(SSO))
156 return true;
157 */
158
159 //Import a list of comets on the desktop. The file is from
160 //http://www.minorplanetcenter.org/iau/Ephemerides/Comets/Soft00Cmt.txt
161 //It seems that some entries in the list don't match the described format
162 /*QList<SsoElements> objectList = readMpcOneLineCometElementsFromFile(StelFileMgr::getDesktopDir() + "/Soft00Cmt.txt");
163 if (!appendToSolarSystemConfigurationFile(objectList))
164 return true;
165 */
166
167 //Import Cruithne
168 /*SsoElements asteroid = readMpcOneLineMinorPlanetElements("03753 15.6 0.15 K107N 205.95453 43.77037 126.27658 19.80793 0.5149179 0.98898552 0.9977217 3 MPO183459 488 28 1973-2010 0.58 M-h 3Eh MPC 0000 (3753) Cruithne 20100822");
169 if (!appendToSolarSystemConfigurationFile(asteroid))
170 return true;
171 */
172
173 //Import a list of asteroids. The file is from
174 //http://www.minorplanetcenter.org/iau/Ephemerides/Bright/2010/Soft00Bright.txt
175 /*QList<SsoElements> objectList = readMpcOneLineMinorPlanetElementsFromFile(StelFileMgr::getDesktopDir() + "/Soft00Bright.txt");
176 if (!appendToSolarSystemConfigurationFile(objectList))
177 return true;*/
178
179 //Destroy and re-create the Solal System
180 //solarSystemManager->reloadPlanets();
181 }
182 }
183 return true;
184}
185
186void SolarSystemEditor::updateI18n()
187{
188 //The Solar System MUST be translated before updating the window
189 //TODO: Remove this if/when you merge this module in the Solar System module
190 solarSystemManager->updateI18n();
191
192 if (mainWindow)
193 {
194 mainWindow->languageChanged();
195 }
196}
197
198bool SolarSystemEditor::cloneSolarSystemConfigurationFile()
199{
200 QDir userDataDirectory(StelFileMgr::getUserDir());
201 if (!userDataDirectory.exists())
202 {
203 qDebug() << "Unable to find user data directory:" << userDataDirectory.absolutePath();
204 return false;
205 }
206 if (!userDataDirectory.exists("data") && !userDataDirectory.mkdir("data"))
207 {
208 qDebug() << "Unable to create a \"data\" subdirectory in" << userDataDirectory.absolutePath();
209 return false;
210 }
211
212 if (QFile::exists(customSolarSystemFilePath))
213 {
214 qDebug() << "Using the ssystem.ini file that already exists in the user directory...";
215 return true;
216 }
217
218 if (QFile::exists(defaultSolarSystemFilePath))
219 {
220 qDebug() << "Trying to copy ssystem.ini to" << customSolarSystemFilePath;
221 return QFile::copy(defaultSolarSystemFilePath, customSolarSystemFilePath);
222 }
223 else
224 {
225 qDebug() << "This should be impossible.";
226 return false;
227 }
228}
229
230bool SolarSystemEditor::resetSolarSystemConfigurationFile()
231{
232 if (QFile::exists(customSolarSystemFilePath))
233 {
234 if (!QFile::remove((customSolarSystemFilePath)))
235 {
236 qWarning() << "Unable to delete" << customSolarSystemFilePath
237 << endl << "Please remove the file manually.";
238 return false;
239 }
240 }
241
242 return cloneSolarSystemConfigurationFile();
243}
244
245void SolarSystemEditor::resetSolarSystemToDefault()
246{
247 if (isInitialized)
248 {
249 if (resetSolarSystemConfigurationFile())
250 {
251 //Deselect all currently selected objects
252 StelObjectMgr * objectManager = GETSTELMODULE(StelObjectMgr);
253 //TODO
254 objectManager->unSelect();
255
256 solarSystemManager->reloadPlanets();
257 emit solarSystemChanged();
258 }
259 }
260}
261
262bool SolarSystemEditor::copySolarSystemConfigurationFileTo(QString filePath)
263{
264 if (QFile::exists(customSolarSystemFilePath))
265 {
266 QFileInfo targetFile(filePath);
267 return QFile::copy(customSolarSystemFilePath, targetFile.absoluteFilePath());
268 }
269 else
270 {
271 return false;
272 }
273}
274
275bool SolarSystemEditor::replaceSolarSystemConfigurationFileWith(QString filePath)
276{
277 if (!QFile::exists(filePath))
278 {
279 //TODO: Message
280 return false;
281 }
282
283 //Is it a valid configuration file?
284 QSettings settings(filePath, QSettings::IniFormat);
285 if (settings.status() != QSettings::NoError)
286 {
287 qWarning() << filePath << "is not a valid configuration file.";
288 return false;
289 }
290
291 //Remove the existingfile
292 if (QFile::exists(customSolarSystemFilePath))
293 {
294 if(!QFile::remove(customSolarSystemFilePath))
295 {
296 //TODO: Message
297 return false;
298 }
299 }
300
301 //Copy the new file
302 //If the copy fails, reset to the default configuration
303 if (QFile::copy(filePath, customSolarSystemFilePath))
304 {
305 solarSystemManager->reloadPlanets();
306 emit solarSystemChanged();
307 return true;
308 }
309 else
310 {
311 //TODO: Message
312 if (cloneSolarSystemConfigurationFile())
313 {
314 solarSystemManager->reloadPlanets();
315 emit solarSystemChanged();
316 return true;
317 }
318 else
319 {
320 //TODO: Message
321 return false;
322 }
323 }
324}
325
326QHash<QString,QString> SolarSystemEditor::listAllLoadedObjectsInFile(QString filePath)
327{
328 if (!QFile::exists(filePath))
329 return QHash<QString,QString>();
330
331 QSettings solarSystem(filePath, QSettings::IniFormat);
332 if (solarSystem.status() != QSettings::NoError)
333 return QHash<QString,QString>();
334
335 QStringList groups = solarSystem.childGroups();
336 QStringList planetNames = solarSystemManager->getAllPlanetEnglishNames();
337 QHash<QString,QString> loadedObjects;
338 foreach (QString group, groups)
339 {
340 QString name = solarSystem.value(group + "/name").toString();
341 if (planetNames.contains(name))
342 {
343 loadedObjects.insert(name, group);
344 }
345 }
346 return loadedObjects;
347}
348
349QHash<QString,QString> SolarSystemEditor::listAllLoadedSsoIdentifiers()
350{
351 if (QFile::exists(customSolarSystemFilePath))
352 {
353 return listAllLoadedObjectsInFile(customSolarSystemFilePath);
354 }
355 else
356 {
357 //TODO: Error message
358 return QHash<QString,QString>();
359 }
360}
361
362bool SolarSystemEditor::removeSsoWithName(QString name)
363{
364 if (name.isEmpty())
365 return false;
366
367 //qDebug() << name;
368 if (defaultSsoIdentifiers.keys().contains(name))
369 {
370 qWarning() << "You can't delete the default Solar System objects for the moment.";
371 return false;
372 }
373
374 //Make sure that the file exists
375 if (!QFile::exists(customSolarSystemFilePath))
376 {
377 qDebug() << "Can't remove" << name << "to ssystem.ini: Unable to find" << customSolarSystemFilePath;
378 return false;
379 }
380
381 //Open the file
382 QSettings settings(customSolarSystemFilePath, QSettings::IniFormat);
383 if (settings.status() != QSettings::NoError)
384 {
385 qDebug() << "Error opening ssystem.ini:" << customSolarSystemFilePath;
386 return false;
387 }
388
389 //Remove the section
390 foreach (QString group, settings.childGroups())
391 {
392 if (settings.value(group + "/name").toString() == name)
393 {
394 settings.remove(group);
395 settings.sync();
396 break;
397 }
398 }
399
400 //Deselect all currently selected objects
401 //TODO: I bet that someone will complains, so: unselect only the removed one
402 GETSTELMODULE(StelObjectMgr)->unSelect();
403
404 //Reload the Solar System
405 solarSystemManager->reloadPlanets();
406 emit solarSystemChanged();
407
408 return true;
409}
410
411//TODO: Strings that have failed to be parsed. The usual source of discrepancies is
412//http://www.minorplanetcenter.org/iau/Ephemerides/Comets/Soft00Cmt.txt
413//It seems that some entries in the list don't match the described format.
414/*
415 " CJ95O010 1997 03 31.4141 0.906507 0.994945 130.5321 282.6820 89.3193 20100723 -2.0 4.0 C/1995 O1 (Hale-Bopp) MPC 61436" -> minus sign, fixed
416 " CK09K030 2011 01 9.266 3.90156 1.00000 251.413 0.032 146.680 8.5 4.0 C/2009 K3 (Beshore) MPC 66205" -> lower precision than the spec, fixed
417 " CK10F040 2010 04 6.109 0.61383 1.00000 120.718 237.294 89.143 13.5 4.0 C/2010 F4 (Machholz) MPC 69906" -> lower precision than the spec, fixed
418 " CK10M010 2012 02 7.840 2.29869 1.00000 265.318 82.150 78.373 9.0 4.0 C/2010 M1 (Gibbs) MPC 70817" -> lower precision than the spec, fixed
419 " CK10R010 2011 11 28.457 6.66247 1.00000 96.009 345.949 157.437 6.0 4.0 C/2010 R1 (LINEAR) MPEC 2010-R99" -> lower precision than the spec, fixed
420 "0128P b 2007 06 13.8064 3.062504 0.320891 210.3319 214.3583 4.3606 20100723 8.5 4.0 128P/Shoemaker-Holt MPC 51822" -> fragment, fixed
421 "0141P d 2010 05 29.7106 0.757809 0.749215 149.3298 246.0849 12.8032 20100723 12.0 12.0 141P/Machholz MPC 59599" -> fragment, fixed
422*/
423SsoElements SolarSystemEditor::readMpcOneLineCometElements(QString oneLineElements)
424{
425 SsoElements result;
426
427 QRegExp mpcParser("^\\s*(\\d{4})?([A-Z])((?:\\w{6}|\\s{6})?[0a-zA-Z])?\\s+(\\d{4})\\s+(\\d{2})\\s+(\\d{1,2}\\.\\d{3,4})\\s+(\\d{1,2}\\.\\d{5,6})\\s+(\\d\\.\\d{5,6})\\s+(\\d{1,3}\\.\\d{3,4})\\s+(\\d{1,3}\\.\\d{3,4})\\s+(\\d{1,3}\\.\\d{3,4})\\s+(?:(\\d{4})(\\d\\d)(\\d\\d))?\\s+(\\-?\\d{1,2}\\.\\d)\\s+(\\d{1,2}\\.\\d)\\s+(\\S.{1,54}\\S)(?:\\s+(\\S.*))?$");//
428
429 int match = mpcParser.indexIn(oneLineElements);
430 //qDebug() << "RegExp captured:" << match << mpcParser.capturedTexts();
431
432 if (match < 0)
433 {
434 qWarning() << "No match for" << oneLineElements;
435 return result;
436 }
437
438 QString numberString = mpcParser.cap(1).trimmed();
439 //QChar cometType = mpcParser.cap(2).at(0);
440 QString provisionalDesignation = mpcParser.cap(3).trimmed();
441
442 if (numberString.isEmpty() && provisionalDesignation.isEmpty())
443 {
444 qWarning() << "Comet is missing both comet number AND provisional designation.";
445 return result;
446 }
447
448 QString name = mpcParser.cap(17).trimmed();
449
450 //Fragment suffix
451 if (provisionalDesignation.length() == 1)
452 {
453 QChar fragmentIndex = provisionalDesignation.at(0);
454 name.append(' ');
455 name.append(fragmentIndex.toUpper());
456 }
457
458 if (name.isEmpty())
459 {
460 return SsoElements();
461 }
462 result.insert("name", name);
463
464 QString sectionName = convertToGroupName(name);
465 if (sectionName.isEmpty())
466 {
467 return SsoElements();
468 }
469 result.insert("section_name", sectionName);
470
471 //After a name has been determined, insert the essential keys
472 result.insert("parent", "Sun");
473 result.insert("type", "comet");
474 //"comet_orbit" is used for all cases:
475 //"ell_orbit" interprets distances as kilometers, not AUs
476 result.insert("coord_func","comet_orbit");
477
478 result.insert("lighting", false);
479 result.insert("color", "1.0, 1.0, 1.0");
480 result.insert("tex_map", "nomap.png");
481
482 bool ok = false;
483 //TODO: Use this for VALIDATION!
484
485 int year = mpcParser.cap(4).toInt();
486 int month = mpcParser.cap(5).toInt();
487 double dayFraction = mpcParser.cap(6).toDouble(&ok);
488 int day = (int) dayFraction;
489 QDate datePerihelionPassage(year, month, day);
490 int fraction = (int) ((dayFraction - day) * 24 * 60 * 60);
491 int seconds = fraction % 60; fraction /= 60;
492 int minutes = fraction % 60; fraction /= 60;
493 int hours = fraction % 24;
494 //qDebug() << hours << minutes << seconds << fraction;
495 QTime timePerihelionPassage(hours, minutes, seconds, 0);
496 QDateTime dtPerihelionPassage(datePerihelionPassage, timePerihelionPassage, Qt::UTC);
497 double jdPerihelionPassage = StelUtils::qDateTimeToJd(dtPerihelionPassage);
498 result.insert("orbit_TimeAtPericenter", jdPerihelionPassage);
499
500 double perihelionDistance = mpcParser.cap(7).toDouble(&ok);//AU
501 result.insert("orbit_PericenterDistance", perihelionDistance);
502
503 double eccentricity = mpcParser.cap(8).toDouble(&ok);//degrees
504 result.insert("orbit_Eccentricity", eccentricity);
505
506 double argumentOfPerihelion = mpcParser.cap(9).toDouble(&ok);//J2000.0, degrees
507 result.insert("orbit_ArgOfPericenter", argumentOfPerihelion);
508
509 double longitudeOfTheAscendingNode = mpcParser.cap(10).toDouble(&ok);//J2000.0, degrees
510 result.insert("orbit_AscendingNode", longitudeOfTheAscendingNode);
511
512 double inclination = mpcParser.cap(11).toDouble(&ok);
513 result.insert("orbit_Inclination", inclination);
514
515 double absoluteMagnitude = mpcParser.cap(15).toDouble(&ok);
516 result.insert("absolute_magnitude", absoluteMagnitude);
517
518 //This is not the same "slope parameter" as used in asteroids. Better name?
519 double slopeParameter = mpcParser.cap(16).toDouble(&ok);
520 result.insert("slope_parameter", slopeParameter);
521
522 double radius = 5; //Fictitious
523 result.insert("radius", radius);
524 result.insert("albedo", 1);
525
526 return result;
527}
528
529SsoElements SolarSystemEditor::readMpcOneLineMinorPlanetElements(QString oneLineElements)
530{
531 SsoElements result;
532
533 //This time I'll try splitting the line to columns, instead of
534 //using a regular expression.
535 //Using QString::mid() allows parsing it in a random sequence.
536
537 //Length validation
538 if (oneLineElements.isEmpty() ||
539 oneLineElements.length() > 202 ||
540 oneLineElements.length() < 152) //The column ends at 160, but is left-aligned
541 {
542 return result;
543 }
544
545 QString column;
546 bool ok = false;
547 //bool isLongForm = (oneLineElements.length() > 160) ? true : false;
548
549 //Minor planet number or provisional designation
550 column = oneLineElements.mid(0, 7).trimmed();
551 if (column.isEmpty())
552 {
553 return result;
554 }
555 int minorPlanetNumber = 0;
556 QString provisionalDesignation;
557 QString name;
558 if (column.toInt(&ok) || ok)
559 {
560 minorPlanetNumber = column.toInt();
561 }
562 else
563 {
564 //See if it is a number, but packed
565 //I hope the format is right (I've seen prefixes only between A and P)
566 QRegExp packedMinorPlanetNumber("^([A-Za-z])(\\d+)$");
567 if (packedMinorPlanetNumber.indexIn(column) == 0)
568 {
569 minorPlanetNumber = packedMinorPlanetNumber.cap(2).toInt(&ok);
570 //TODO: Validation
571 QChar prefix = packedMinorPlanetNumber.cap(1).at(0);
572 if (prefix.isUpper())
573 {
574 minorPlanetNumber += ((10 + prefix.toAscii() - 'A') * 10000);
575 }
576 else
577 {
578 minorPlanetNumber += ((10 + prefix.toAscii() - 'a' + 26) * 10000);
579 }
580 }
581 else
582 {
583 provisionalDesignation = unpackMinorPlanetProvisionalDesignation(column);
584 }
585 }
586
587 if (minorPlanetNumber)
588 {
589 name = QString::number(minorPlanetNumber);
590 }
591 else if(provisionalDesignation.isEmpty())
592 {
593 qDebug() << "readMpcOneLineMinorPlanetElements():"
594 << column
595 << "is not a valid number or packed provisional designation";
596 return SsoElements();
597 }
598 else
599 {
600 name = provisionalDesignation;
601 }
602
603 //In case the longer format is used, extract the human-readable name
604 column = oneLineElements.mid(166, 28).trimmed();
605 if (!column.isEmpty())
606 {
607 if (minorPlanetNumber)
608 {
609 QRegExp asteroidName("^\\((\\d+)\\)\\s+(\\S.+)$");
610 if (asteroidName.indexIn(column) == 0)
611 {
612 name = asteroidName.cap(2);
613 result.insert("minor_planet_number", minorPlanetNumber);
614 }
615 else
616 {
617 //Use the whole string, just in case
618 name = column;
619 }
620 }
621 //In the other case, the name is already the provisional designation
622 }
623 if (name.isEmpty())
624 {
625 return SsoElements();
626 }
627 result.insert("name", name);
628
629 //Section name
630 QString sectionName = convertToGroupName(name, minorPlanetNumber);
631 if (sectionName.isEmpty())
632 {
633 return SsoElements();
634 }
635 result.insert("section_name", sectionName);
636
637 //After a name has been determined, insert the essential keys
638 result.insert("parent", "Sun");
639 result.insert("type", "asteroid");
640 //"comet_orbit" is used for all cases:
641 //"ell_orbit" interprets distances as kilometers, not AUs
642 result.insert("coord_func","comet_orbit");
643
644 result.insert("lighting", false);
645 result.insert("color", "1.0, 1.0, 1.0");
646 result.insert("tex_map", "nomap.png");
647
648 //Magnitude and slope parameter
649 column = oneLineElements.mid(8,5).trimmed();
650 double absoluteMagnitude = column.toDouble(&ok);
651 if (!ok)
652 return SsoElements();
653 column = oneLineElements.mid(14,5).trimmed();
654 double slopeParameter = column.toDouble(&ok);
655 if (!ok)
656 return SsoElements();
657 result.insert("absolute_magnitude", absoluteMagnitude);
658 result.insert("slope_parameter", slopeParameter);
659
660 //Orbital parameters
661 column = oneLineElements.mid(37, 9).trimmed();
662 double argumentOfPerihelion = column.toDouble(&ok);//J2000.0, degrees
663 if (!ok)
664 return SsoElements();
665 result.insert("orbit_ArgOfPericenter", argumentOfPerihelion);
666
667 column = oneLineElements.mid(48, 9).trimmed();
668 double longitudeOfTheAscendingNode = column.toDouble(&ok);//J2000.0, degrees
669 if (!ok)
670 return SsoElements();
671 result.insert("orbit_AscendingNode", longitudeOfTheAscendingNode);
672
673 column = oneLineElements.mid(59, 9).trimmed();
674 double inclination = column.toDouble(&ok);//J2000.0, degrees
675 if (!ok)
676 return SsoElements();
677 result.insert("orbit_Inclination", inclination);
678
679 column = oneLineElements.mid(70, 9).trimmed();
680 double eccentricity = column.toDouble(&ok);//degrees
681 if (!ok)
682 return SsoElements();
683 result.insert("orbit_Eccentricity", eccentricity);
684
685 column = oneLineElements.mid(80, 11).trimmed();
686 double meanDailyMotion = column.toDouble(&ok);//degrees per day
687 if (!ok)
688 return SsoElements();
689 result.insert("orbit_MeanMotion", meanDailyMotion);
690
691 column = oneLineElements.mid(92, 11).trimmed();
692 double semiMajorAxis = column.toDouble(&ok);
693 if (!ok)
694 return SsoElements();
695 result.insert("orbit_SemiMajorAxis", semiMajorAxis);
696
697 column = oneLineElements.mid(20, 5).trimmed();//Epoch, in packed form
698 QRegExp packedDateFormat("^([IJK])(\\d\\d)([1-9A-C])([1-9A-V])$");
699 if (packedDateFormat.indexIn(column) != 0)
700 {
701 qDebug() << "readMpcOneLineMinorPlanetElements():"
702 << column << "is not a date in packed format";
703 return SsoElements();
704 }
705 int year = packedDateFormat.cap(2).toInt();
706 switch (packedDateFormat.cap(1).at(0).toAscii())
707 {
708 case 'I':
709 year += 1800;
710 break;
711 case 'J':
712 year += 1900;
713 break;
714 case 'K':
715 default:
716 year += 2000;
717 }
718 int month = unpackDayOrMonthNumber(packedDateFormat.cap(3).at(0));
719 int day = unpackDayOrMonthNumber(packedDateFormat.cap(4).at(0));
720 //qDebug() << column << year << month << day;
721 QDate epochDate(year, month, day);
722 if (!epochDate.isValid())
723 {
724 qDebug() << "readMpcOneLineMinorPlanetElements():"
725 << column << "unpacks to"
726 << QString("%1-%2-%3").arg(year).arg(month).arg(day)
727 << "This is not a valid date for an Epoch.";
728 return SsoElements();
729 }
730 int epochJD = epochDate.toJulianDay();
731 result.insert("orbit_Epoch", epochJD);
732
733 column = oneLineElements.mid(26, 9).trimmed();
734 double meanAnomalyAtEpoch = column.toDouble(&ok);//degrees
735 if (!ok)
736 return SsoElements();
737 result.insert("orbit_MeanAnomaly", meanAnomalyAtEpoch);
738
739 //Radius and albedo
740 //Assume albedo of 0.15 and calculate a radius based on the absolute magnitude
741 //as described here: http://www.physics.sfasu.edu/astro/asteroids/sizemagnitude.html
742 double albedo = 0.15; //Assumed
743 double radius = std::ceil((1329 / std::sqrt(albedo)) * std::pow(10, -0.2 * absoluteMagnitude));
744 result.insert("albedo", albedo);
745 result.insert("radius", radius);
746
747 return result;
748}
749
750SsoElements SolarSystemEditor::readXEphemOneLineElements(QString oneLineElements)
751{
752 SsoElements result;
753
754 enum OrbitType {Elliptic, Hyperbolic, Parabolic} orbitType;
755
756 QStringList fields = oneLineElements.split(',');
757 if (fields.isEmpty() || fields.count() < 10 || fields.count() > 14)
758 return result;
759 //qDebug() << fields;
760
761 QString name = fields.at(0).trimmed();
762 if (name.isEmpty() || fields.at(1).isEmpty())
763 return result;
764
765 QChar orbitTypeFlag = fields.at(1).trimmed().at(0);
766 if (orbitTypeFlag == 'e')
767 orbitType = Elliptic;
768 else if(orbitTypeFlag == 'h')
769 orbitType = Hyperbolic;
770 else if (orbitTypeFlag == 'p')
771 orbitType = Parabolic;
772 else
773 {
774 qDebug() << "Unrecognised orbit type:" << orbitTypeFlag;
775 return result;
776 }
777
778 //"comet_orbit" is used for all cases:
779 //"ell_orbit" interprets distances as kilometers, not AUs
780 result.insert("coord_func", "comet_orbit");
781
782 //Type detection and name parsing
783 QString objectType;
784 int minorPlanetNumber = 0;
785 QRegExp cometProvisionalDesignationStart("^[PCDX]/");
786 QRegExp cometDesignationStart("^(\\d)+[PCDX]/");
787 if (cometDesignationStart.indexIn(name) == 0 ||
788 cometProvisionalDesignationStart.indexIn(name) == 0)
789 {
790 objectType = "comet";
791 }
792 else
793 {
794 objectType = "asteroid";
795 QRegExp asteroidProvisionalDesignation("(\\d{4}\\s[A-Z]{2})(\\d*)$");
796 int pdIndex = asteroidProvisionalDesignation.indexIn(name);
797 if (pdIndex != 0)
798 {
799 int spaceIndex = name.indexOf(' ');
800 if (spaceIndex > 0)
801 {
802 QString numberString = name.left(spaceIndex);
803 //qDebug() << numberString;
804 minorPlanetNumber = numberString.toInt();
805 if (minorPlanetNumber)
806 name = name.right(name.length() - spaceIndex - 1);
807 //qDebug() << name;
808 }
809 }
810 }
811 if (name.isEmpty())
812 {
813 return SsoElements();
814 }
815 result.insert("name", name);
816 result.insert("type", objectType);
817 if (minorPlanetNumber)
818 result.insert("minor_planet_number", minorPlanetNumber);
819
820 //Section name
821 QString sectionName = convertToGroupName(name, minorPlanetNumber);
822 if (sectionName.isEmpty())
823 {
824 return SsoElements();
825 }
826 result.insert("section_name", sectionName);
827
828 //After a name has been determined, insert the essential keys
829 result.insert("parent", "Sun");
830
831 result.insert("lighting", false);
832 result.insert("color", "1.0, 1.0, 1.0");
833 result.insert("tex_map", "nomap.png");
834
835 //Orbital elements
836 bool ok;
837 QString field;
838
839 if (orbitType == Elliptic)
840 field = fields.at(2);//Field 3
841 else
842 field = fields.at(3);//Field 4
843 double inclination = field.trimmed().toDouble(&ok);
844 if (!ok)
845 return SsoElements();
846 result.insert("orbit_Inclination", inclination);
847
848 if (orbitType == Elliptic)
849 field = fields.at(3);//Field 4
850 else if (orbitType == Hyperbolic)
851 field = fields.at(4);//Field 5
852 else
853 field = fields.at(6);//Field 7
854 double longitudeOfTheAscendingNode = field.toDouble(&ok);//J2000.0, degrees
855 if (!ok)
856 return SsoElements();
857 result.insert("orbit_AscendingNode", longitudeOfTheAscendingNode);
858
859 if (orbitType == Hyperbolic)
860 field = fields.at(5);//Field 6
861 else
862 field = fields.at(4);//Field 5
863 double argumentOfPerihelion = field.toDouble(&ok);//J2000.0, degrees
864 if (!ok)
865 return SsoElements();
866 result.insert("orbit_ArgOfPericenter", argumentOfPerihelion);
867
868 if (orbitType == Elliptic)
869 {
870 field = fields.at(5);//Field 6
871 double semiMajorAxis = field.toDouble(&ok);
872 if (!ok)
873 return SsoElements();
874 result.insert("orbit_SemiMajorAxis", semiMajorAxis);
875
876 field = fields.at(6);//Field 7
877 double meanDailyMotion = field.toDouble(&ok);//degrees per day
878 if (!ok)
879 return SsoElements();
880 result.insert("orbit_MeanMotion", meanDailyMotion);
881 }
882
883 double eccentricity;
884 if (orbitType == Elliptic)
885 eccentricity = fields.at(7).toDouble(&ok);//Field 8
886 else if (orbitType == Hyperbolic)
887 eccentricity = fields.at(6).toDouble(&ok);//Field 7
888 else
889 {
890 //Parabolic orbit
891 eccentricity = 1.0;
892 ok = true;
893 }
894 if (!ok)
895 return SsoElements();
896 result.insert("orbit_Eccentricity", eccentricity);
897
898 if (orbitType == Elliptic)
899 {
900 double meanAnomalyAtEpoch = fields.at(8).toDouble(&ok);//degrees
901 if (!ok)
902 return SsoElements();
903 result.insert("orbit_MeanAnomaly", meanAnomalyAtEpoch);
904 }
905
906 if (orbitType == Elliptic)
907 field = fields.at(9);//Field 10
908 else
909 field = fields.at(2);//Field 3
910 QStringList dateStrings = field.trimmed().split('/');
911 //TODO: Validation
912 int year = dateStrings.at(2).toInt();
913 int month = dateStrings.at(0).toInt();
914 double dayFraction = dateStrings.at(1).toDouble(&ok);
915 int day = (int) dayFraction;
916 QDate date(year, month, day);
917 int fraction = (int) ((dayFraction - day) * 24 * 60 * 60);
918 int seconds = fraction % 60; fraction /= 60;
919 int minutes = fraction % 60; fraction /= 60;
920 int hours = fraction % 24;
921 //qDebug() << hours << minutes << seconds << fraction;
922 QTime time(hours, minutes, seconds, 0);
923 QDateTime dt(date, time, Qt::UTC);
924 double jd = StelUtils::qDateTimeToJd(dt);
925 if (orbitType == Elliptic)
926 result.insert("orbit_Epoch", jd);
927 else
928 result.insert("orbit_TimeAtPericenter", jd);
929
930 if (orbitType != Elliptic)
931 {
932 if (orbitType == Hyperbolic)
933 field = fields.at(7);//Field 8
934 else
935 field = fields.at(5);//Field 6
936 double perihelionDistance = field.toDouble(&ok);//AU
937 if (!ok)
938 return SsoElements();
939 result.insert("orbit_PericenterDistance", perihelionDistance);
940 }
941
942 //Magnitude
943 if (orbitType == Elliptic)
944 field = fields.at(11);//Field 12
945 else if (orbitType == Hyperbolic)
946 field = fields.at(9);//Field 10
947 else
948 field = fields.at(8);//Field 9
949 QRegExp magnitudePrefix("^([Hg]\\s*)?(\\d.+)");
950 if (magnitudePrefix.indexIn(field) != 0)
951 return SsoElements();
952 field = magnitudePrefix.cap(2);
953 double absoluteMagnitude = field.toDouble(&ok);
954 if (!ok)
955 return SsoElements();
956 result.insert("absolute_magnitude", absoluteMagnitude);
957
958 if (orbitType == Elliptic)
959 field = fields.at(12);//Field 13
960 else if (orbitType == Hyperbolic)
961 field = fields.at(10);//Field 11
962 else
963 field = fields.at(9);//Field 10
964 double slopeParameter = field.toDouble(&ok);
965 if (!ok)
966 return SsoElements();
967 result.insert("slope_parameter", slopeParameter);
968
969 //Radius and albedo
970 double albedo = 0.04;
971 double radius = 5.0;
972 if (objectType == "asteroid")
973 {
974 //Assume albedo of 0.15 and calculate a radius based on the absolute magnitude
975 //http://www.physics.sfasu.edu/astro/asteroids/sizemagnitude.html
976 albedo = 0.15;
977 radius = std::ceil((1329 / std::sqrt(albedo)) * std::pow(10, -0.2 * absoluteMagnitude));
978 }
979 result.insert("albedo", albedo);
980 result.insert("radius", radius);
981
982 return result;
983}
984
985QList<SsoElements> SolarSystemEditor::readMpcOneLineCometElementsFromFile(QString filePath)
986{
987 QList<SsoElements> objectList;
988
989 if (!QFile::exists(filePath))
990 {
991 qDebug() << "Can't find" << filePath;
992 return objectList;
993 }
994
995 QFile mpcElementsFile(filePath);
996 if (mpcElementsFile.open(QFile::ReadOnly | QFile::Text ))//| QFile::Unbuffered
997 {
998 int candidatesCount = 0;
999 int lineCount = 0;
1000
1001 while(!mpcElementsFile.atEnd())
1002 {
1003 QString oneLineElements = QString(mpcElementsFile.readLine(200));
1004 if(oneLineElements.endsWith('\n'))
1005 {
1006 oneLineElements.chop(1);
1007 }
1008 if (oneLineElements.isEmpty())
1009 {
1010 qDebug() << "Empty line skipped.";
1011 continue;
1012 }
1013 lineCount++;
1014
1015 SsoElements ssObject = readMpcOneLineCometElements(oneLineElements);
1016 if(!ssObject.isEmpty() && !ssObject.value("section_name").toString().isEmpty())
1017 {
1018 objectList << ssObject;
1019 candidatesCount++;
1020 }
1021 }
1022 mpcElementsFile.close();
1023 qDebug() << "Done reading comet orbital elements."
1024 << "Recognized" << candidatesCount << "candidate objects"
1025 << "out of" << lineCount << "lines.";
1026
1027 return objectList;
1028 }
1029 else
1030 {
1031 qDebug() << "Unable to open for reading" << filePath;
1032 qDebug() << "File error:" << mpcElementsFile.errorString();
1033 return objectList;
1034 }
1035
1036 return objectList;
1037}
1038
1039QList<SsoElements> SolarSystemEditor::readMpcOneLineMinorPlanetElementsFromFile(QString filePath)
1040{
1041 QList<SsoElements> objectList;
1042
1043 if (!QFile::exists(filePath))
1044 {
1045 qDebug() << "Can't find" << filePath;
1046 return objectList;
1047 }
1048
1049 QFile mpcElementsFile(filePath);
1050 if (mpcElementsFile.open(QFile::ReadOnly | QFile::Text ))//| QFile::Unbuffered
1051 {
1052 int candidatesCount = 0;
1053 int lineCount = 0;
1054
1055 while(!mpcElementsFile.atEnd())
1056 {
1057 QString oneLineElements = QString(mpcElementsFile.readLine(202 + 2));//Allow for end-of-line characters
1058 if(oneLineElements.endsWith('\n'))
1059 {
1060 oneLineElements.chop(1);
1061 }
1062 if (oneLineElements.isEmpty())
1063 {
1064 qDebug() << "Empty line skipped.";
1065 continue;
1066 }
1067 lineCount++;
1068
1069 SsoElements ssObject = readMpcOneLineMinorPlanetElements(oneLineElements);
1070 if(!ssObject.isEmpty() && !ssObject.value("section_name").toString().isEmpty())
1071 {
1072 objectList << ssObject;
1073 candidatesCount++;
1074 }
1075 }
1076 mpcElementsFile.close();
1077 qDebug() << "Done reading minor planet orbital elements."
1078 << "Recognized" << candidatesCount << "candidate objects"
1079 << "out of" << lineCount << "lines.";
1080
1081 return objectList;
1082 }
1083 else
1084 {
1085 qDebug() << "Unable to open for reading" << filePath;
1086 qDebug() << "File error:" << mpcElementsFile.errorString();
1087 return objectList;
1088 }
1089
1090 return objectList;
1091}
1092
1093QList<SsoElements> SolarSystemEditor::readXEphemOneLineElementsFromFile(QString filePath)
1094{
1095 QList<SsoElements> objectList;
1096
1097 if (!QFile::exists(filePath))
1098 {
1099 qDebug() << "Can't find" << filePath;
1100 return objectList;
1101 }
1102
1103 QFile xEphemElementsFile(filePath);
1104 if (xEphemElementsFile.open(QFile::ReadOnly | QFile::Text ))
1105 {
1106 int candidatesCount = 0;
1107 int lineCount = 0;
1108
1109 while(!xEphemElementsFile.atEnd())
1110 {
1111 QString oneLineElements = QString(xEphemElementsFile.readLine());
1112 if(oneLineElements.endsWith('\n'))
1113 {
1114 oneLineElements.chop(1);
1115 }
1116 if (oneLineElements.isEmpty())
1117 {
1118 qDebug() << "Empty line skipped.";
1119 continue;
1120 }
1121 if (oneLineElements.startsWith('#'))
1122 {
1123 qDebug() << "Comment skipped.";
1124 continue;
1125 }
1126 lineCount++;
1127
1128 SsoElements ssObject = readXEphemOneLineElements(oneLineElements);
1129 if(!ssObject.isEmpty() && !ssObject.value("section_name").toString().isEmpty())
1130 {
1131 objectList << ssObject;
1132 candidatesCount++;
1133 }
1134 }
1135 xEphemElementsFile.close();
1136 qDebug() << "Done reading minor planet orbital elements."
1137 << "Recognized" << candidatesCount << "candidate objects"
1138 << "out of" << lineCount << "lines.";
1139
1140 return objectList;
1141 }
1142 else
1143 {
1144 qDebug() << "Unable to open for reading" << filePath;
1145 qDebug() << "File error:" << xEphemElementsFile.errorString();
1146 return objectList;
1147 }
1148
1149 return objectList;
1150}
1151
1152bool SolarSystemEditor::appendToSolarSystemConfigurationFile(QList<SsoElements> objectList)
1153{
1154 if (objectList.isEmpty())
1155 {
1156 return false;
1157 }
1158
1159 //Check if the configuration file exists
1160 if (!QFile::exists(customSolarSystemFilePath))
1161 {
1162 qDebug() << "Can't append object data to ssystem.ini: Unable to find" << customSolarSystemFilePath;
1163 return false;
1164 }
1165
1166
1167 QHash<QString,QString> loadedObjects = listAllLoadedSsoIdentifiers();
1168
1169 //Remove duplicates (identified by name, not by section name)
1170 QSettings * solarSystemSettings = new QSettings(customSolarSystemFilePath, QSettings::IniFormat);
1171 if (solarSystemSettings->status() != QSettings::NoError)
1172 {
1173 qDebug() << "Error opening ssystem.ini:" << customSolarSystemFilePath;
1174 return false;
1175 }
1176 foreach (SsoElements object, objectList)
1177 {
1178 QString name = object.value("name").toString();
1179 if (name.isEmpty())
1180 continue;
1181
1182 QString group = object.value("section_name").toString();
1183 if (group.isEmpty())
1184 continue;
1185
1186 if (loadedObjects.contains(name))
1187 {
1188 solarSystemSettings->remove(loadedObjects.value(name));
1189 loadedObjects.remove(name);
1190 }
1191 else if (solarSystemSettings->childGroups().contains(group))
1192 {
1193 loadedObjects.remove(solarSystemSettings->value(group + "/name").toString());
1194 solarSystemSettings->remove(group);
1195 }
1196 }
1197 solarSystemSettings->sync();
1198 delete solarSystemSettings;
1199 solarSystemSettings = NULL;
1200
1201 //Write to file
1202 //TODO: The usual validation
1203 qDebug() << "Appending to file...";
1204 QFile solarSystemConfigurationFile(customSolarSystemFilePath);
1205 if(solarSystemConfigurationFile.open(QFile::WriteOnly | QFile::Append | QFile::Text))
1206 {
1207 QTextStream output (&solarSystemConfigurationFile);
1208 bool appendedAtLeastOne = false;
1209
1210 foreach (SsoElements object, objectList)
1211 {
1212 if (!object.contains("section_name"))
1213 continue;
1214
1215 QString sectionName = object.value("section_name").toString();
1216 if (sectionName.isEmpty())
1217 continue;
1218 object.remove("section_name");
1219
1220 QString name = object.value("name").toString();
1221 if (name.isEmpty())
1222 continue;
1223
1224 output << endl << QString("[%1]").arg(sectionName) << endl;
1225 foreach(QString key, object.keys())
1226 {
1227 output << QString("%1 = %2").arg(key).arg(object.value(key).toString()) << endl;
1228 }
1229 output.flush();
1230 qDebug() << "Appended successfully" << sectionName;
1231 appendedAtLeastOne = true;
1232 }
1233
1234 solarSystemConfigurationFile.close();
1235 return appendedAtLeastOne;
1236 }
1237 else
1238 {
1239 qDebug() << "Unable to open for writing" << customSolarSystemFilePath;
1240 return false;
1241 }
1242}
1243
1244bool SolarSystemEditor::appendToSolarSystemConfigurationFile(SsoElements object)
1245{
1246 if (!object.contains("section_name") || object.value("section_name").toString().isEmpty())
1247 {
1248 qDebug() << "appendToSolarSystemConfigurationFile(): Invalid object:" << object;
1249 return false;
1250 }
1251
1252 QList<SsoElements> list;
1253 list << object;
1254 return appendToSolarSystemConfigurationFile(list);
1255}
1256
1257bool SolarSystemEditor::updateSolarSystemConfigurationFile(QList<SsoElements> objectList, UpdateFlags flags)
1258{
1259 if (objectList.isEmpty())
1260 {
1261 //Empty lists can be added without any problem. :)
1262 qWarning() << "updateSolarSystemConfigurationFile(): The source list is empty.";
1263 return true;
1264 }
1265
1266 //Check if the configuration file exists
1267 if (!QFile::exists(customSolarSystemFilePath))
1268 {
1269 qDebug() << "Can't update ssystem.ini: Unable to find" << customSolarSystemFilePath;
1270 return false;
1271 }
1272
1273 QSettings solarSystem(customSolarSystemFilePath, QSettings::IniFormat);
1274 if (solarSystem.status() != QSettings::NoError)
1275 {
1276 qDebug() << "Error opening ssystem.ini:" << customSolarSystemFilePath;
1277 return false;
1278 }
1279 QStringList existingSections = solarSystem.childGroups();
1280 QHash<QString,QString> loadedObjects = listAllLoadedSsoIdentifiers();
1281 //TODO: Move to contstructor?
1282 QStringList orbitalElementsKeys;
1283 orbitalElementsKeys << "coord_func"
1284 << "orbit_ArgOfPericenter"
1285 << "orbit_AscendingNode"
1286 << "orbit_Eccentricity"
1287 << "orbit_Epoch"
1288 << "orbit_Inclination"
1289 << "orbit_LongOfPericenter"
1290 << "orbit_MeanAnomaly"
1291 << "orbit_MeanLongitude"
1292 << "orbit_MeanMotion"
1293 << "orbit_PericenterDistance"
1294 << "orbit_Period"
1295 << "orbit_SemiMajorAxis"
1296 << "orbit_TimeAtPericenter";
1297
1298 qDebug() << "Updating objects...";
1299 foreach (SsoElements object, objectList)
1300 {
1301 QString name = object.value("name").toString();
1302 if (name.isEmpty())
1303 continue;
1304
1305 QString sectionName = object.value("section_name").toString();
1306 if (sectionName.isEmpty())
1307 continue;
1308 object.remove("section_name");
1309
1310 if (loadedObjects.contains(name))
1311 {
1312 if (sectionName != loadedObjects.value(name))
1313 {
1314 //Is this a name conflict between an asteroid and a moon?
1315 QString currentParent = solarSystem.value(loadedObjects.value(name) + "/parent").toString();
1316 QString newParent = object.value("parent").toString();
1317 if (newParent != currentParent)
1318 {
1319 name.append('*');
1320 object.insert("name", name);
1321
1322 if (!existingSections.contains(sectionName))
1323 {
1324 solarSystem.beginGroup(sectionName);
1325 foreach (QString property, object.keys())
1326 {
1327 solarSystem.setValue(property, object.value(property));
1328 }
1329 solarSystem.endGroup();
1330 }
1331 }
1332 else
1333 {
1334 //If the parent is the same, update that object
1335 sectionName = loadedObjects.value(name);
1336 }
1337 }
1338 }
1339 else
1340 {
1341 qDebug() << "Skipping update of" << sectionName << ", as no object with this name exists.";
1342 continue;
1343 }
1344
1345 solarSystem.beginGroup(sectionName);
1346
1347 if (flags.testFlag(UpdateNameAndNumber))
1348 {
1349 updateSsoProperty(solarSystem, object, "name");
1350 updateSsoProperty(solarSystem, object, "minor_planet_number");
1351 }
1352
1353 if (flags.testFlag(UpdateType))
1354 {
1355 updateSsoProperty(solarSystem, object, "type");
1356 }
1357
1358 if (flags.testFlag(UpdateOrbitalElements))
1359 {
1360 //Remove all orbital elements first, in case
1361 //the new ones use another coordinate function
1362 foreach (QString key, orbitalElementsKeys)
1363 {
1364 solarSystem.remove(key);
1365 }
1366
1367 foreach (QString key, orbitalElementsKeys)
1368 {
1369 updateSsoProperty(solarSystem, object, key);
1370 }
1371 }
1372
1373 if (flags.testFlag(UpdateMagnitudeParameters))
1374 {
1375 if (object.contains("absolute_magnitude") && object.contains("slope_parameter"))
1376 {
1377 QString type = solarSystem.value("type").toString();
1378 if (type == "asteroid" || type == "comet" )
1379 {
1380 updateSsoProperty(solarSystem, object, "absolute_magnitude");
1381 updateSsoProperty(solarSystem, object, "slope_parameter");
1382 }
1383 else
1384 {
1385 //TODO: Do what, log a message?
1386 }
1387 }
1388 }
1389
1390 solarSystem.endGroup();
1391 qDebug() << "Updated successfully" << sectionName;
1392 }
1393
1394 return true;
1395}
1396
1397void SolarSystemEditor::updateSsoProperty(QSettings & settings, SsoElements & properties, QString key)
1398{
1399 if (properties.contains(key))
1400 {
1401 settings.setValue(key, properties.value(key));
1402 }
1403}
1404
1405QString SolarSystemEditor::convertToGroupName(QString &name, int minorPlanetNumber)
1406{
1407 //TODO: Should I remove all non-alphanumeric, or only the obviously problematic?
1408 QString groupName(name);
1409 groupName.remove('\\');
1410 groupName.remove('/');
1411 groupName.remove('#');
1412 groupName.remove(' ');
1413 groupName.remove('-');
1414 groupName = groupName.toLower();
1415
1416 //To prevent mix-up between asteroids and satellites:
1417 //insert the minor planet number in the section name
1418 //(if an asteroid is named, it must be numbered)
1419 if (minorPlanetNumber)
1420 {
1421 groupName.prepend(QString::number(minorPlanetNumber));
1422 }
1423
1424 return groupName;
1425}
1426
1427int SolarSystemEditor::unpackDayOrMonthNumber(QChar digit)
1428{
1429 //0-9, 0 is an invalid value, but the function is supposed to return 0 on failure.
1430 if (digit.isDigit())
1431 {
1432 return digit.digitValue();
1433 }
1434
1435 if (digit.isUpper())
1436 {
1437 char letter = digit.toAscii();
1438 if (letter < 'A' || letter > 'V')
1439 return 0;
1440 return (10 + (letter - 'A'));
1441 }
1442 else
1443 {
1444 return 0;
1445 }
1446}
1447
1448int SolarSystemEditor::unpackYearNumber (QChar prefix, int lastTwoDigits)
1449{
1450 int year = lastTwoDigits;
1451 if (prefix == 'I')
1452 year += 1800;
1453 else if (prefix == 'J')
1454 year += 1900;
1455 else if (prefix == 'K')
1456 year += 2000;
1457 else
1458 year = 0; //Error
1459
1460 return year;
1461}
1462
1463//Can be used both for minor planets and comets with no additional modification,
1464//as the regular expression for comets will match only capital letters.
1465int SolarSystemEditor::unpackAlphanumericNumber (QChar prefix, int lastDigit)
1466{
1467 int cycleCount = lastDigit;
1468 if (prefix.isDigit())
1469 cycleCount += prefix.digitValue() * 10;
1470 else if (prefix.isLetter() && prefix.isUpper())
1471 cycleCount += (10 + prefix.toAscii() - QChar('A').toAscii()) * 10;
1472 else if (prefix.isLetter() && prefix.isLower())
1473 cycleCount += (10 + prefix.toAscii() - QChar('a').toAscii()) * 10 + 26*10;
1474 else
1475 cycleCount = 0; //Error
1476
1477 return cycleCount;
1478}
1479
1480QString SolarSystemEditor::unpackMinorPlanetProvisionalDesignation (QString packedDesignation)
1481{
1482 QRegExp packedFormat("^([IJK])(\\d\\d)([A-Z])([\\dA-Za-z])(\\d)([A-Z])$");
1483 if (packedFormat.indexIn(packedDesignation) != 0)
1484 {
1485 QRegExp packedSurveyDesignation("^(PL|T1|T2|T3)S(\\d+)$");
1486 if (packedSurveyDesignation.indexIn(packedDesignation) == 0)
1487 {
1488 int number = packedSurveyDesignation.cap(2).toInt();
1489 if (packedSurveyDesignation.cap(1) == "PL")
1490 {
1491 return QString("%1 P-L").arg(number);
1492 }
1493 else if (packedSurveyDesignation.cap(1) == "T1")
1494 {
1495 return QString("%1 T-1").arg(number);
1496 }
1497 else if (packedSurveyDesignation.cap(1) == "T2")
1498 {
1499 return QString("%1 T-2").arg(number);
1500 }
1501 else
1502 {
1503 return QString("%1 T-3").arg(number);
1504 }
1505 //TODO: Are there any other surveys?
1506 }
1507 else
1508 {
1509 return QString();
1510 }
1511 }
1512
1513 //Year
1514 QChar yearPrefix = packedFormat.cap(1).at(0);
1515 int yearLastTwoDigits = packedFormat.cap(2).toInt();
1516 int year = unpackYearNumber(yearPrefix, yearLastTwoDigits);
1517
1518 //Letters
1519 QString halfMonthLetter = packedFormat.cap(3);
1520 QString secondLetter = packedFormat.cap(6);
1521
1522 //Second letter cycle count
1523 QChar cycleCountPrefix = packedFormat.cap(4).at(0);
1524 int cycleCountLastDigit = packedFormat.cap(5).toInt();
1525 int cycleCount = unpackAlphanumericNumber(cycleCountPrefix, cycleCountLastDigit);
1526
1527 //Assemble the unpacked provisional designation
1528 QString result = QString("%1 %2%3").arg(year).arg(halfMonthLetter).arg(secondLetter);
1529 if (cycleCount != 0)
1530 {
1531 result.append(QString::number(cycleCount));
1532 }
1533
1534 return result;
1535}
01536
=== added file 'plugins/SolarSystemEditor/src/SolarSystemEditor.hpp'
--- plugins/SolarSystemEditor/src/SolarSystemEditor.hpp 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/SolarSystemEditor.hpp 2010-11-16 20:06:17 +0000
@@ -0,0 +1,312 @@
1/*
2 * Solar System editor plug-in for Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifndef _SOLAR_SYSTEM_EDITOR_HPP_
22#define _SOLAR_SYSTEM_EDITOR_HPP_
23
24#include "StelGui.hpp"
25#include "StelModule.hpp"
26//#include "CAIMainWindow.hpp"
27
28#include <QHash>
29#include <QList>
30#include <QString>
31#include <QVariant>
32
33class SolarSystemManagerWindow;
34class SolarSystem;
35class QSettings;
36
37//! Convenience type for storage of SSO properties in ssystem.ini format.
38//! This is an easy way of storing data in the format used in Stellarium's
39//! solar system configuration file.
40//! What would be key/value pairs in a section in the ssystem.ini file
41//! are key/value pairs in the hash. The section name is stored with key
42//! "section_name".
43//! As it is a hash, key names are not stored alphabetically. This allows
44//! for rapid addition and look-up of values, unlike a real QSettings
45//! object in StelIniFormat.
46//! Also, using this way may allow scripts to define SSOs.
47//! \todo Better name.
48typedef QHash<QString, QVariant> SsoElements;
49
50/*!
51 \class SolarSystemEditor
52 \brief Main class of the Solar System Editor plug-in.
53 \author Bogdan Marinov
54
55 Solar System bodies are identified by their names in Stellarium, but entries
56 in the configuration file are identified by their group (section) names.
57 This makes more difficult the detection of duplicates.
58*/
59class SolarSystemEditor : public StelModule
60{
61 Q_OBJECT
62
63public:
64 SolarSystemEditor();
65 virtual ~SolarSystemEditor();
66
67 ///////////////////////////////////////////////////////////////////////////
68 // Methods inherited from the StelModule class
69 //! called when the plug-in is loaded.
70 //! All initializations should be done here.
71 virtual void init();
72 //! called before the plug-in is un-loaded.
73 //! Useful for stopping processes, unloading textures, etc.
74 virtual void deinit();
75 virtual void update(double deltaTime);
76 //! draws on the view port.
77 //! Dialog windows don't need explicit drawing, it's done automatically.
78 //! If a plug-in draws on the screen, it should be able to respect
79 //! the night vision mode.
80 virtual void draw(StelCore * core);
81 virtual double getCallOrder(StelModuleActionName actionName) const;
82 //! called when the "configure" button in the "Plugins" tab is pressed
83 virtual bool configureGui(bool show);
84 virtual void updateI18n();
85
86 //! Reads a single comet's orbital elements from a string.
87 //! This function converts a line of comet orbital elements in MPC format
88 //! to a hash in Stellarium's ssystem.ini format.
89 //! The MPC's one-line orbital elements format for comets
90 //! is described on their website:
91 //! http://www.minorplanetcenter.org/iau/info/CometOrbitFormat.html
92 //! \returns an empty hash if there is an error or the source string is not
93 //! a valid line in MPC format.
94 //! \todo Recognise the long form packed designations (to handle fragments)
95 //! \todo Handle better any unusual symbols in section names (URL encoding?)
96 //! \todo Use column cuts intead of a regular expression?
97 SsoElements readMpcOneLineCometElements(QString oneLineElements);
98
99 //! Reads a single minor planet's orbital elements from a string.
100 //! This function converts a line of minor planet orbital elements in
101 //! MPC format to a hash in Stellarium's ssystem.ini format.
102 //! The MPC's one-line orbital elements format for minor planets
103 //! is described on their website:
104 //! http://www.minorplanetcenter.org/iau/info/MPOrbitFormat.html
105 //! \returns an empty hash if there is an error or the source string is not
106 //! a valid line in MPC format.
107 //! \todo Handle better any unusual symbols in section names (URL encoding?)
108 SsoElements readMpcOneLineMinorPlanetElements(QString oneLineElements);
109
110 //! Reads a single object's orbital elements from a string.
111 //! This function converts a line of orbital elements in XEphem format
112 //! to a hash in Stellarium's ssystem.ini format.
113 //! http://www.clearskyinstitute.com/xephem/help/xephem.html#mozTocId468501
114 //! It recognises only the 'e', 'h' and 'p' types of orbits in XEphem's
115 //! format (comets and minor planets). It is used in handling on-line search
116 //! queries to the MPC's Minor Planet and Comet Ephemeris System, as
117 //! using the MPC format causes long object names to be truncated
118 //! due to the fixed width of the columns.
119 //! An object's type (comet or asteroid) is determined based on its name.
120 SsoElements readXEphemOneLineElements(QString oneLineElements);
121
122 //! Reads a list of comet orbital elements from a file.
123 //! This function reads a list of comet orbital elements in MPC's one-line
124 //! format from a file (one comet per line) and converts it to a list of
125 //! hashes in Stellarium's ssystem.ini format.
126 //! Example source file is the list of observable comets on the MPC's site:
127 //! http://www.minorplanetcenter.org/iau/Ephemerides/Comets/Soft00Cmt.txt
128 //! readMpcOneLineCometElements() is used internally to parse each line.
129 QList<SsoElements> readMpcOneLineCometElementsFromFile(QString filePath);
130
131 //! Reads a list of minor planet orbital elements from a file.
132 //! This function reads a list of minor planets orbital elements in MPC's
133 //! one-line format from a file (one comet per line) and converts it to
134 //! a list of hashes in Stellarium's ssystem.ini format.
135 //! Example source file is the list of bright asteroids on the MPC's site:
136 //! http://www.minorplanetcenter.org/iau/Ephemerides/Bright/2010/Soft00Bright.txt
137 //! readMpcOneLineMinorPlanetElements() is used internally to parse each line.
138 QList<SsoElements> readMpcOneLineMinorPlanetElementsFromFile(QString filePath);
139
140 //! Reads a list of Solar System object orbital elements from a file.
141 //! This function reads a list of Solar System object orbital elements in
142 //! XEphem's one-line format (one object per line, comment lines starting
143 //! with # are skipped) and converts it to a list of hashes in Stellarium's
144 //! ssystem.ini format. XEphem's file format is described in its manual:
145 //! http://www.clearskyinstitute.com/xephem/help/xephem.html#mozTocId468501
146 //! Example source file can be any of the lists of objects on the MPC site:
147 //! http://www.minorplanetcenter.org/iau/Ephemerides/Comets/Soft03Cmt.txt
148 //! http://www.minorplanetcenter.org/iau/Ephemerides/Bright/2010/Soft03Bright.txt
149 //! readXEphemOneLineElements() is used internally to parse each line.
150 QList<SsoElements> readXEphemOneLineElementsFromFile(QString filePath);
151
152 //! Adds a new entry at the end of the user solar system configuration file.
153 //! This function writes directly to the file. See the note on why QSettings
154 //! was not used in the description of
155 //! appendToSolarSystemConfigurationFile(QList<SsoElements>)
156 //! Duplicates are removed: If any section in the file matches the
157 //! "section_name" value of the inserted entry, it is removed.
158 bool appendToSolarSystemConfigurationFile(SsoElements object);
159
160 //! Adds new entries at the end of the user solar system configuration file.
161 //! This function writes directly to the file. QSettings was not used, as:
162 //! - Using QSettings with QSettings::IniFormat causes the list in the
163 //! "color" field (e.g. "1.0, 1.0, 1.0") to be wrapped in double quotation
164 //! marks (Stellarium requires no quotation marks).
165 //! - Using QSettings with StelIniFormat causes unaccepptable append times
166 //! when the file grows (>~40 entries). This most probably happens because
167 //! StelIniParser uses QMap internally for the entry list. QMap orders its
168 //! keys (in the case of strings - alphabetically) and it has to find
169 //! the appropriate place in the ordering for every new key, which takes
170 //! more and more time as the list grows.
171 //!
172 //! Duplicates are removed: If any section in the file matches the
173 //! "section_name" value of a new entry, it is removed.
174 //! Invalid entries in the list (that don't contain a value for
175 //! "section_name" or it is an empty string) are skipped and the processing
176 //! continues from the next entry.
177 //! \todo Protect the default Solar System configuration?
178 //! \todo At least warn when overwriting old entries?
179 bool appendToSolarSystemConfigurationFile(QList<SsoElements>);
180
181 //! Flags to control the updateSolarSystemConfigurationFile() function.
182 enum UpdateFlag {
183 UpdateNameAndNumber = 0x01,//!< Update the name and minor planet number, if any.
184 UpdateType = 0x02, //!< Update objects that lack the "type" parameter
185 UpdateOrbitalElements = 0x04, //!< Update the orbital elements, including the orbit function.
186 UpdateMagnitudeParameters = 0x08 //!< Update the values in the two parameter system, or add them if they are missing and the type allows.
187 };
188 Q_DECLARE_FLAGS(UpdateFlags, UpdateFlag)
189
190 //! Updates entries in the user solar system configuration file.
191 //! \param objects a list of data for already existing objects (non-existing ones are skipped);
192 //! \param flags flags controlling what is being updated. See UpdateFlag.
193 //! \returns false if the operation has failed completely for some reason.
194 bool updateSolarSystemConfigurationFile(QList<SsoElements> objects, UpdateFlags flags);
195
196 //! Returns the names of the objects listed in the default ssystem.ini.
197 //! The default solar system configuration file is assumed to be the one
198 //! in the installation directory.
199 QHash<QString,QString> getDefaultSsoIdentifiers() {return defaultSsoIdentifiers;}
200
201 //! Lists the objects listed in the current user ssystem.ini.
202 //! As the name suggests, the list is compiled when the function is run.
203 QHash<QString,QString> listAllLoadedSsoIdentifiers();
204
205 //! Removes an object from the user Solar System configuration file.
206 //! Reloads the Solar System on successfull removal.
207 //! \arg name true name of the object ("name" parameter in the configuration file)
208 //! \returns true if the entry has been removed successfully or there is
209 //! no such entry
210 //! \returns false if there was an error
211 bool removeSsoWithName(QString name);
212
213 //!
214 bool copySolarSystemConfigurationFileTo(QString filePath);
215 //!
216 bool replaceSolarSystemConfigurationFileWith(QString filePath);
217
218 //! returns the path
219 QString getCustomSolarSystemFilePath() const {return customSolarSystemFilePath;}
220
221public slots:
222 //! Resets the Solar System configuration file and reloads the Solar System.
223 //! \todo Return a bool and make the GUI display a message if it was not successful.
224 void resetSolarSystemToDefault();
225
226signals:
227 //TODO: This should be part of SolarSystem::reloadPlanets()
228 void solarSystemChanged();
229
230private:
231 bool isInitialized;
232
233 //! Main window of the module's GUI
234 SolarSystemManagerWindow * mainWindow;
235
236 QSettings * solarSystemConfigurationFile;
237 SolarSystem * solarSystemManager;
238
239 QString customSolarSystemFilePath;
240 QString defaultSolarSystemFilePath;
241
242 //! A hash matching SSO names with the group names used to identify them
243 //! in the configuration file.
244
245 //! The names and group names of all objects in the default ssystem.ini.
246 //! The keys are the names, the values are the group names.
247 //! Initialized in init().
248 QHash<QString,QString> defaultSsoIdentifiers;
249
250 //! Gets the names of the objects listed in a ssystem.ini-formatted file.
251 //! Used internally in readAllCurrentSsoNames() and in init() to initialize
252 //! defaultSsoNames.
253 //! Does not check if the file exists.
254 QHash<QString,QString> listAllLoadedObjectsInFile(QString filePath);
255
256 //! Creates a copy of the default ssystem.ini file in the user data directory.
257 //! \returns true if a file already exists or the copying has been successful
258 bool cloneSolarSystemConfigurationFile();
259
260 //! Replaces the user copy of ssystem.ini with the default one.
261 //! This function simply deletes the file, if it exists, and calls
262 //! cloneSolarSystemConfigurationFile().
263 //! \returns true if the replacement has been successfull.
264 bool resetSolarSystemConfigurationFile();
265
266 //! Converts an alphanumeric digit as used in MPC packed dates to an integer.
267 //! See http://www.minorplanetcenter.org/iau/info/PackedDates.html
268 //! Interprets the digits from 1 to 9 normally, and the capital leters
269 //! from A to V as numbers between 10 and 31.
270 //! \returns 0 if the digit is invalid (0 is also an invalid ordinal number
271 //! for a day or month, so this is not a problem)
272 int unpackDayOrMonthNumber (QChar digit);
273 //! Converts an alphanumeric year number as used in MPC packed dates to an integer.
274 //! See http://www.minorplanetcenter.org/iau/info/PackedDates.html
275 //! Also used in packed provisional designations, see
276 //! http://www.minorplanetcenter.org/iau/info/PackedDes.html
277 int unpackYearNumber (QChar prefix, int lastTwoDigits);
278 //! Converts a two-character number used in MPC packed provisional designations.
279 //! See http://www.minorplanetcenter.org/iau/info/PackedDes.html
280 //! This function is used for both asteroid and comet designations.
281 int unpackAlphanumericNumber (QChar prefix, int lastDigit);
282
283 //TODO: This should be public and static, perhaps?
284 //! Unpacks an MPC packed minor planet provisional designation.
285 //! See http://www.minorplanetcenter.org/iau/info/PackedDes.html
286 //! \returns an empty string if the argument is not a valid packed
287 //! provisional designation.
288 QString unpackMinorPlanetProvisionalDesignation(QString packedDesignation);
289
290 //! Updates a value in a configuration file with a value with the same key in a SsoElements hash.
291 void updateSsoProperty(QSettings& configuration, SsoElements& properties, QString key);
292
293 //! Converts an object name to a key (group) name in a configuration file.
294 QString convertToGroupName(QString& name, int minorPlanetNumber = 0);
295};
296
297
298#include "fixx11h.h"
299#include <QObject>
300#include "StelPluginInterface.hpp"
301
302//! This class is used by Qt to manage a plug-in interface
303class SolarSystemEditorStelPluginInterface : public QObject, public StelPluginInterface
304{
305 Q_OBJECT
306 Q_INTERFACES(StelPluginInterface)
307public:
308 virtual StelModule* getStelModule() const;
309 virtual StelPluginInfo getPluginInfo() const;
310};
311
312#endif //_SOLAR_SYSTEM_EDITOR_HPP_
0313
=== added directory 'plugins/SolarSystemEditor/src/gui'
=== added file 'plugins/SolarSystemEditor/src/gui/MPCImporterDialogPrototype02.ui'
--- plugins/SolarSystemEditor/src/gui/MPCImporterDialogPrototype02.ui 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/MPCImporterDialogPrototype02.ui 2010-11-16 20:06:17 +0000
@@ -0,0 +1,171 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <author>Bogdan Marinov</author>
4 <class>Form</class>
5 <widget class="QWidget" name="Form">
6 <property name="geometry">
7 <rect>
8 <x>0</x>
9 <y>0</y>
10 <width>400</width>
11 <height>300</height>
12 </rect>
13 </property>
14 <layout class="QVBoxLayout" name="verticalLayout_5">
15 <property name="spacing">
16 <number>0</number>
17 </property>
18 <property name="margin">
19 <number>0</number>
20 </property>
21 <item>
22 <widget class="QStackedWidget" name="stackedWidget">
23 <property name="currentIndex">
24 <number>0</number>
25 </property>
26 <widget class="QWidget" name="page">
27 <layout class="QVBoxLayout" name="verticalLayout">
28 <property name="spacing">
29 <number>0</number>
30 </property>
31 <property name="margin">
32 <number>0</number>
33 </property>
34 <item>
35 <widget class="QGroupBox" name="groupBox">
36 <property name="title">
37 <string>Select source</string>
38 </property>
39 <layout class="QVBoxLayout" name="verticalLayout_2">
40 <item>
41 <widget class="QRadioButton" name="radioButton">
42 <property name="text">
43 <string>Import a single line (one body)</string>
44 </property>
45 </widget>
46 </item>
47 <item>
48 <layout class="QHBoxLayout" name="horizontalLayout">
49 <item>
50 <widget class="QLineEdit" name="lineEdit"/>
51 </item>
52 <item>
53 <widget class="QPushButton" name="pushButton_3">
54 <property name="text">
55 <string>Paste</string>
56 </property>
57 </widget>
58 </item>
59 </layout>
60 </item>
61 <item>
62 <widget class="QRadioButton" name="radioButton_2">
63 <property name="text">
64 <string>Import bodies from a file</string>
65 </property>
66 </widget>
67 </item>
68 <item>
69 <layout class="QHBoxLayout" name="horizontalLayout_2">
70 <item>
71 <widget class="QLineEdit" name="lineEdit_2"/>
72 </item>
73 <item>
74 <widget class="QPushButton" name="pushButton_4">
75 <property name="text">
76 <string>Browse</string>
77 </property>
78 </widget>
79 </item>
80 </layout>
81 </item>
82 <item>
83 <spacer name="verticalSpacer">
84 <property name="orientation">
85 <enum>Qt::Vertical</enum>
86 </property>
87 <property name="sizeHint" stdset="0">
88 <size>
89 <width>20</width>
90 <height>40</height>
91 </size>
92 </property>
93 </spacer>
94 </item>
95 </layout>
96 </widget>
97 </item>
98 </layout>
99 </widget>
100 <widget class="QWidget" name="page_2">
101 <layout class="QVBoxLayout" name="verticalLayout_3">
102 <property name="spacing">
103 <number>0</number>
104 </property>
105 <property name="margin">
106 <number>0</number>
107 </property>
108 <item>
109 <widget class="QGroupBox" name="groupBox_2">
110 <property name="title">
111 <string>Objects found</string>
112 </property>
113 <layout class="QVBoxLayout" name="verticalLayout_4">
114 <item>
115 <widget class="QLabel" name="label">
116 <property name="text">
117 <string>Mark the objects you wish to be imported.</string>
118 </property>
119 </widget>
120 </item>
121 <item>
122 <widget class="QListWidget" name="listWidget">
123 <item>
124 <property name="text">
125 <string notr="true">2P/Encke</string>
126 </property>
127 <property name="checkState">
128 <enum>Unchecked</enum>
129 </property>
130 <property name="flags">
131 <set>ItemIsSelectable|ItemIsUserCheckable|ItemIsEnabled</set>
132 </property>
133 </item>
134 </widget>
135 </item>
136 </layout>
137 </widget>
138 </item>
139 </layout>
140 </widget>
141 </widget>
142 </item>
143 <item>
144 <layout class="QHBoxLayout" name="horizontalLayout_3">
145 <property name="leftMargin">
146 <number>10</number>
147 </property>
148 <property name="rightMargin">
149 <number>10</number>
150 </property>
151 <item>
152 <widget class="QPushButton" name="pushButton">
153 <property name="text">
154 <string>Next</string>
155 </property>
156 </widget>
157 </item>
158 <item>
159 <widget class="QPushButton" name="pushButton_2">
160 <property name="text">
161 <string>Cancel</string>
162 </property>
163 </widget>
164 </item>
165 </layout>
166 </item>
167 </layout>
168 </widget>
169 <resources/>
170 <connections/>
171</ui>
0172
=== added file 'plugins/SolarSystemEditor/src/gui/ManualImportWindow.cpp'
--- plugins/SolarSystemEditor/src/gui/ManualImportWindow.cpp 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/ManualImportWindow.cpp 2010-11-16 20:06:17 +0000
@@ -0,0 +1,257 @@
1/*
2 * Solar System editor plug-in for Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include "SolarSystemEditor.hpp"
22
23#include "ManualImportWindow.hpp"
24#include "ui_manualImportWindow.h"
25
26#include <QColor>
27#include <QColorDialog>
28#include <QFileDialog>
29#include <QImageReader>
30
31#include "StelApp.hpp"
32#include "StelFileMgr.hpp"
33#include "StelModuleMgr.hpp"
34
35
36ManualImportWindow::ManualImportWindow()
37{
38 ui = new Ui_manualImportWindow();
39 ssoManager = GETSTELMODULE(SolarSystemEditor);
40}
41
42ManualImportWindow::~ManualImportWindow()
43{
44 delete ui;
45}
46
47void ManualImportWindow::createDialogContent()
48{
49 ui->setupUi(dialog);
50
51 //Signals
52 connect(ui->closeStelWindow, SIGNAL(clicked()), this, SLOT(close()));
53
54 connect(ui->lineEditColor, SIGNAL(textChanged(QString)), this, SLOT(parseColorString(QString)));
55 connect(ui->pushButtonSelectColor, SIGNAL(clicked()), this, SLOT(selectColor()));
56
57 connect(ui->pushButtonSelectTexture, SIGNAL(clicked()), this, SLOT(selectPlanetTextureFile()));
58 connect(ui->pushButtonSelectRingTexture, SIGNAL(clicked()), this, SLOT(selectRingTextureFile()));
59
60 ui->labelLongitudeOfTheAscendingNode->setText(QString("Longitude of the ascending node %1:").arg(QChar(0x03A9)));//Capital omega
61 ui->radioButtonArgumentOfPeriapsis->setText(QString("Argument of periapsis %1:").arg(QChar(0x3C9)));//Lowercase omega
62 ui->radioButtonLongitudeOfPeriapsis->setText(QString("Longitude of periapsis %1:").arg(QChar(0x3D6)));
63
64 //TODO: Move to "set defaults" function
65 ui->lineEditColor->setText("1.0, 1.0, 1.0");
66 ui->lineEditTexture->setText("nomap.png");
67 ui->lineEditRingTexture->setText("saturn_rings_radial.png");
68}
69
70void ManualImportWindow::languageChanged()
71{
72 if (dialog)
73 ui->retranslateUi(dialog);
74}
75
76void ManualImportWindow::selectColor()
77{
78 QColor color = QColorDialog::getColor(objectColor);
79 objectColor = color;
80 ui->lineEditColor->setText(QString("%1, %2, %3").arg(color.redF()).arg(color.greenF()).arg(color.blueF()));
81 setColorButtonColor(color);
82}
83
84void ManualImportWindow::parseColorString(QString colorCode)
85{
86 QStringList colorComponents = colorCode.split(QChar(','));
87 int count = colorComponents.count();
88 if (count < 3 || count > 4)
89 return;
90
91 bool ok;
92 double red = colorComponents.at(0).toDouble(&ok);
93 if (!ok || red < 0.0 || red > 1.0)
94 return;
95 double green = colorComponents.at(1).toDouble(&ok);
96 if (!ok || green < 0.0 || green > 1.0)
97 return;
98 double blue = colorComponents.at(2).toDouble(&ok);
99 if (!ok || blue < 0.0 || blue > 1.0)
100 return;
101
102 QColor color;
103 color.setRedF(red);
104 color.setGreenF(green);
105 color.setBlueF(blue);
106
107 if (count == 4)
108 {
109 double alpha = colorComponents.at(3).toDouble(&ok);
110 if (!ok || alpha < 0.0 || alpha > 1.0)
111 return;
112 color.setAlphaF(alpha);
113 }
114
115 objectColor = color;
116 setColorButtonColor(color);
117}
118
119void ManualImportWindow::setColorButtonColor(QColor newColor)
120{
121 qDebug() << "setColorButtonColor()";
122 QPixmap pixmap(16, 16);
123 pixmap.fill(newColor);
124 ui->pushButtonSelectColor->setIcon(QIcon(pixmap));
125}
126
127void ManualImportWindow::toggleCometOrbit(bool)
128{
129 //
130}
131
132void ManualImportWindow::toggleEllipticOrbit(bool)
133{
134 //
135}
136
137void ManualImportWindow::toggleObjectSpecificOrbit(bool)
138{
139 //
140}
141
142void ManualImportWindow::toggleMeanMotionOrPeriod(bool)
143{
144 //
145}
146
147void ManualImportWindow::selectPlanetTextureFile()
148{
149 selectTextureFile(ui->lineEditTexture);
150}
151
152void ManualImportWindow::selectRingTextureFile()
153{
154 selectTextureFile(ui->lineEditRingTexture);
155}
156
157void ManualImportWindow::selectTextureFile(QLineEdit * filePathLineEdit)
158{
159 //Find out the parent directory of the last selected file.
160 //Open the textures directory if no file have been selected.
161 QString texturesDirectoryPath;
162 QString currentFileName = filePathLineEdit->text();
163 if (currentFileName.isEmpty())
164 {
165 try
166 {
167 texturesDirectoryPath = StelFileMgr::findFile("textures", StelFileMgr::Directory);
168 }
169 catch (std::runtime_error &e)
170 {
171 qDebug() << e.what();
172 return;
173 }
174 }
175 else
176 {
177 QString currentFilePath;
178 try
179 {
180 currentFilePath = StelFileMgr::findFile("textures/" + currentFileName, StelFileMgr::File);
181 }
182 catch (std::runtime_error &e)
183 {
184 qDebug() << e.what();
185 filePathLineEdit->clear();
186 return;
187 }
188 if (currentFilePath.isEmpty())
189 {
190 filePathLineEdit->clear();
191 return;
192 }
193 QFileInfo currentFileInfo(currentFilePath);
194 texturesDirectoryPath = currentFileInfo.canonicalPath();
195 }
196
197 //Select an existing file
198 QStringList supportedFormats;
199 foreach (QByteArray format, QImageReader::supportedImageFormats())
200 {
201 supportedFormats.append(QString("*.%1").arg(QString(format)));//It's a wee bit long...
202 }
203 QString fileFilter = QString("Texture files (%1)").arg(supportedFormats.join(" "));
204 QString newFilePath = QFileDialog::getOpenFileName(0, QString(), texturesDirectoryPath, fileFilter);
205
206 //Is the file in one of the two "textures" directories?
207 if (newFilePath.isEmpty())
208 return;
209 QFileInfo newFileInfo(newFilePath);
210 QDir newFileParentDirectory = newFileInfo.dir();
211 if (newFileParentDirectory.dirName() != "textures")
212 return;
213 QDir installedTexturesDirectory(StelFileMgr::getInstallationDir() + "/textures");
214 QDir userTexturesDirectory(StelFileMgr::getUserDir() + "/textures");
215 if (newFileParentDirectory != installedTexturesDirectory && newFileParentDirectory != userTexturesDirectory)
216 return;
217
218 if (verifyTextureFile(newFileInfo.canonicalFilePath()))
219 filePathLineEdit->setText(newFileInfo.fileName());
220}
221
222bool ManualImportWindow::verifyTextureFile(QString filePath)
223{
224 //TODO: Absolute path? File exists?
225
226 QPixmap texture(filePath);
227
228 if (texture.isNull())
229 {
230 qDebug() << "File doesn't exist or is not an accepted texure format:"
231 << filePath;
232 return false;
233 }
234
235 if (!verifyPowerOfTwo(texture.height()))
236 {
237 qDebug() << "Invalid texure height:" << texture.height()
238 << "for file" << filePath;
239 return false;
240 }
241 if (!verifyPowerOfTwo(texture.width()))
242 {
243 qDebug() << "Invalid texture width:" << texture.width()
244 << "for file" << filePath;
245 return false;
246 }
247
248 return true;
249}
250
251bool ManualImportWindow::verifyPowerOfTwo(int value)
252{
253 if (value > 0 && (value & (value-1)) == 0)
254 return true;
255 else
256 return false;
257}
0258
=== added file 'plugins/SolarSystemEditor/src/gui/ManualImportWindow.hpp'
--- plugins/SolarSystemEditor/src/gui/ManualImportWindow.hpp 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/ManualImportWindow.hpp 2010-11-16 20:06:17 +0000
@@ -0,0 +1,79 @@
1/*
2 * Solar System editor plug-in for Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifndef _MANUAL_IMPORT_WINDOW_
22#define _MANUAL_IMPORT_WINDOW_
23
24#include <QObject>
25#include "StelDialog.hpp"
26
27#include "SolarSystemEditor.hpp"
28
29#include <QColor>
30
31class Ui_manualImportWindow;
32class QLineEdit;
33
34/*! \brief Window for manual entry of Solar System object properties.
35 \author Bogdan Marinov
36*/
37class ManualImportWindow : public StelDialog
38{
39 Q_OBJECT
40public:
41 ManualImportWindow();
42 virtual ~ManualImportWindow();
43 void languageChanged();
44
45private slots:
46 //TODO: Object type
47
48 void selectColor();
49 void parseColorString(QString);
50
51 void toggleCometOrbit(bool);
52 void toggleEllipticOrbit(bool);
53 void toggleObjectSpecificOrbit(bool);
54
55 void toggleMeanMotionOrPeriod(bool);
56
57 void selectPlanetTextureFile();
58 void selectRingTextureFile();
59 //TODO: Parse input in the line edits? (Otherwise, leave them read-only.)
60
61private:
62 SolarSystemEditor * ssoManager;
63
64 QColor objectColor;
65
66 void setColorButtonColor(QColor newColor);
67
68 void selectTextureFile(QLineEdit * filePathLineEdit);
69 //! Check if a file is a valid graphics file with OpenGL texture dimensions.
70 //! OpenGL accepts only dimentions that are powers of 2 (512, 1024, etc.)
71 bool verifyTextureFile(QString filePath);
72 bool verifyPowerOfTwo(int value);
73
74protected:
75 virtual void createDialogContent();
76 Ui_manualImportWindow * ui;
77};
78
79#endif //_MANUAL_IMPORT_WINDOW_
080
=== added file 'plugins/SolarSystemEditor/src/gui/MpcImportWindow.cpp'
--- plugins/SolarSystemEditor/src/gui/MpcImportWindow.cpp 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/MpcImportWindow.cpp 2010-11-16 20:06:17 +0000
@@ -0,0 +1,958 @@
1/*
2 * Solar System editor plug-in for Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include "SolarSystemEditor.hpp"
22
23#include "MpcImportWindow.hpp"
24#include "ui_mpcImportWindow.h"
25
26#include "StelApp.hpp"
27#include "StelFileMgr.hpp"
28#include "StelJsonParser.hpp"
29#include "StelModuleMgr.hpp"
30#include "SolarSystem.hpp"
31
32#include <QApplication>
33#include <QClipboard>
34#include <QFileDialog>
35#include <QHash>
36#include <QList>
37#include <QNetworkAccessManager>
38#include <QNetworkRequest>
39#include <QNetworkReply>
40#include <QString>
41#include <QTemporaryFile>
42#include <QTimer>
43#include <QUrl>
44
45MpcImportWindow::MpcImportWindow()
46{
47 ui = new Ui_mpcImportWindow();
48 ssoManager = GETSTELMODULE(SolarSystemEditor);
49
50 networkManager = StelApp::getInstance().getNetworkAccessManager();
51
52 downloadReply = NULL;
53 queryReply = NULL;
54 downloadProgressBar = NULL;
55 queryProgressBar = NULL;
56
57 countdownTimer = new QTimer(this);
58
59 QHash<QString,QString> asteroidBookmarks;
60 QHash<QString,QString> cometBookmarks;
61 bookmarks.insert(MpcComets, cometBookmarks);
62 bookmarks.insert(MpcMinorPlanets, asteroidBookmarks);
63}
64
65MpcImportWindow::~MpcImportWindow()
66{
67 delete ui;
68 delete countdownTimer;
69 if (downloadReply)
70 downloadReply->deleteLater();
71 if (queryReply)
72 queryReply->deleteLater();
73 if (downloadProgressBar)
74 downloadProgressBar->deleteLater();
75 if (queryProgressBar)
76 queryProgressBar->deleteLater();
77}
78
79void MpcImportWindow::createDialogContent()
80{
81 ui->setupUi(dialog);
82
83 //Signals
84 connect(ui->closeStelWindow, SIGNAL(clicked()), this, SLOT(close()));
85
86 connect(ui->pushButtonAcquire, SIGNAL(clicked()), this, SLOT(acquireObjectData()));
87 connect(ui->pushButtonAbortDownload, SIGNAL(clicked()), this, SLOT(abortDownload()));
88 connect(ui->pushButtonAdd, SIGNAL(clicked()), this, SLOT(addObjects()));
89 connect(ui->pushButtonDiscard, SIGNAL(clicked()), this, SLOT(discardObjects()));
90
91 connect(ui->pushButtonBrowse, SIGNAL(clicked()), this, SLOT(selectFile()));
92 connect(ui->pushButtonPasteURL, SIGNAL(clicked()), this, SLOT(pasteClipboardURL()));
93 connect(ui->comboBoxBookmarks, SIGNAL(currentIndexChanged(QString)), this, SLOT(bookmarkSelected(QString)));
94
95 //connect(ui->radioButtonSingle, SIGNAL(toggled(bool)), ui->frameSingle, SLOT(setVisible(bool)));
96 connect(ui->radioButtonFile, SIGNAL(toggled(bool)), ui->frameFile, SLOT(setVisible(bool)));
97 connect(ui->radioButtonURL, SIGNAL(toggled(bool)), ui->frameURL, SLOT(setVisible(bool)));
98
99 connect(ui->radioButtonAsteroids, SIGNAL(toggled(bool)), this, SLOT(switchImportType(bool)));
100 connect(ui->radioButtonComets, SIGNAL(toggled(bool)), this, SLOT(switchImportType(bool)));
101
102 connect(ui->pushButtonMarkAll, SIGNAL(clicked()), this, SLOT(markAll()));
103 connect(ui->pushButtonMarkNone, SIGNAL(clicked()), this, SLOT(unmarkAll()));
104
105 connect(ui->pushButtonSendQuery, SIGNAL(clicked()), this, SLOT(sendQuery()));
106 connect(ui->pushButtonAbortQuery, SIGNAL(clicked()), this, SLOT(abortQuery()));
107 connect(ui->lineEditQuery, SIGNAL(textEdited(QString)), this, SLOT(resetNotFound()));
108 //connect(ui->lineEditQuery, SIGNAL(editingFinished()), this, SLOT(sendQuery()));
109 connect(countdownTimer, SIGNAL(timeout()), this, SLOT(updateCountdown()));
110
111 loadBookmarks();
112
113 resetCountdown();
114 resetDialog();
115}
116
117void MpcImportWindow::resetDialog()
118{
119 ui->stackedWidget->setCurrentIndex(0);
120
121 //ui->tabWidget->setCurrentIndex(0);
122 ui->groupBoxType->setVisible(true);
123 ui->radioButtonAsteroids->setChecked(true);
124
125 ui->radioButtonFile->setChecked(true);
126 ui->frameURL->setVisible(false);
127
128 ui->lineEditFilePath->clear();
129 ui->lineEditQuery->clear();
130 ui->lineEditURL->setText("http://");
131 ui->checkBoxAddBookmark->setChecked(false);
132 ui->frameBookmarkTitle->setVisible(false);
133 ui->comboBoxBookmarks->setCurrentIndex(0);
134
135 ui->radioButtonUpdate->setChecked(true);
136 ui->checkBoxOnlyOrbitalElements->setChecked(true);
137
138 //TODO: Is this the right place?
139 ui->pushButtonAbortQuery->setVisible(false);
140 ui->pushButtonAbortDownload->setVisible(false);
141
142 //Resetting the dialog should not reset the timer
143 //resetCountdown();
144 resetNotFound();
145 enableInterface(true);
146}
147
148void MpcImportWindow::populateBookmarksList()
149{
150 ui->comboBoxBookmarks->clear();
151 ui->comboBoxBookmarks->addItem("Select bookmark...");
152 QStringList bookmarkTitles(bookmarks.value(importType).keys());
153 bookmarkTitles.sort();
154 ui->comboBoxBookmarks->addItems(bookmarkTitles);
155}
156
157void MpcImportWindow::languageChanged()
158{
159 if (dialog)
160 ui->retranslateUi(dialog);
161}
162
163void MpcImportWindow::acquireObjectData()
164{
165 if (ui->radioButtonFile->isChecked())
166 {
167 QString filePath = ui->lineEditFilePath->text();
168 if (filePath.isEmpty())
169 return;
170
171 QList<SsoElements> objects = readElementsFromFile(importType, filePath);
172 if (objects.isEmpty())
173 return;
174
175 //Temporary, until the slot/socket mechanism is ready
176 populateCandidateObjects(objects);
177 ui->stackedWidget->setCurrentIndex(1);
178 }
179 else if (ui->radioButtonURL->isChecked())
180 {
181 QString url = ui->lineEditURL->text();
182 if (url.isEmpty())
183 return;
184 startDownload(url);
185 }
186 //close();
187}
188
189void MpcImportWindow::addObjects()
190{
191 disconnect(ssoManager, SIGNAL(solarSystemChanged()), this, SLOT(resetDialog()));
192
193 QList<QString> checkedObjectsNames;
194
195 //Extract the marked objects
196 while (ui->listWidgetObjects->count() > 0)
197 {
198 QListWidgetItem * item = ui->listWidgetObjects->takeItem(0);
199 if (item->checkState() == Qt::Checked)
200 {
201 checkedObjectsNames.append(item->text());
202 }
203 delete item;
204 }
205 //qDebug() << "Checked:" << checkedObjectsNames;
206
207 QList<SsoElements> approvedForAddition;
208 for (int i = 0; i < candidatesForAddition.count(); i++)
209 {
210 QString name = candidatesForAddition.at(i).value("name").toString();
211 if (checkedObjectsNames.contains(name))
212 approvedForAddition.append(candidatesForAddition.at(i));
213 }
214
215 bool overwrite = ui->radioButtonOverwrite->isChecked();
216 QList<SsoElements> approvedForUpdate;
217 for (int j = 0; j < candidatesForUpdate.count(); j++)
218 {
219 QString name = candidatesForUpdate.at(j).value("name").toString();
220 if (checkedObjectsNames.contains(name))
221 {
222 if (overwrite)
223 {
224 approvedForAddition.append(candidatesForUpdate.at(j));
225 }
226 else
227 {
228 approvedForUpdate.append(candidatesForUpdate.at(j));
229 }
230 }
231 }
232
233 //Write to file
234 ssoManager->appendToSolarSystemConfigurationFile(approvedForAddition);
235
236 if (ui->radioButtonUpdate->isChecked())
237 {
238 SolarSystemEditor::UpdateFlags flags(SolarSystemEditor::UpdateNameAndNumber | SolarSystemEditor::UpdateOrbitalElements);
239 if (!ui->checkBoxOnlyOrbitalElements->isChecked())
240 {
241 flags |= SolarSystemEditor::UpdateType;
242 flags |= SolarSystemEditor::UpdateMagnitudeParameters;
243 }
244
245 ssoManager->updateSolarSystemConfigurationFile(approvedForUpdate, flags);
246 }
247
248 //Refresh the Solar System
249 GETSTELMODULE(SolarSystem)->reloadPlanets();
250
251 resetDialog();
252 emit objectsImported();
253}
254
255void MpcImportWindow::discardObjects()
256{
257 resetDialog();
258}
259
260void MpcImportWindow::pasteClipboardURL()
261{
262 ui->lineEditURL->setText(QApplication::clipboard()->text());
263}
264
265void MpcImportWindow::selectFile()
266{
267 QString filePath = QFileDialog::getOpenFileName(NULL, "Select a text file", StelFileMgr::getDesktopDir());
268 ui->lineEditFilePath->setText(filePath);
269}
270
271void MpcImportWindow::bookmarkSelected(QString bookmarkTitle)
272{
273 if (bookmarkTitle.isEmpty() || bookmarkTitle == "Select bookmark...")
274 {
275 ui->lineEditURL->clear();
276 return;
277 }
278 QString bookmarkUrl = bookmarks.value(importType).value(bookmarkTitle);
279 ui->lineEditURL->setText(bookmarkUrl);
280}
281
282void MpcImportWindow::populateCandidateObjects(QList<SsoElements> objects)
283{
284 candidatesForAddition.clear();
285
286 //Get a list of the current objects
287 QHash<QString,QString> defaultSsoIdentifiers = ssoManager->getDefaultSsoIdentifiers();
288 QHash<QString,QString> loadedSsoIdentifiers = ssoManager->listAllLoadedSsoIdentifiers();
289
290 //Separating the objects into visual groups in the list
291 int newDefaultSsoIndex = 0;
292 int newLoadedSsoIndex = 0;
293 int newNovelSsoIndex = 0;
294 int insertionIndex = 0;
295
296 QListWidget * list = ui->listWidgetObjects;
297 list->clear();
298 foreach (SsoElements object, objects)
299 {
300 QString name = object.value("name").toString();
301 if (name.isEmpty())
302 continue;
303
304 QString group = object.value("section_name").toString();
305 if (group.isEmpty())
306 continue;
307
308 //Prevent name conflicts between asteroids and moons
309 if (loadedSsoIdentifiers.contains(name))
310 {
311 if (loadedSsoIdentifiers.value(name) != group)
312 {
313 name.append('*');
314 object.insert("name", name);
315 }
316 }
317
318 QListWidgetItem * item = new QListWidgetItem();
319 item->setText(name);
320 item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
321 item->setCheckState(Qt::Unchecked);
322
323 if (defaultSsoIdentifiers.contains(name))
324 {
325 //Duplicate of a default solar system object
326 QFont itemFont(item->font());
327 itemFont.setBold(true);
328 item->setFont(itemFont);
329
330 candidatesForUpdate.append(object);
331
332 insertionIndex = newDefaultSsoIndex;
333 newDefaultSsoIndex++;
334 newLoadedSsoIndex++;
335 newNovelSsoIndex++;
336 }
337 else if (loadedSsoIdentifiers.contains(name))
338 {
339 //Duplicate of another existing object
340 QFont itemFont(item->font());
341 itemFont.setItalic(true);
342 item->setFont(itemFont);
343
344 candidatesForUpdate.append(object);
345
346 insertionIndex = newLoadedSsoIndex;
347 newLoadedSsoIndex++;
348 newNovelSsoIndex++;
349 }
350 else
351 {
352 candidatesForAddition.append(object);
353
354 insertionIndex = newNovelSsoIndex;
355 newNovelSsoIndex++;
356 }
357
358 list->insertItem(insertionIndex, item);
359 }
360
361 //Select the first item
362 if (list->count() > 0)
363 list->setCurrentRow(0);
364}
365
366void MpcImportWindow::enableInterface(bool enable)
367{
368 ui->groupBoxType->setVisible(enable);
369
370 ui->frameFile->setEnabled(enable);
371 ui->frameURL->setEnabled(enable);
372
373 ui->radioButtonFile->setEnabled(enable);
374 ui->radioButtonURL->setEnabled(enable);
375
376 ui->pushButtonAcquire->setEnabled(enable);
377}
378
379SsoElements MpcImportWindow::readElementsFromString (QString elements)
380{
381 Q_ASSERT(ssoManager);
382
383 switch (importType)
384 {
385 case MpcComets:
386 return ssoManager->readMpcOneLineCometElements(elements);
387 case MpcMinorPlanets:
388 default:
389 return ssoManager->readMpcOneLineMinorPlanetElements(elements);
390 }
391}
392
393QList<SsoElements> MpcImportWindow::readElementsFromFile(ImportType type, QString filePath)
394{
395 Q_ASSERT(ssoManager);
396
397 switch (type)
398 {
399 case MpcComets:
400 return ssoManager->readMpcOneLineCometElementsFromFile(filePath);
401 case MpcMinorPlanets:
402 default:
403 return ssoManager->readMpcOneLineMinorPlanetElementsFromFile(filePath);
404 }
405}
406
407void MpcImportWindow::switchImportType(bool)
408{
409 if (ui->radioButtonAsteroids->isChecked())
410 {
411 importType = MpcMinorPlanets;
412 }
413 else
414 {
415 importType = MpcComets;
416 }
417
418 populateBookmarksList();
419
420 //Clear the fields
421 //ui->lineEditSingle->clear();
422 ui->lineEditFilePath->clear();
423 ui->lineEditURL->clear();
424
425 //If one of the options is selected, show the rest of the dialog
426 ui->groupBoxSource->setVisible(true);
427}
428
429void MpcImportWindow::markAll()
430{
431 QListWidget * const list = ui->listWidgetObjects;
432 int rowCount = list->count();
433 if (rowCount < 1)
434 return;
435
436 for (int row = 0; row < rowCount; row++)
437 {
438 QListWidgetItem * item = list->item(row);
439 if (item)
440 {
441 item->setCheckState(Qt::Checked);
442 }
443 }
444}
445
446void MpcImportWindow::unmarkAll()
447{
448 QListWidget * const list = ui->listWidgetObjects;
449 int rowCount = list->count();
450 if (rowCount < 1)
451 return;
452
453 for (int row = 0; row < rowCount; row++)
454 {
455 QListWidgetItem * item = list->item(row);
456 if (item)
457 {
458 item->setCheckState(Qt::Unchecked);
459 }
460 }
461}
462
463void MpcImportWindow::updateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal)
464{
465 if (downloadProgressBar == NULL)
466 return;
467
468 int currentValue = 0;
469 int endValue = 0;
470
471 if (bytesTotal > -1 && bytesReceived <= bytesTotal)
472 {
473 //Round to the greatest possible derived unit
474 while (bytesTotal > 1024)
475 {
476 bytesReceived = std::floor(bytesReceived / 1024);
477 bytesTotal = std::floor(bytesTotal / 1024);
478 }
479 currentValue = bytesReceived;
480 endValue = bytesTotal;
481 }
482
483 downloadProgressBar->setValue(currentValue);
484 downloadProgressBar->setMaximum(endValue);
485}
486
487void MpcImportWindow::updateQueryProgress(qint64, qint64)
488{
489 if (queryProgressBar == NULL)
490 return;
491
492 //Just show activity
493 queryProgressBar->setValue(0);
494 queryProgressBar->setMaximum(0);
495}
496
497void MpcImportWindow::startDownload(QString urlString)
498{
499 if (downloadReply)
500 {
501 //There's already an operation in progress?
502 //TODO
503 return;
504 }
505
506 QUrl url(urlString);
507 if (!url.isValid() || url.isRelative() || url.scheme() != "http")
508 {
509 qWarning() << "Invalid URL:" << urlString;
510 return;
511 }
512 //qDebug() << url.toString();
513
514 //TODO: Interface changes!
515
516 downloadProgressBar = StelApp::getInstance().getGui()->addProgressBar();
517 downloadProgressBar->setValue(0);
518 downloadProgressBar->setMaximum(0);
519 //downloadProgressBar->setFormat("%v/%m");
520 downloadProgressBar->setVisible(true);
521
522 //TODO: Better handling of the interface
523 //dialog->setVisible(false);
524 enableInterface(false);
525 ui->pushButtonAbortDownload->setVisible(true);
526
527 connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadComplete(QNetworkReply*)));
528 downloadReply = networkManager->get(QNetworkRequest(url));
529 connect(downloadReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDownloadProgress(qint64,qint64)));
530}
531
532void MpcImportWindow::abortDownload()
533{
534 if (downloadReply == NULL || downloadReply->isFinished())
535 return;
536
537 qDebug() << "Aborting download...";
538
539 disconnect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadComplete(QNetworkReply*)));
540 deleteDownloadProgressBar();
541
542 downloadReply->abort();
543 downloadReply->deleteLater();
544 downloadReply = NULL;
545
546 enableInterface(true);
547 ui->pushButtonAbortDownload->setVisible(false);
548}
549
550void MpcImportWindow::downloadComplete(QNetworkReply *reply)
551{
552 disconnect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadComplete(QNetworkReply*)));
553 deleteDownloadProgressBar();
554 ui->pushButtonAbortDownload->setVisible(false);
555
556 /*
557 qDebug() << "reply->isOpen():" << reply->isOpen()
558 << "reply->isReadable():" << reply->isReadable()
559 << "reply->isFinished():" << reply->isFinished();
560 */
561
562 if(reply->error())
563 {
564 qWarning() << "Download error: While downloading"
565 << reply->url().toString()
566 << "the following error occured:"
567 << reply->errorString();
568 enableInterface(true);
569 reply->deleteLater();
570 downloadReply = NULL;
571 return;
572 }
573
574 QList<SsoElements> objects;
575 QTemporaryFile file;
576 if (file.open())
577 {
578 file.write(reply->readAll());
579 file.close();
580 objects = readElementsFromFile(importType, file.fileName());
581 }
582 else
583 {
584 qWarning() << "Unable to open a temporary file. Aborting operation.";
585 }
586
587 if (objects.isEmpty())
588 {
589 qWarning() << "No objects found in the file downloaded from"
590 << reply->url().toString();
591 }
592 else
593 {
594 //The request has been successful: add the URL to bookmarks?
595 if (ui->checkBoxAddBookmark->isChecked())
596 {
597 QString url = reply->url().toString();
598 QString title = ui->lineEditBookmarkTitle->text().trimmed();
599 //If no title has been entered, use the URL as a title
600 if (title.isEmpty())
601 title = url;
602 if (!bookmarks.value(importType).values().contains(url))
603 {
604 bookmarks[importType].insert(title, url);
605 populateBookmarksList();
606 saveBookmarks();
607 }
608 }
609 }
610
611 reply->deleteLater();
612 downloadReply = NULL;
613
614 //Temporary, until the slot/socket mechanism is ready
615 populateCandidateObjects(objects);
616 ui->stackedWidget->setCurrentIndex(1);
617 //As this window is persistent, if the Solar System is changed
618 //while there is a list, it should be reset.
619 connect(ssoManager, SIGNAL(solarSystemChanged()), this, SLOT(resetDialog()));
620}
621
622void MpcImportWindow::deleteDownloadProgressBar()
623{
624 disconnect(this, SLOT(updateDownloadProgress(qint64,qint64)));
625
626 if (downloadProgressBar)
627 {
628 downloadProgressBar->setVisible(false);
629 downloadProgressBar->deleteLater();
630 downloadProgressBar = NULL;
631 }
632}
633
634void MpcImportWindow::sendQuery()
635{
636 if (queryReply != NULL)
637 return;
638
639 QString query = ui->lineEditQuery->text().trimmed();
640 if (query.isEmpty())
641 return;
642
643 //Progress bar
644 queryProgressBar = StelApp::getInstance().getGui()->addProgressBar();
645 queryProgressBar->setValue(0);
646 queryProgressBar->setMaximum(0);
647 queryProgressBar->setFormat("Searching...");
648 queryProgressBar->setVisible(true);
649
650 //TODO: Better handling of the interface
651 enableInterface(false);
652 ui->labelQueryMessage->setVisible(false);
653
654 QUrl url;
655 url.addQueryItem("ty","e");//Type: ephemerides
656 url.addQueryItem("TextArea", query);//Object name query
657 //url.addQueryItem("e", "-1");//Elements format: MPC 1-line
658 url.addQueryItem("e", "3");//Elements format: XEphem
659 //Yes, all of the rest are necessary
660 url.addQueryItem("d","");
661 url.addQueryItem("l","");
662 url.addQueryItem("i","");
663 url.addQueryItem("u","d");
664 url.addQueryItem("uto", "0");
665 url.addQueryItem("c", "");
666 url.addQueryItem("long", "");
667 url.addQueryItem("lat", "");
668 url.addQueryItem("alt", "");
669 url.addQueryItem("raty", "a");
670 url.addQueryItem("s", "t");
671 url.addQueryItem("m", "m");
672 url.addQueryItem("adir", "S");
673 url.addQueryItem("oed", "");
674 url.addQueryItem("resoc", "");
675 url.addQueryItem("tit", "");
676 url.addQueryItem("bu", "");
677 url.addQueryItem("ch", "c");
678 url.addQueryItem("ce", "f");
679 url.addQueryItem("js", "f");
680
681 QNetworkRequest request(QUrl("http://scully.cfa.harvard.edu/~cgi/MPEph2"));
682 request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");//Is this really necessary?
683 request.setHeader(QNetworkRequest::ContentLengthHeader, url.encodedQuery().length());
684
685 startCountdown();
686 ui->pushButtonAbortQuery->setVisible(true);
687 connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(queryComplete(QNetworkReply*)));
688 queryReply = networkManager->post(request, url.encodedQuery());
689 connect(queryReply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateQueryProgress(qint64,qint64)));
690}
691
692void MpcImportWindow::abortQuery()
693{
694 if (queryReply == NULL)
695 return;
696
697 disconnect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(queryComplete(QNetworkReply*)));
698 deleteQueryProgressBar();
699
700 queryReply->abort();
701 queryReply->deleteLater();
702 queryReply = NULL;
703
704 //resetCountdown();
705 enableInterface(true);
706 ui->pushButtonAbortQuery->setVisible(false);
707}
708
709void MpcImportWindow::queryComplete(QNetworkReply *reply)
710{
711 disconnect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(queryComplete(QNetworkReply*)));
712 deleteQueryProgressBar();
713
714 //Hide the abort button - a reply has been received
715 ui->pushButtonAbortQuery->setVisible(false);
716
717 if (reply->error())
718 {
719 qWarning() << "Download error: While trying to access"
720 << reply->url().toString()
721 << "the following error occured:"
722 << reply->errorString();
723 ui->labelQueryMessage->setText(reply->errorString());//TODO: Decide if this is a good idea
724 ui->labelQueryMessage->setVisible(true);
725 enableInterface(true);
726
727 reply->deleteLater();
728 queryReply = NULL;
729 return;
730 }
731
732 if (reply->header(QNetworkRequest::ContentTypeHeader) != "text/ascii" ||
733 reply->rawHeader(QByteArray("Content-disposition")) != "attachment; filename=elements.txt")
734 {
735 ui->labelQueryMessage->setText("Object not found.");
736 ui->labelQueryMessage->setVisible(true);
737 enableInterface(true);
738 }
739 else
740 {
741 QList<SsoElements> objects;
742 QTemporaryFile file;
743 if (file.open())
744 {
745 file.write(reply->readAll());
746 file.close();
747
748 /*
749 //Try to read it as a comet first?
750 objects = readElementsFromFile(MpcComets, file.fileName());
751 if (objects.isEmpty())
752 objects = readElementsFromFile(MpcMinorPlanets, file.fileName());
753 */
754 objects = ssoManager->readXEphemOneLineElementsFromFile(file.fileName());
755 }
756 else
757 {
758 qWarning() << "Unable to open a temporary file. Aborting operation.";
759 }
760
761 if (objects.isEmpty())
762 {
763 qWarning() << "No objects found in the file downloaded from"
764 << reply->url().toString();
765 }
766 else
767 {
768 //The request has been successful: add the URL to bookmarks?
769 if (ui->checkBoxAddBookmark->isChecked())
770 {
771 QString url = reply->url().toString();
772 if (!bookmarks.value(importType).values().contains(url))
773 {
774 //Use the URL as a title for now
775 bookmarks[importType].insert(url, url);
776 }
777 }
778
779 //Temporary, until the slot/socket mechanism is ready
780 populateCandidateObjects(objects);
781 ui->stackedWidget->setCurrentIndex(1);
782 }
783 }
784
785 reply->deleteLater();
786 queryReply = NULL;
787}
788
789void MpcImportWindow::deleteQueryProgressBar()
790{
791 disconnect(this, SLOT(updateQueryProgress(qint64,qint64)));
792 if (queryProgressBar)
793 {
794 queryProgressBar->setVisible(false);
795 queryProgressBar->deleteLater();
796 queryProgressBar = NULL;
797 }
798}
799
800void MpcImportWindow::startCountdown()
801{
802 if (!countdownTimer->isActive())
803 countdownTimer->start(1000);//1 second
804
805 //Disable the interface
806 ui->lineEditQuery->setEnabled(false);
807 ui->pushButtonSendQuery->setEnabled(false);
808}
809
810void MpcImportWindow::resetCountdown()
811{
812 //Stop the timer
813 if (countdownTimer->isActive())
814 {
815 countdownTimer->stop();
816
817 //If the query is still active, kill it
818 if (queryReply != NULL && queryReply->isRunning())
819 {
820 abortQuery();
821 ui->labelQueryMessage->setText("The query timed out. You can try again, now or later.");
822 ui->labelQueryMessage->setVisible(true);
823 }
824 }
825
826 //Reset the counter
827 countdown = 60;
828
829 //Enable the interface
830 ui->lineEditQuery->setEnabled(true);
831 ui->pushButtonSendQuery->setEnabled(true);
832}
833
834void MpcImportWindow::updateCountdown()
835{
836 --countdown;
837 if (countdown < 0)
838 {
839 resetCountdown();
840 }
841 //If there has been an answer
842 else if (countdown > 50 && queryReply == NULL)
843 {
844 resetCountdown();
845 }
846}
847
848void MpcImportWindow::resetNotFound()
849{
850 ui->labelQueryMessage->setVisible(false);
851}
852
853void MpcImportWindow::loadBookmarks()
854{
855 bookmarks[MpcComets].clear();
856 bookmarks[MpcMinorPlanets].clear();
857
858 QString bookmarksFilePath(StelFileMgr::getUserDir() + "/modules/SolarSystemEditor/bookmarks.json");
859 if (StelFileMgr::isReadable(bookmarksFilePath))
860 {
861 QFile bookmarksFile(bookmarksFilePath);
862 if (bookmarksFile.open(QFile::ReadOnly | QFile::Text))
863 {
864 QVariantMap jsonRoot = StelJsonParser::parse(bookmarksFile.readAll()).toMap();
865
866 loadBookmarksGroup(jsonRoot.value("mpcMinorPlanets").toMap(), bookmarks[MpcMinorPlanets]);
867 loadBookmarksGroup(jsonRoot.value("mpcComets").toMap(), bookmarks[MpcComets]);
868
869 bookmarksFile.close();
870
871 //If nothing was read, continue
872 if (!bookmarks.value(MpcComets).isEmpty() && !bookmarks[MpcMinorPlanets].isEmpty())
873 return;
874 }
875 }
876
877 qDebug() << "Bookmarks file can't be read. Hard-coded bookmarks will be used.";
878
879 //Initialize with hard-coded values
880 bookmarks[MpcMinorPlanets].insert("MPC's list of bright minor planets at opposition", "http://www.minorplanetcenter.org/iau/Ephemerides/Bright/2010/Soft00Bright.txt");
881 bookmarks[MpcMinorPlanets].insert("MPCORB: near-Earth asteroids (NEAs)", "http://www.minorplanetcenter.org/iau/MPCORB/NEA.txt");
882 bookmarks[MpcMinorPlanets].insert("MPCORB: potentially hazardous asteroids (PHAs)", "http://www.minorplanetcenter.org/iau/MPCORB/PHA.txt");
883 bookmarks[MpcComets].insert("MPC's list of observable comets", "http://www.minorplanetcenter.org/iau/Ephemerides/Comets/Soft00Cmt.txt");
884
885 //Try to save them to a file
886 saveBookmarks();
887}
888
889void MpcImportWindow::loadBookmarksGroup(QVariantMap source, Bookmarks & bookmarkGroup)
890{
891 if (source.isEmpty())
892 return;
893
894 foreach (QString title, source.keys())
895 {
896 QString url = source.value(title).toString();
897 if (!url.isEmpty())
898 bookmarkGroup.insert(title, url);
899 }
900}
901
902void MpcImportWindow::saveBookmarks()
903{
904 try
905 {
906 StelFileMgr::makeSureDirExistsAndIsWritable(StelFileMgr::getUserDir() + "/modules/SolarSystemEditor");
907
908 QVariantMap jsonRoot;
909
910 QString bookmarksFilePath(StelFileMgr::getUserDir() + "/modules/SolarSystemEditor/bookmarks.json");
911
912 //If the file exists, load it first
913 if (StelFileMgr::isReadable(bookmarksFilePath))
914 {
915 QFile bookmarksFile(bookmarksFilePath);
916 if (bookmarksFile.open(QFile::ReadOnly | QFile::Text))
917 {
918 jsonRoot = StelJsonParser::parse(bookmarksFile.readAll()).toMap();
919 bookmarksFile.close();
920 }
921 }
922
923 QFile bookmarksFile(bookmarksFilePath);
924 if (bookmarksFile.open(QFile::WriteOnly | QFile::Truncate | QFile::Text))
925 {
926 QVariantMap minorPlanetsObject;
927 saveBookmarksGroup(bookmarks[MpcMinorPlanets], minorPlanetsObject);
928 //qDebug() << minorPlanetsObject.keys();
929 jsonRoot.insert("mpcMinorPlanets", minorPlanetsObject);
930
931 QVariantMap cometsObject;
932 saveBookmarksGroup(bookmarks[MpcComets], cometsObject);
933 jsonRoot.insert("mpcComets", cometsObject);
934
935 StelJsonParser::write(jsonRoot, &bookmarksFile);
936 bookmarksFile.close();
937
938 qDebug() << "Bookmarks file saved to" << bookmarksFilePath;
939 return;
940 }
941 else
942 {
943 qDebug() << "Unable to write bookmarks file to" << bookmarksFilePath;
944 }
945 }
946 catch (std::exception & e)
947 {
948 qDebug() << "Unable to save bookmarks file:" << e.what();
949 }
950}
951
952void MpcImportWindow::saveBookmarksGroup(Bookmarks & bookmarkGroup, QVariantMap & output)
953{
954 foreach (QString title, bookmarkGroup.keys())
955 {
956 output.insert(title, bookmarkGroup.value(title));
957 }
958}
0959
=== added file 'plugins/SolarSystemEditor/src/gui/MpcImportWindow.hpp'
--- plugins/SolarSystemEditor/src/gui/MpcImportWindow.hpp 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/MpcImportWindow.hpp 2010-11-16 20:06:17 +0000
@@ -0,0 +1,135 @@
1/*
2 * Solar System editor plug-in for Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifndef _MPC_IMPORT_WINDOW_
22#define _MPC_IMPORT_WINDOW_
23
24#include <QObject>
25#include "StelDialog.hpp"
26
27#include "SolarSystemEditor.hpp"
28
29class Ui_mpcImportWindow;
30class QNetworkAccessManager;
31class QNetworkReply;
32class QProgressBar;
33
34/*! \brief Window for importing orbital elements from various sources.
35 \author Bogdan Marinov
36*/
37class MpcImportWindow : public StelDialog
38{
39 Q_OBJECT
40public:
41 enum ImportType {
42 MpcComets,
43 MpcMinorPlanets
44 };
45
46 MpcImportWindow();
47 virtual ~MpcImportWindow();
48 void languageChanged();
49
50signals:
51 void objectsImported();
52
53private slots:
54 //Radio buttons for type
55 void switchImportType(bool checked);
56
57 //File
58 void selectFile();
59
60 //Download
61 void pasteClipboardURL();
62 void bookmarkSelected(QString);
63
64 //Buttons for the list tab
65 void acquireObjectData();
66 void abortDownload();
67
68 //Online search
69 void sendQuery();
70 void abortQuery();
71 void updateCountdown();
72 void resetNotFound();
73
74 //Network
75 void updateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal);
76 void updateQueryProgress(qint64 bytesReceived, qint64 bytesTotal);
77 void downloadComplete(QNetworkReply * reply);
78 void queryComplete(QNetworkReply * reply);
79
80 //! Marks (checks) all items in the results lists
81 void markAll();
82 //! Unmarks (unchecks) all items in the results lists
83 void unmarkAll();
84 void addObjects();
85 void discardObjects();
86
87 //! resets the dialog to the state it should be in immediately after createDialogContent();.
88 void resetDialog();
89
90private:
91 SolarSystemEditor * ssoManager;
92 QList<SsoElements> candidatesForAddition;
93 QList<SsoElements> candidatesForUpdate;
94
95 ImportType importType;
96
97 //! wrapper for the single object function to allow multiple formats.
98 SsoElements readElementsFromString(QString elements);
99 //! wrapper for the file function to allow multiple formats
100 QList<SsoElements> readElementsFromFile(ImportType type, QString filePath);
101
102 void populateBookmarksList();
103 //void populateCandidateObjects();
104 void populateCandidateObjects(QList<SsoElements>);
105 void enableInterface(bool enable);
106
107 //Downloading
108 QNetworkAccessManager * networkManager;
109 QNetworkReply * downloadReply;
110 QNetworkReply * queryReply;
111 QProgressBar * downloadProgressBar;
112 QProgressBar * queryProgressBar;
113 void startDownload(QString url);
114 void deleteDownloadProgressBar();
115 void deleteQueryProgressBar();
116
117 typedef QHash<QString,QString> Bookmarks;
118 QHash<ImportType, Bookmarks> bookmarks;
119 void loadBookmarks();
120 void loadBookmarksGroup(QVariantMap source, Bookmarks & bookmarkGroup);
121 void saveBookmarks();
122 void saveBookmarksGroup(Bookmarks & bookmarkGroup, QVariantMap & output);
123
124 //Online search
125 int countdown;
126 QTimer * countdownTimer;
127 void startCountdown();
128 void resetCountdown();
129
130protected:
131 virtual void createDialogContent();
132 Ui_mpcImportWindow * ui;
133};
134
135#endif //_MPC_IMPORT_WINDOW_
0136
=== added file 'plugins/SolarSystemEditor/src/gui/SolarSystemManagerWindow.cpp'
--- plugins/SolarSystemEditor/src/gui/SolarSystemManagerWindow.cpp 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/SolarSystemManagerWindow.cpp 2010-11-16 20:06:17 +0000
@@ -0,0 +1,170 @@
1/*
2 * Solar System editor plug-in for Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#include "SolarSystemEditor.hpp"
22
23#include "SolarSystemManagerWindow.hpp"
24#include "ui_solarSystemManagerWindow.h"
25
26#include "MpcImportWindow.hpp"
27#include "ManualImportWindow.hpp"
28
29#include "StelApp.hpp"
30#include "StelFileMgr.hpp"
31#include "StelModuleMgr.hpp"
32#include "Planet.hpp"
33#include "SolarSystem.hpp"
34
35#include <QFileDialog>
36
37SolarSystemManagerWindow::SolarSystemManagerWindow()
38{
39 ui = new Ui_solarSystemManagerWindow();
40 mpcImportWindow = new MpcImportWindow();
41 manualImportWindow = NULL;
42
43 ssoManager = GETSTELMODULE(SolarSystemEditor);
44}
45
46SolarSystemManagerWindow::~SolarSystemManagerWindow()
47{
48 delete ui;
49
50 if (mpcImportWindow)
51 delete mpcImportWindow;
52 if (manualImportWindow)
53 delete manualImportWindow;
54}
55
56void SolarSystemManagerWindow::createDialogContent()
57{
58 ui->setupUi(dialog);
59
60 //Signals
61 connect(ui->closeStelWindow, SIGNAL(clicked()), this, SLOT(close()));
62 connect(ui->pushButtonCopyFile, SIGNAL(clicked()), this, SLOT(copyConfiguration()));
63 connect(ui->pushButtonReplaceFile, SIGNAL(clicked()), this, SLOT(replaceConfiguration()));
64 connect(ui->pushButtonRemove, SIGNAL(clicked()), this, SLOT(removeObject()));
65 connect(ui->pushButtonImportMPC, SIGNAL(clicked()), this, SLOT(newImportMPC()));
66 connect(ui->pushButtonManual, SIGNAL(clicked()), this, SLOT(newImportManual()));
67
68 connect(ssoManager, SIGNAL(solarSystemChanged()), this, SLOT(populateSolarSystemList()));
69 connect(ui->pushButtonReset, SIGNAL(clicked()), ssoManager, SLOT(resetSolarSystemToDefault()));
70
71 ui->labelVersion->setText(QString("Version %1").arg(PLUGIN_VERSION));
72 //Remove the "Data Import" tab
73 //TODO: (temporary, until the ManualImportWindow is finished)
74 ui->tabWidget->removeTab(2);
75
76 Q_ASSERT(mpcImportWindow);
77 //Rebuild the list if any planets have been imported
78 connect(mpcImportWindow, SIGNAL(objectsImported()), this, SLOT(populateSolarSystemList()));
79
80 ui->lineEditUserFilePath->setText(ssoManager->getCustomSolarSystemFilePath());
81 populateSolarSystemList();
82}
83
84void SolarSystemManagerWindow::languageChanged()
85{
86 if (dialog)
87 {
88 ui->retranslateUi(dialog);
89 populateSolarSystemList();
90 ui->labelVersion->setText(QString("Version %1").arg(PLUGIN_VERSION));
91 }
92
93 if (mpcImportWindow)
94 mpcImportWindow->languageChanged();
95}
96
97void SolarSystemManagerWindow::newImportMPC()
98{
99 Q_ASSERT(mpcImportWindow);
100
101 mpcImportWindow->setVisible(true);
102}
103
104void SolarSystemManagerWindow::newImportManual()
105{
106 if (manualImportWindow == NULL)
107 {
108 manualImportWindow = new ManualImportWindow();
109 connect(manualImportWindow, SIGNAL(visibleChanged(bool)), this, SLOT(resetImportManual(bool)));
110 }
111
112 manualImportWindow->setVisible(true);
113}
114
115void SolarSystemManagerWindow::resetImportManual(bool show)
116{
117 //If the window is being displayed, do nothing
118 if (show)
119 return;
120
121 if (manualImportWindow)
122 {
123 //TODO:Move this out of here!
124 //Reload the list, in case there are new objects
125 populateSolarSystemList();
126
127 delete manualImportWindow;
128 manualImportWindow = NULL;
129
130 //This window is in the background, bring it to the foreground
131 dialog->setVisible(true);
132 }
133}
134
135void SolarSystemManagerWindow::populateSolarSystemList()
136{
137 unlocalizedNames.clear();
138 foreach (const PlanetP & object, GETSTELMODULE(SolarSystem)->getAllPlanets())
139 {
140 unlocalizedNames.insert(object->getNameI18n(), object->getEnglishName());
141 }
142
143 ui->listWidgetObjects->clear();
144 ui->listWidgetObjects->addItems(unlocalizedNames.keys());
145 //No explicit sorting is necessary: sortingEnabled is set in the .ui
146}
147
148void SolarSystemManagerWindow::removeObject()
149{
150 if(ui->listWidgetObjects->currentItem())
151 {
152 QString ssoI18nName = ui->listWidgetObjects->currentItem()->text();
153 QString ssoEnglishName = unlocalizedNames.value(ssoI18nName);
154 //qDebug() << ssoId;
155 //TODO: Ask for confirmation first?
156 ssoManager->removeSsoWithName(ssoEnglishName);
157 }
158}
159
160void SolarSystemManagerWindow::copyConfiguration()
161{
162 QString filePath = QFileDialog::getSaveFileName(0, "Save the Solar System configuration file as...", StelFileMgr::getDesktopDir());
163 ssoManager->copySolarSystemConfigurationFileTo(filePath);
164}
165
166void SolarSystemManagerWindow::replaceConfiguration()
167{
168 QString filePath = QFileDialog::getOpenFileName(0, "Select a file to replace the Solar System configuration file", StelFileMgr::getDesktopDir(), QString("Configration files (*.ini)"));
169 ssoManager->replaceSolarSystemConfigurationFileWith(filePath);
170}
0171
=== added file 'plugins/SolarSystemEditor/src/gui/SolarSystemManagerWindow.hpp'
--- plugins/SolarSystemEditor/src/gui/SolarSystemManagerWindow.hpp 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/SolarSystemManagerWindow.hpp 2010-11-16 20:06:17 +0000
@@ -0,0 +1,73 @@
1/*
2 * Solar System editor plug-in for Stellarium
3 *
4 * Copyright (C) 2010 Bogdan Marinov
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21#ifndef _SOLAR_SYSTEM_MANAGER_WINDOW_
22#define _SOLAR_SYSTEM_MANAGER_WINDOW_
23
24#include <QObject>
25#include "StelDialog.hpp"
26
27#include <QHash>
28#include <QString>
29
30class SolarSystemEditor;
31
32class Ui_solarSystemManagerWindow;
33class MpcImportWindow;
34class ManualImportWindow;
35
36/*! \brief Main window for handling Solar System objects.
37 \author Bogdan Marinov
38*/
39class SolarSystemManagerWindow : public StelDialog
40{
41 Q_OBJECT
42public:
43 SolarSystemManagerWindow();
44 virtual ~SolarSystemManagerWindow();
45 void languageChanged();
46
47protected:
48 virtual void createDialogContent();
49 Ui_solarSystemManagerWindow * ui;
50
51private slots:
52 //! \todo Find a way to suggest a default file name (select directory instead of file?)
53 void copyConfiguration();
54 void replaceConfiguration();
55
56 void populateSolarSystemList();
57 void removeObject();
58
59 void newImportMPC();
60
61 void newImportManual();
62 void resetImportManual(bool);
63
64private:
65 MpcImportWindow* mpcImportWindow;
66 ManualImportWindow * manualImportWindow;
67
68 SolarSystemEditor * ssoManager;
69
70 QHash<QString,QString> unlocalizedNames;
71};
72
73#endif //_SOLAR_SYSTEM_MANAGER_WINDOW_
074
=== added file 'plugins/SolarSystemEditor/src/gui/manualImportWindow.ui'
--- plugins/SolarSystemEditor/src/gui/manualImportWindow.ui 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/manualImportWindow.ui 2010-11-16 20:06:17 +0000
@@ -0,0 +1,890 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>manualImportWindow</class>
4 <widget class="QWidget" name="manualImportWindow">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>600</width>
10 <height>500</height>
11 </rect>
12 </property>
13 <layout class="QGridLayout" name="gridLayoutWindow">
14 <property name="margin">
15 <number>0</number>
16 </property>
17 <property name="spacing">
18 <number>0</number>
19 </property>
20 <item row="0" column="0" colspan="2">
21 <widget class="BarFrame" name="LocationBar">
22 <property name="sizePolicy">
23 <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
24 <horstretch>0</horstretch>
25 <verstretch>0</verstretch>
26 </sizepolicy>
27 </property>
28 <property name="minimumSize">
29 <size>
30 <width>0</width>
31 <height>25</height>
32 </size>
33 </property>
34 <property name="maximumSize">
35 <size>
36 <width>16777215</width>
37 <height>30</height>
38 </size>
39 </property>
40 <property name="focusPolicy">
41 <enum>Qt::NoFocus</enum>
42 </property>
43 <property name="autoFillBackground">
44 <bool>false</bool>
45 </property>
46 <property name="frameShape">
47 <enum>QFrame::StyledPanel</enum>
48 </property>
49 <layout class="QHBoxLayout" name="_2">
50 <property name="spacing">
51 <number>6</number>
52 </property>
53 <property name="leftMargin">
54 <number>0</number>
55 </property>
56 <property name="topMargin">
57 <number>0</number>
58 </property>
59 <property name="rightMargin">
60 <number>4</number>
61 </property>
62 <property name="bottomMargin">
63 <number>0</number>
64 </property>
65 <item>
66 <spacer name="leftSpacer">
67 <property name="orientation">
68 <enum>Qt::Horizontal</enum>
69 </property>
70 <property name="sizeHint" stdset="0">
71 <size>
72 <width>40</width>
73 <height>20</height>
74 </size>
75 </property>
76 </spacer>
77 </item>
78 <item>
79 <widget class="QLabel" name="stelWindowTitle">
80 <property name="text">
81 <string notr="true" extracomment="The title of the window will be set during runtime">Define an object</string>
82 </property>
83 </widget>
84 </item>
85 <item>
86 <spacer name="rightSpacer">
87 <property name="orientation">
88 <enum>Qt::Horizontal</enum>
89 </property>
90 <property name="sizeHint" stdset="0">
91 <size>
92 <width>40</width>
93 <height>20</height>
94 </size>
95 </property>
96 </spacer>
97 </item>
98 <item>
99 <widget class="QPushButton" name="closeStelWindow">
100 <property name="minimumSize">
101 <size>
102 <width>16</width>
103 <height>16</height>
104 </size>
105 </property>
106 <property name="maximumSize">
107 <size>
108 <width>16</width>
109 <height>16</height>
110 </size>
111 </property>
112 <property name="focusPolicy">
113 <enum>Qt::NoFocus</enum>
114 </property>
115 <property name="text">
116 <string/>
117 </property>
118 </widget>
119 </item>
120 </layout>
121 </widget>
122 </item>
123 <item row="1" column="1">
124 <widget class="QGroupBox" name="groupBoxObjectType">
125 <property name="title">
126 <string>Object type</string>
127 </property>
128 <property name="alignment">
129 <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
130 </property>
131 <layout class="QVBoxLayout" name="verticalLayoutObjectType">
132 <property name="margin">
133 <number>0</number>
134 </property>
135 <item>
136 <widget class="QRadioButton" name="radioButtonSolarSystemObject">
137 <property name="text">
138 <string>Solar System object</string>
139 </property>
140 </widget>
141 </item>
142 <item>
143 <widget class="QRadioButton" name="radioButtonMinorPlanet">
144 <property name="text">
145 <string>Minor planet (asteroid)</string>
146 </property>
147 </widget>
148 </item>
149 <item>
150 <widget class="QRadioButton" name="radioButtonComet">
151 <property name="text">
152 <string>Comet</string>
153 </property>
154 </widget>
155 </item>
156 <item>
157 <widget class="QRadioButton" name="radioButtonSatellite">
158 <property name="text">
159 <string>Satellite</string>
160 </property>
161 </widget>
162 </item>
163 </layout>
164 </widget>
165 </item>
166 <item row="1" column="0">
167 <widget class="QGroupBox" name="groupBoxName">
168 <property name="title">
169 <string>Name</string>
170 </property>
171 <property name="alignment">
172 <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
173 </property>
174 <layout class="QGridLayout" name="gridLayoutName">
175 <property name="margin">
176 <number>0</number>
177 </property>
178 <item row="0" column="0">
179 <widget class="QLabel" name="labelName">
180 <property name="text">
181 <string>Name</string>
182 </property>
183 </widget>
184 </item>
185 <item row="0" column="1">
186 <widget class="QLineEdit" name="lineEditName"/>
187 </item>
188 <item row="1" column="0">
189 <widget class="QLabel" name="labelIdentifier">
190 <property name="text">
191 <string>Identifier</string>
192 </property>
193 </widget>
194 </item>
195 <item row="1" column="1">
196 <widget class="QLineEdit" name="lineEditIdentifier"/>
197 </item>
198 <item row="2" column="0">
199 <widget class="QCheckBox" name="checkBoxMinorPlanetNumber">
200 <property name="text">
201 <string>Minor planet number</string>
202 </property>
203 </widget>
204 </item>
205 <item row="2" column="1">
206 <widget class="QLineEdit" name="lineEditMinorPlanetNumber"/>
207 </item>
208 </layout>
209 </widget>
210 </item>
211 <item row="2" column="0" colspan="2">
212 <widget class="QScrollArea" name="scrollArea">
213 <property name="widgetResizable">
214 <bool>true</bool>
215 </property>
216 <property name="alignment">
217 <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
218 </property>
219 <widget class="QWidget" name="scrollAreaWidgetContents">
220 <property name="geometry">
221 <rect>
222 <x>0</x>
223 <y>0</y>
224 <width>582</width>
225 <height>1436</height>
226 </rect>
227 </property>
228 <layout class="QVBoxLayout" name="verticalLayoutScroll">
229 <property name="margin">
230 <number>0</number>
231 </property>
232 <item>
233 <widget class="QGroupBox" name="groupBoxProperties">
234 <property name="title">
235 <string>Properties</string>
236 </property>
237 <layout class="QGridLayout" name="gridLayout_4">
238 <item row="0" column="0">
239 <widget class="QLabel" name="labelParent">
240 <property name="text">
241 <string>Parent:</string>
242 </property>
243 </widget>
244 </item>
245 <item row="0" column="2" colspan="2">
246 <widget class="QComboBox" name="comboBoxParent"/>
247 </item>
248 <item row="1" column="0">
249 <widget class="QLabel" name="labelRadius">
250 <property name="text">
251 <string>Radius:</string>
252 </property>
253 </widget>
254 </item>
255 <item row="1" column="2" colspan="2">
256 <widget class="QLineEdit" name="lineEditRadius"/>
257 </item>
258 <item row="2" column="0">
259 <widget class="QLabel" name="labelOblateness">
260 <property name="text">
261 <string>Oblateness:</string>
262 </property>
263 </widget>
264 </item>
265 <item row="2" column="2" colspan="2">
266 <widget class="QLineEdit" name="lineEditOblateness"/>
267 </item>
268 <item row="3" column="0">
269 <widget class="QLabel" name="labelAlbedo">
270 <property name="text">
271 <string>Albedo:</string>
272 </property>
273 </widget>
274 </item>
275 <item row="3" column="2" colspan="2">
276 <widget class="QLineEdit" name="lineEditAlbedo"/>
277 </item>
278 <item row="4" column="0">
279 <widget class="QLabel" name="labelColor">
280 <property name="text">
281 <string>Color:</string>
282 </property>
283 </widget>
284 </item>
285 <item row="4" column="3">
286 <widget class="QPushButton" name="pushButtonSelectColor"/>
287 </item>
288 <item row="5" column="0" colspan="4">
289 <widget class="QCheckBox" name="checkBoxLighting">
290 <property name="text">
291 <string>Lighting (TODO: More clear name)</string>
292 </property>
293 </widget>
294 </item>
295 <item row="6" column="0" colspan="4">
296 <widget class="QCheckBox" name="checkBoxAtmosphere">
297 <property name="text">
298 <string>Atmosphere</string>
299 </property>
300 </widget>
301 </item>
302 <item row="7" column="0" colspan="4">
303 <widget class="QCheckBox" name="checkBoxHidden">
304 <property name="text">
305 <string>Hidden</string>
306 </property>
307 </widget>
308 </item>
309 <item row="8" column="0">
310 <widget class="QLabel" name="labelTexture">
311 <property name="text">
312 <string>Texture:</string>
313 </property>
314 </widget>
315 </item>
316 <item row="8" column="2">
317 <widget class="QLineEdit" name="lineEditTexture">
318 <property name="readOnly">
319 <bool>true</bool>
320 </property>
321 </widget>
322 </item>
323 <item row="8" column="3">
324 <widget class="QPushButton" name="pushButtonSelectTexture">
325 <property name="text">
326 <string>...</string>
327 </property>
328 </widget>
329 </item>
330 <item row="9" column="0" colspan="4">
331 <widget class="QFrame" name="frameMagnitude">
332 <layout class="QGridLayout" name="gridLayoutMagnitude">
333 <property name="margin">
334 <number>0</number>
335 </property>
336 <item row="1" column="0">
337 <widget class="QLabel" name="labelAbsoluteMagnitude">
338 <property name="text">
339 <string>Absolute magnitude:</string>
340 </property>
341 </widget>
342 </item>
343 <item row="1" column="1">
344 <widget class="QLineEdit" name="lineEditAbsoluteMagnitude"/>
345 </item>
346 <item row="1" column="2">
347 <widget class="QLabel" name="labelSlopeParameter">
348 <property name="text">
349 <string>Slope parameter:</string>
350 </property>
351 </widget>
352 </item>
353 <item row="1" column="3">
354 <widget class="QLineEdit" name="lineEditSlopeParameter"/>
355 </item>
356 <item row="2" column="0" colspan="4">
357 <widget class="QPushButton" name="pushButtonCalculateRadius">
358 <property name="text">
359 <string>Calculate the object's radius from the absolute magnitude and the current albedo</string>
360 </property>
361 </widget>
362 </item>
363 <item row="0" column="0" colspan="4">
364 <widget class="QLabel" name="labelMagnitudeSystem">
365 <property name="text">
366 <string>H-G two parameter magnitude system for minor planets:</string>
367 </property>
368 </widget>
369 </item>
370 </layout>
371 </widget>
372 </item>
373 <item row="4" column="2">
374 <widget class="QLineEdit" name="lineEditColor"/>
375 </item>
376 </layout>
377 </widget>
378 </item>
379 <item>
380 <widget class="QGroupBox" name="groupBoxOrbitalElements">
381 <property name="title">
382 <string>Orbital elements</string>
383 </property>
384 <layout class="QGridLayout" name="gridLayoutOrbitalElements">
385 <property name="margin">
386 <number>0</number>
387 </property>
388 <item row="0" column="0" colspan="2">
389 <widget class="QLabel" name="labelOrbitType">
390 <property name="text">
391 <string>Orbital function type:</string>
392 </property>
393 </widget>
394 </item>
395 <item row="1" column="0" colspan="2">
396 <widget class="QRadioButton" name="radioButtonCometaryOrbit">
397 <property name="text">
398 <string>Cometary orbit</string>
399 </property>
400 </widget>
401 </item>
402 <item row="2" column="0" colspan="2">
403 <widget class="QRadioButton" name="radioButtonEllipticOrbit">
404 <property name="text">
405 <string>Elliptic orbit</string>
406 </property>
407 </widget>
408 </item>
409 <item row="4" column="0">
410 <widget class="QLabel" name="labelEccentricity">
411 <property name="text">
412 <string>Eccentricity (%1):</string>
413 </property>
414 </widget>
415 </item>
416 <item row="4" column="1">
417 <widget class="QLineEdit" name="lineEditEccentricity">
418 <property name="text">
419 <string>0</string>
420 </property>
421 </widget>
422 </item>
423 <item row="5" column="0">
424 <widget class="QLabel" name="labelInclination">
425 <property name="text">
426 <string>Inclination (degrees):</string>
427 </property>
428 </widget>
429 </item>
430 <item row="5" column="1">
431 <widget class="QLineEdit" name="lineEditInclination"/>
432 </item>
433 <item row="6" column="0">
434 <widget class="QLabel" name="labelLongitudeOfTheAscendingNode">
435 <property name="text">
436 <string>Longitude of the ascending node %1:</string>
437 </property>
438 </widget>
439 </item>
440 <item row="6" column="1">
441 <widget class="QLineEdit" name="lineEditLongitudeOfTheAscendingNode"/>
442 </item>
443 <item row="7" column="0" colspan="2">
444 <widget class="QFrame" name="framePeriapsis">
445 <layout class="QGridLayout" name="gridLayoutPeriapsis">
446 <property name="margin">
447 <number>0</number>
448 </property>
449 <item row="0" column="0">
450 <widget class="QRadioButton" name="radioButtonArgumentOfPeriapsis">
451 <property name="text">
452 <string>Argument of the periapsis %1:</string>
453 </property>
454 </widget>
455 </item>
456 <item row="0" column="1">
457 <widget class="QLineEdit" name="lineEditArgumentOfPeriapsis"/>
458 </item>
459 <item row="1" column="0">
460 <widget class="QRadioButton" name="radioButtonLongitudeOfPeriapsis">
461 <property name="text">
462 <string>Longitude of the periapsis %1:</string>
463 </property>
464 </widget>
465 </item>
466 <item row="1" column="1">
467 <widget class="QLineEdit" name="lineEditLongitudeOfPeriapsis"/>
468 </item>
469 </layout>
470 </widget>
471 </item>
472 <item row="8" column="0" colspan="2">
473 <widget class="QFrame" name="frameSemiMajorAxis">
474 <layout class="QGridLayout" name="gridLayoutSemiMajorAxis">
475 <property name="margin">
476 <number>0</number>
477 </property>
478 <item row="0" column="1">
479 <widget class="QLineEdit" name="lineEditSemiMajorAxis"/>
480 </item>
481 <item row="1" column="1">
482 <widget class="QLineEdit" name="lineEditPeriapsisDistance"/>
483 </item>
484 <item row="0" column="0">
485 <widget class="QRadioButton" name="radioButtonSemiMajorAxis">
486 <property name="text">
487 <string>Semi-major axis %1:</string>
488 </property>
489 </widget>
490 </item>
491 <item row="1" column="0">
492 <widget class="QRadioButton" name="radioButtonPeriapsisDistance">
493 <property name="text">
494 <string>Periapsis distance %1:</string>
495 </property>
496 </widget>
497 </item>
498 </layout>
499 </widget>
500 </item>
501 <item row="9" column="0" colspan="2">
502 <widget class="QFrame" name="framePeriod">
503 <layout class="QGridLayout" name="gridLayoutPeriod">
504 <property name="margin">
505 <number>0</number>
506 </property>
507 <item row="0" column="0">
508 <widget class="QCheckBox" name="checkBoxPeriod">
509 <property name="text">
510 <string>Period:</string>
511 </property>
512 </widget>
513 </item>
514 <item row="0" column="1">
515 <widget class="QLineEdit" name="lineEditPeriod"/>
516 </item>
517 <item row="1" column="0">
518 <widget class="QCheckBox" name="checkBoxMeanMotion">
519 <property name="text">
520 <string>Mean motion:</string>
521 </property>
522 </widget>
523 </item>
524 <item row="1" column="1">
525 <widget class="QLineEdit" name="lineEditMeanMotion"/>
526 </item>
527 </layout>
528 </widget>
529 </item>
530 <item row="10" column="0" colspan="2">
531 <widget class="QFrame" name="frameEpoch">
532 <layout class="QGridLayout" name="gridLayoutEpoch">
533 <property name="margin">
534 <number>0</number>
535 </property>
536 <item row="0" column="1">
537 <widget class="QLineEdit" name="lineEditEpoch"/>
538 </item>
539 <item row="1" column="1" colspan="2">
540 <widget class="QLineEdit" name="lineEditTimeOfPeriapsis"/>
541 </item>
542 <item row="0" column="0">
543 <widget class="QRadioButton" name="radioButtonEpoch">
544 <property name="text">
545 <string>Epoch:</string>
546 </property>
547 </widget>
548 </item>
549 <item row="1" column="0">
550 <widget class="QRadioButton" name="radioButtonTimeOfPeriapsis">
551 <property name="text">
552 <string>Time of periapsis passage:</string>
553 </property>
554 </widget>
555 </item>
556 <item row="0" column="2">
557 <widget class="QPushButton" name="pushButtonEpochJ2000">
558 <property name="text">
559 <string>J2000.0</string>
560 </property>
561 </widget>
562 </item>
563 </layout>
564 </widget>
565 </item>
566 <item row="11" column="0" colspan="2">
567 <widget class="QFrame" name="frameMeanAnomaly">
568 <layout class="QGridLayout" name="gridLayout_2">
569 <property name="margin">
570 <number>0</number>
571 </property>
572 <item row="1" column="1">
573 <widget class="QLineEdit" name="lineEditMeanAnomaly"/>
574 </item>
575 <item row="2" column="1">
576 <widget class="QLineEdit" name="lineEditMeanLongitude"/>
577 </item>
578 <item row="1" column="0">
579 <widget class="QRadioButton" name="radioButtonMeanAnomaly">
580 <property name="text">
581 <string>Mean anomaly:</string>
582 </property>
583 </widget>
584 </item>
585 <item row="2" column="0">
586 <widget class="QRadioButton" name="radioButtonMeanLongitude">
587 <property name="text">
588 <string>Mean longitude:</string>
589 </property>
590 </widget>
591 </item>
592 </layout>
593 </widget>
594 </item>
595 <item row="3" column="0">
596 <widget class="QRadioButton" name="radioButtonOrbitFunction">
597 <property name="text">
598 <string>Object-specific:</string>
599 </property>
600 </widget>
601 </item>
602 <item row="3" column="1">
603 <widget class="QComboBox" name="comboBoxOrbitFunction"/>
604 </item>
605 <item row="12" column="0">
606 <widget class="QCheckBox" name="checkBoxOrbitVisualizationPeriod">
607 <property name="text">
608 <string>Orbit visualization period:</string>
609 </property>
610 </widget>
611 </item>
612 <item row="12" column="1">
613 <widget class="QLineEdit" name="lineEditOrbitVisualizationPeriod"/>
614 </item>
615 </layout>
616 </widget>
617 </item>
618 <item>
619 <widget class="QGroupBox" name="groupBoxRotationalElements">
620 <property name="title">
621 <string>Rotational elements</string>
622 </property>
623 <layout class="QGridLayout" name="gridLayout">
624 <item row="0" column="0">
625 <widget class="QCheckBox" name="checkBoxObliquity">
626 <property name="text">
627 <string>Obliquity:</string>
628 </property>
629 </widget>
630 </item>
631 <item row="0" column="1" colspan="3">
632 <widget class="QLineEdit" name="lineEditObliquity"/>
633 </item>
634 <item row="2" column="0">
635 <widget class="QCheckBox" name="checkBoxNorthPoleRA">
636 <property name="text">
637 <string>North pole right ascension:</string>
638 </property>
639 </widget>
640 </item>
641 <item row="2" column="1" colspan="3">
642 <widget class="QLineEdit" name="lineEditNorthPoleRA"/>
643 </item>
644 <item row="3" column="0">
645 <widget class="QCheckBox" name="checkBoxNorthPoleDec">
646 <property name="text">
647 <string>North pole declination:</string>
648 </property>
649 </widget>
650 </item>
651 <item row="3" column="1" colspan="3">
652 <widget class="QLineEdit" name="lineEditNorthPoleDec"/>
653 </item>
654 <item row="4" column="0">
655 <widget class="QCheckBox" name="checkBoxRotationalPeriod">
656 <property name="text">
657 <string>Period (hours):</string>
658 </property>
659 </widget>
660 </item>
661 <item row="4" column="1" colspan="3">
662 <widget class="QLineEdit" name="lineEditRotationalPeriod"/>
663 </item>
664 <item row="5" column="0">
665 <widget class="QCheckBox" name="checkBoxPrecessionRate">
666 <property name="text">
667 <string>Precession rate:</string>
668 </property>
669 </widget>
670 </item>
671 <item row="5" column="1" colspan="3">
672 <widget class="QLineEdit" name="lineEditPrecessionRate"/>
673 </item>
674 <item row="6" column="0">
675 <widget class="QCheckBox" name="checkBoxRotationalEpoch">
676 <property name="text">
677 <string>Epoch:</string>
678 </property>
679 </widget>
680 </item>
681 <item row="6" column="1">
682 <widget class="QLineEdit" name="lineEditRotationalEpoch"/>
683 </item>
684 <item row="7" column="0">
685 <widget class="QCheckBox" name="checkBoxOffset">
686 <property name="text">
687 <string>Offset:</string>
688 </property>
689 </widget>
690 </item>
691 <item row="7" column="1" colspan="3">
692 <widget class="QLineEdit" name="lineEditOffset"/>
693 </item>
694 <item row="1" column="0" colspan="3">
695 <widget class="QCheckBox" name="checkBoxEquatorAscendingNode">
696 <property name="text">
697 <string>Longitude of the ascending node of the ecliptic on the equator:</string>
698 </property>
699 </widget>
700 </item>
701 <item row="6" column="3">
702 <widget class="QPushButton" name="pushButtonRotationalEpochJ2000">
703 <property name="text">
704 <string>J2000.0</string>
705 </property>
706 </widget>
707 </item>
708 <item row="1" column="3">
709 <widget class="QLineEdit" name="lineEditEquatorAscendingNode"/>
710 </item>
711 </layout>
712 </widget>
713 </item>
714 <item>
715 <widget class="QGroupBox" name="groupBoxRings">
716 <property name="title">
717 <string>Rings</string>
718 </property>
719 <property name="checkable">
720 <bool>true</bool>
721 </property>
722 <property name="checked">
723 <bool>false</bool>
724 </property>
725 <layout class="QGridLayout" name="gridLayout_3">
726 <item row="0" column="0">
727 <widget class="QLabel" name="labelInnerSize">
728 <property name="text">
729 <string>Inner size:</string>
730 </property>
731 </widget>
732 </item>
733 <item row="1" column="0">
734 <widget class="QLabel" name="labelOuterSize">
735 <property name="text">
736 <string>Outer size:</string>
737 </property>
738 </widget>
739 </item>
740 <item row="2" column="0">
741 <widget class="QLabel" name="labelRingTexture">
742 <property name="text">
743 <string>Texture:</string>
744 </property>
745 </widget>
746 </item>
747 <item row="2" column="1">
748 <widget class="QLineEdit" name="lineEditRingTexture">
749 <property name="readOnly">
750 <bool>true</bool>
751 </property>
752 </widget>
753 </item>
754 <item row="2" column="2">
755 <widget class="QPushButton" name="pushButtonSelectRingTexture">
756 <property name="text">
757 <string>...</string>
758 </property>
759 </widget>
760 </item>
761 <item row="0" column="1" colspan="2">
762 <widget class="QLineEdit" name="lineEditRingInnerSize"/>
763 </item>
764 <item row="1" column="1" colspan="2">
765 <widget class="QLineEdit" name="lineEditRingOuterSize"/>
766 </item>
767 </layout>
768 </widget>
769 </item>
770 </layout>
771 </widget>
772 </widget>
773 </item>
774 <item row="3" column="0" colspan="2">
775 <widget class="QFrame" name="frameButton">
776 <layout class="QHBoxLayout" name="horizontalLayoutButton">
777 <item>
778 <widget class="QLabel" name="labelErrorMessage">
779 <property name="sizePolicy">
780 <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
781 <horstretch>0</horstretch>
782 <verstretch>0</verstretch>
783 </sizepolicy>
784 </property>
785 <property name="text">
786 <string/>
787 </property>
788 </widget>
789 </item>
790 <item>
791 <widget class="QPushButton" name="pushButtonSave">
792 <property name="text">
793 <string>Save</string>
794 </property>
795 </widget>
796 </item>
797 </layout>
798 </widget>
799 </item>
800 </layout>
801 </widget>
802 <customwidgets>
803 <customwidget>
804 <class>BarFrame</class>
805 <extends>QFrame</extends>
806 <header>Dialog.hpp</header>
807 <container>1</container>
808 </customwidget>
809 </customwidgets>
810 <tabstops>
811 <tabstop>lineEditName</tabstop>
812 <tabstop>lineEditIdentifier</tabstop>
813 <tabstop>checkBoxMinorPlanetNumber</tabstop>
814 <tabstop>lineEditMinorPlanetNumber</tabstop>
815 <tabstop>radioButtonSolarSystemObject</tabstop>
816 <tabstop>radioButtonMinorPlanet</tabstop>
817 <tabstop>radioButtonComet</tabstop>
818 <tabstop>radioButtonSatellite</tabstop>
819 <tabstop>scrollArea</tabstop>
820 <tabstop>comboBoxParent</tabstop>
821 <tabstop>lineEditRadius</tabstop>
822 <tabstop>lineEditOblateness</tabstop>
823 <tabstop>lineEditAlbedo</tabstop>
824 <tabstop>lineEditColor</tabstop>
825 <tabstop>pushButtonSelectColor</tabstop>
826 <tabstop>checkBoxLighting</tabstop>
827 <tabstop>checkBoxAtmosphere</tabstop>
828 <tabstop>checkBoxHidden</tabstop>
829 <tabstop>lineEditTexture</tabstop>
830 <tabstop>pushButtonSelectTexture</tabstop>
831 <tabstop>lineEditAbsoluteMagnitude</tabstop>
832 <tabstop>lineEditSlopeParameter</tabstop>
833 <tabstop>pushButtonCalculateRadius</tabstop>
834 <tabstop>radioButtonCometaryOrbit</tabstop>
835 <tabstop>radioButtonEllipticOrbit</tabstop>
836 <tabstop>radioButtonOrbitFunction</tabstop>
837 <tabstop>comboBoxOrbitFunction</tabstop>
838 <tabstop>lineEditEccentricity</tabstop>
839 <tabstop>lineEditInclination</tabstop>
840 <tabstop>lineEditLongitudeOfTheAscendingNode</tabstop>
841 <tabstop>radioButtonArgumentOfPeriapsis</tabstop>
842 <tabstop>lineEditArgumentOfPeriapsis</tabstop>
843 <tabstop>radioButtonLongitudeOfPeriapsis</tabstop>
844 <tabstop>lineEditLongitudeOfPeriapsis</tabstop>
845 <tabstop>radioButtonSemiMajorAxis</tabstop>
846 <tabstop>lineEditSemiMajorAxis</tabstop>
847 <tabstop>radioButtonPeriapsisDistance</tabstop>
848 <tabstop>lineEditPeriapsisDistance</tabstop>
849 <tabstop>checkBoxPeriod</tabstop>
850 <tabstop>lineEditPeriod</tabstop>
851 <tabstop>checkBoxMeanMotion</tabstop>
852 <tabstop>lineEditMeanMotion</tabstop>
853 <tabstop>radioButtonEpoch</tabstop>
854 <tabstop>lineEditEpoch</tabstop>
855 <tabstop>pushButtonEpochJ2000</tabstop>
856 <tabstop>radioButtonTimeOfPeriapsis</tabstop>
857 <tabstop>lineEditTimeOfPeriapsis</tabstop>
858 <tabstop>radioButtonMeanAnomaly</tabstop>
859 <tabstop>lineEditMeanAnomaly</tabstop>
860 <tabstop>radioButtonMeanLongitude</tabstop>
861 <tabstop>lineEditMeanLongitude</tabstop>
862 <tabstop>checkBoxOrbitVisualizationPeriod</tabstop>
863 <tabstop>lineEditOrbitVisualizationPeriod</tabstop>
864 <tabstop>checkBoxObliquity</tabstop>
865 <tabstop>lineEditObliquity</tabstop>
866 <tabstop>checkBoxEquatorAscendingNode</tabstop>
867 <tabstop>lineEditEquatorAscendingNode</tabstop>
868 <tabstop>checkBoxNorthPoleRA</tabstop>
869 <tabstop>lineEditNorthPoleRA</tabstop>
870 <tabstop>checkBoxNorthPoleDec</tabstop>
871 <tabstop>lineEditNorthPoleDec</tabstop>
872 <tabstop>checkBoxRotationalPeriod</tabstop>
873 <tabstop>lineEditRotationalPeriod</tabstop>
874 <tabstop>checkBoxPrecessionRate</tabstop>
875 <tabstop>lineEditPrecessionRate</tabstop>
876 <tabstop>checkBoxRotationalEpoch</tabstop>
877 <tabstop>lineEditRotationalEpoch</tabstop>
878 <tabstop>pushButtonRotationalEpochJ2000</tabstop>
879 <tabstop>checkBoxOffset</tabstop>
880 <tabstop>lineEditOffset</tabstop>
881 <tabstop>groupBoxRings</tabstop>
882 <tabstop>lineEditRingInnerSize</tabstop>
883 <tabstop>lineEditRingOuterSize</tabstop>
884 <tabstop>lineEditRingTexture</tabstop>
885 <tabstop>pushButtonSelectRingTexture</tabstop>
886 <tabstop>pushButtonSave</tabstop>
887 </tabstops>
888 <resources/>
889 <connections/>
890</ui>
0891
=== added file 'plugins/SolarSystemEditor/src/gui/mpcImportWindow.ui'
--- plugins/SolarSystemEditor/src/gui/mpcImportWindow.ui 1970-01-01 00:00:00 +0000
+++ plugins/SolarSystemEditor/src/gui/mpcImportWindow.ui 2010-11-16 20:06:17 +0000
@@ -0,0 +1,679 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <author>Bogdan Marinov</author>
4 <class>mpcImportWindow</class>
5 <widget class="QWidget" name="mpcImportWindow">
6 <property name="geometry">
7 <rect>
8 <x>0</x>
9 <y>0</y>
10 <width>480</width>
11 <height>475</height>
12 </rect>
13 </property>
14 <layout class="QVBoxLayout" name="verticalLayout_2">
15 <property name="spacing">
16 <number>0</number>
17 </property>
18 <property name="margin">
19 <number>0</number>
20 </property>
21 <item>
22 <widget class="BarFrame" name="TitleBar">
23 <property name="sizePolicy">
24 <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
25 <horstretch>0</horstretch>
26 <verstretch>0</verstretch>
27 </sizepolicy>
28 </property>
29 <property name="minimumSize">
30 <size>
31 <width>0</width>
32 <height>25</height>
33 </size>
34 </property>
35 <property name="maximumSize">
36 <size>
37 <width>16777215</width>
38 <height>30</height>
39 </size>
40 </property>
41 <property name="focusPolicy">
42 <enum>Qt::NoFocus</enum>
43 </property>
44 <property name="autoFillBackground">
45 <bool>false</bool>
46 </property>
47 <property name="frameShape">
48 <enum>QFrame::StyledPanel</enum>
49 </property>
50 <layout class="QHBoxLayout" name="_2">
51 <property name="spacing">
52 <number>6</number>
53 </property>
54 <property name="leftMargin">
55 <number>0</number>
56 </property>
57 <property name="topMargin">
58 <number>0</number>
59 </property>
60 <property name="rightMargin">
61 <number>4</number>
62 </property>
63 <property name="bottomMargin">
64 <number>0</number>
65 </property>
66 <item>
67 <spacer name="leftSpacer">
68 <property name="orientation">
69 <enum>Qt::Horizontal</enum>
70 </property>
71 <property name="sizeHint" stdset="0">
72 <size>
73 <width>40</width>
74 <height>20</height>
75 </size>
76 </property>
77 </spacer>
78 </item>
79 <item>
80 <widget class="QLabel" name="stelWindowTitle">
81 <property name="text">
82 <string notr="true" extracomment="The title of the window will be set during runtime">Import data</string>
83 </property>
84 </widget>
85 </item>
86 <item>
87 <spacer name="rightSpacer">
88 <property name="orientation">
89 <enum>Qt::Horizontal</enum>
90 </property>
91 <property name="sizeHint" stdset="0">
92 <size>
93 <width>40</width>
94 <height>20</height>
95 </size>
96 </property>
97 </spacer>
98 </item>
99 <item>
100 <widget class="QPushButton" name="closeStelWindow">
101 <property name="minimumSize">
102 <size>
103 <width>16</width>
104 <height>16</height>
105 </size>
106 </property>
107 <property name="maximumSize">
108 <size>
The diff has been truncated for viewing.