Merge lp:~stellarium/stellarium/ip-query-location into lp:stellarium
- ip-query-location
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 6951 |
Proposed branch: | lp:~stellarium/stellarium/ip-query-location |
Merge into: | lp:stellarium |
Diff against target: |
1030 lines (+531/-168) 14 files modified
data/default_config.ini.cmake (+1/-1) src/core/StelCore.cpp (+11/-2) src/core/StelLocation.cpp (+7/-0) src/core/StelLocation.hpp (+3/-0) src/core/StelLocationMgr.cpp (+115/-1) src/core/StelLocationMgr.hpp (+25/-0) src/core/StelUtils.cpp (+34/-0) src/core/StelUtils.hpp (+12/-0) src/gui/LocationDialog.cpp (+122/-31) src/gui/LocationDialog.hpp (+11/-1) src/gui/StelGuiItems.cpp (+8/-4) src/gui/locationDialogGui.ui (+140/-128) src/tests/testConversions.cpp (+41/-0) src/tests/testConversions.hpp (+1/-0) |
To merge this branch: | bzr merge lp:~stellarium/stellarium/ip-query-location |
Related bugs: | |
Related blueprints: |
Location dialog redesign
(Medium)
Enhanced Location Window
(Low)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alexander Wolf | Abstain | ||
Marcos Cardinot | Approve | ||
gzotti | Approve | ||
Fabien Chéreau | Pending | ||
Review via email: mp+229834@code.launchpad.net |
This proposal supersedes a proposal from 2014-07-19.
Commit message
Description of the change
1) Added IP-based location query for location panel and optionally at program start.
2) Improved location GUI:
(a) clicking on the map reduces site list to sites in 3 degrees vicinity.
(b) selecting a country in the combo box reduces site list to sites in that country.
(c) selecting a planet other than earth reduces site list to sites on that planet.
Alexander Wolf (alexwolf) wrote : Posted in a previous version of this proposal | # |
Alexander Wolf (alexwolf) wrote : Posted in a previous version of this proposal | # |
The second feature is OK for me. Are you want merge it yourself?
Alexander Wolf (alexwolf) wrote : Posted in a previous version of this proposal | # |
Wait! What about non-Earth location?
Fabien Chéreau (xalioth) wrote : Posted in a previous version of this proposal | # |
Hi Please cleanup The code. Also use the regular event loop to make a non
blocking call to the service.
Le 19 juil. 2014 15:58, "Alexander Wolf" <email address hidden> a écrit :
> Alexander Wolf has proposed merging
> lp:~georg-zotti/stellarium/ip-query-location into lp:stellarium.
>
> Requested reviews:
> Alexander Wolf (alexwolf)
>
> For more details, see:
>
> https:/
>
> This branch introduces new feature - automatic finding approximate
> location of Stellarium from IP address.
> --
>
> https:/
> You are subscribed to branch lp:stellarium.
>
> === modified file 'src/core/
> --- src/core/
> +++ src/core/
> @@ -114,7 +114,14 @@
> defaultLocationID =
> conf->value(
> bool ok;
> StelLocationMgr* locationMgr =
> &StelApp:
> - StelLocation location =
> locationMgr-
> + StelLocation location;
> + if (conf->
> "false").toBool()
> + && locationMgr-
> + {
> + location=
> + }
> +
> + else location = locationMgr-
> if (!location.
> {
> qWarning() << "Warning: location" << defaultLocationID <<
> "is unknown.";
>
> === modified file 'src/core/
> --- src/core/
> +++ src/core/
> @@ -25,6 +25,13 @@
> #include <QDebug>
> #include <QFile>
> #include <QDir>
> +#include <QtNetwork/
> +#include <QtNetwork/
> +#include <QEventLoop>
> +#include <QNetworkRequest>
> +#include <QNetworkReply>
> +#include <QUrl>
> +#include <QUrlQuery>
>
> StelLocationMgr
> {
> @@ -307,3 +314,99 @@
> sourcefile.close();
> return true;
> }
> +
> +
> +//! check if there is an IP connection.
> +// Along the lines of
> +//
> http://
> +//#define DEBUG 1
> +bool StelLocationMgr
> +{
> + QList<QNetworkI
> + bool connectionExists = false;
> +
> + for (int i = 0; i < ifaces.count(); i++) {
> +
> + QNetworkInterface iface = ifaces.at(i);
> + if ( iface.flags(
> + && !iface.
> +
> +#ifdef DEBUG
> + // details of connection
> + qDebug() << "name:" << iface.name() << endl
> + << "mac:" << iface.hardwareA
> + << "ip addresses:" << endl;
> +#endif
> + for (int j=0; j<iface.
gzotti (georg-zotti) wrote : Posted in a previous version of this proposal | # |
Hm, I was surprised that the site list mixes all sites anyhow. I will try
to reduce selection to the currently set planet...
G.
On Sa, 19.07.2014, 14:26, Alexander Wolf wrote:
> Review: Needs Fixing
>
> Wait! What about non-Earth location?
> --
> https:/
> You are the owner of lp:~georg-zotti/stellarium/ip-query-location.
>
Alexander Wolf (alexwolf) wrote : Posted in a previous version of this proposal | # |
This list is "correct". I meant new features. If I change the planet and picked some point on the map (as example on Mars) then I get locations from Earth!
gzotti (georg-zotti) wrote : Posted in a previous version of this proposal | # |
Sure. This context info did not exist previously...
I filter also by current planet name now. And I want to add a filter for
country as next step towards better usability.
G.
On Sa, 19.07.2014, 18:42, Alexander Wolf wrote:
> This list is "correct". I meant new features. If I change the planet and
> picked some point on the map (as example on Mars) then I get locations
> from Earth!
> --
> https:/
> You are the owner of lp:~georg-zotti/stellarium/ip-query-location.
>
Alexander Wolf (alexwolf) wrote : Posted in a previous version of this proposal | # |
2014-07-20 1:33 GMT+07:00 gzotti <email address hidden>:
> Sure. This context info did not exist previously...
>
> I filter also by current planet name now. And I want to add a filter for
> country as next step towards better usability.
>
It's introduces important problem: search tool will search location in full
list or in filtered list?
--
With best regards, Alexander
gzotti (georg-zotti) wrote : Posted in a previous version of this proposal | # |
The list box gets filled with a preselected short list of nearby locations
on the current planet. If the user selects Earth, the complete list will
be shown at the moment (50 non-Earth entries in 15000 locations, should
not matter...)
The search tool is directly connected to the list, so it only searches in
the pre-filtered list.
There is a reset list button to recreate all entries.
I am not yet sure if I shouldn't clear out the country combobox if
planet!=Earth. This was always quite strange...
G.
On Sa, 19.07.2014, 20:45, Alexander Wolf wrote:
> 2014-07-20 1:33 GMT+07:00 gzotti <email address hidden>:
>
>> Sure. This context info did not exist previously...
>>
>> I filter also by current planet name now. And I want to add a filter for
>> country as next step towards better usability.
>>
>
> It's introduces important problem: search tool will search location in
> full
> list or in filtered list?
>
> --
> With best regards, Alexander
>
> https:/
> You are the owner of lp:~georg-zotti/stellarium/ip-query-location.
>
gzotti (georg-zotti) wrote : Posted in a previous version of this proposal | # |
I have added the requested improvements. I think it works all now.
Alexander Wolf (alexwolf) wrote : Posted in a previous version of this proposal | # |
OK. It work correct now and I think it ready to merge. Fabien?
Fabien Chéreau (xalioth) wrote : Posted in a previous version of this proposal | # |
Please see comments
Marcos Cardinot (cardinot) wrote : Posted in a previous version of this proposal | # |
Hello Georg,
congrats for the excellent work!
I have just a couple of things to suggest (nitpicks)... see comments + I noticed that you are using spaces instead of tabs...
Marcos Cardinot (cardinot) : Posted in a previous version of this proposal | # |
gzotti (georg-zotti) wrote : Posted in a previous version of this proposal | # |
Dear Fabien,
I fixed these items on Monday. Do you approve a merge now?
Kind regards,
Georg
On Mo, 21.07.2014, 19:07, Fabien Chéreau wrote:
> Review: Needs Fixing
>
> Please see comments
>
> Diff comments:
>
>> === modified file 'src/core/
>> --- src/core/
>> +++ src/core/
>> @@ -114,7 +114,13 @@
>> defaultLocationID =
>> conf->value(
>> bool ok;
>> StelLocationMgr* locationMgr =
>> &StelApp:
>> - StelLocation location =
>> locationMgr-
>> + StelLocation location;
>> + if (conf->
>> "false").toBool())
>> + {
>> + locationMgr-
>> + }
>> +
>> + else location = locationMgr-
>> if (!location.
>> {
>> qWarning() << "Warning: location" << defaultLocationID << "is
>> unknown.";
>>
>> === modified file 'src/core/
>> --- src/core/
>> +++ src/core/
>> @@ -125,3 +125,10 @@
>> return loc;
>> }
>>
>> +// Compute great-circle distance between two locations
>> +float StelLocation:
>> lat1, const float long2, const float lat2)
>> +{
>> + const float DEGREES=
>> + return std::acos( std::sin(
>> +
>> std::cos(
>> ) / DEGREES;
>> +}
>>
>> === modified file 'src/core/
>> --- src/core/
>> +++ src/core/
>> @@ -74,6 +74,9 @@
>> //! Parse a location from a line serialization
>> static StelLocation createFromLine(
>>
>> + //! Compute great-circle distance between two locations
>> + static float distanceDegrees
>> const float long2, const float lat2);
>> +
>> //! Used privately by the StelLocationMgr
>> bool isUserLocation;
>>
>>
>> === modified file 'src/core/
>> --- src/core/
>> +++ src/core/
>> @@ -17,6 +17,7 @@
>> */
>>
>> #include "StelApp.hpp"
>> +#include "StelCore.hpp"
>> #include "StelFileMgr.hpp"
>> #include "StelLocationMg
>> #include "StelUtils.hpp"
>> @@ -25,6 +26,12 @@
>> #include <QDebug>
>> #include <QFile>
>> #include <QDir>
>> +#include <QtNetwork/
>> +#include <QtNetwork/
>> +#include <QNetworkRequest>
>> +#include <QNetworkReply>
>> +#include <QUrl>
>> +#include <QUrlQuery>
>>
>> StelLocationMgr
>> {
>> @@ -36,9 +43,12 @@
>>
>> modelAllLocation = new QStringListMode
>> modelAllLocatio
>> + modelPickedLocation = new QStringListMode
>> now.
>>
>> // Init to Paris France because it's the center of the world.
>> lastResortLocation =...
Fabien Chéreau (xalioth) wrote : Posted in a previous version of this proposal | # |
Hi Georg,
now that I'm back from holidays, I could acutally try the code, and I have
some more general comments about your (very very good!) work:
- we should rename "IP Query" to something less technical, like "Get
location from Network"
- I think the IP location is such an improvement that it should be the
default for all new install, and also probably used by default for installs
where the location was never set (set to Paris). This would imply that we
transform at startup all older config.ini from location = Paris, France to
location = auto. And use this "auto" value to trigger IP Lookup instead of
adding a new "init_location/
- Also when the lookup is successful, we could save the last know location
into an "init_location/
without network.
Sorry to give these feedbacks so late, I hope they make sense, what do you
think? In any case, I think the lack of auto location feature was the most
annoying problem of Stellarium for an average user living in US, so thanks
a lot again!
Fabien
On Sat, Jul 26, 2014 at 12:24 PM, gzotti <email address hidden> wrote:
> Dear Fabien,
>
> I fixed these items on Monday. Do you approve a merge now?
>
> Kind regards,
> Georg
>
> On Mo, 21.07.2014, 19:07, Fabien Chéreau wrote:
> > Review: Needs Fixing
> >
> > Please see comments
> >
> > Diff comments:
> >
> >> === modified file 'src/core/
> >> --- src/core/
> >> +++ src/core/
> >> @@ -114,7 +114,13 @@
> >> defaultLocationID =
> >> conf->value(
> >> bool ok;
> >> StelLocationMgr* locationMgr =
> >> &StelApp:
> >> - StelLocation location =
> >> locationMgr-
> >> + StelLocation location;
> >> + if (conf->
> >> "false").toBool())
> >> + {
> >> + locationMgr-
> >> + }
> >> +
> >> + else location = locationMgr-
> >> if (!location.
> >> {
> >> qWarning() << "Warning: location" << defaultLocationID <<
> "is
> >> unknown.";
> >>
> >> === modified file 'src/core/
> >> --- src/core/
> >> +++ src/core/
> >> @@ -125,3 +125,10 @@
> >> return loc;
> >> }
> >>
> >> +// Compute great-circle distance between two locations
> >> +float StelLocation:
> >> lat1, const float long2, const float lat2)
> >> +{
> >> + const float DEGREES=
> >> + return std::acos( std::sin(
> >> +
> >>
> std::cos(
> >> ) / DEGREES;
> >> +}
> >>
> >> === modified file 'src/core/
> >> --- src/core/
> >> +++ src/core/
> >> ...
gzotti (georg-zotti) wrote : Posted in a previous version of this proposal | # |
Dear Fabien,
thanks for your friendly words.
I know "IP query" is very technical. But what to write on a 6-letter
button? Else, the button must stretch over the whole window, I did not
want to make it too intrusive. If there is space, it should be
"approximate location", my own query is about 50km off... But it's still
quite a good start.
A default IP lookup for new installs seems fine, as long as there remains
a fallback location in case someone travels to his offline PC with an USB
stick with the latest version. (When I traveled to Namibia for some
astrophotos with a Stellarium-guided telescope, my Atom netbook was also
definitely offline...)
Having the always-
possible to set and keep a home position as well, even if we are online at
startup. (And if somebody in Paris is happy with startup location, he will
be surprised to find his place renamed to IPxxxx :-)
The other changes are with finding a location near map-click point and
with the country/planet comboboxes. I think they are much more functional
now. What may still be done is to deactivate and empty the country box if
we are not on Earth.
My short slot of time is unfortunately over for this weekend. So, if you
like it, please merge and feel free to tweak these small details.
I just tried your brother's no-bit-field branch. It compiles on my Atom
450 netbook (MSVC2012/Angle; takes ages...), but the shader programs are
too long. I cannot find any info on how to programmatically check shader
support from the GPU: is Angle limited to pixelshader2, vertexshader2 and
fails on every system, or would it compile ps_3, vs_3 if the graphics card
supports this? Going for Angle was the hope to support simpler/older
hardware, so if there would be a way to support ps_2+vs_2 hardware like
Atom or older Radeon or Intel GMA by utilizing simpler shader programs
(e.g. no ring shadows, normal maps, etc.?) after some tests, there would
be less users having to use super-slow MESA. (But I'm happy at least MESA
is a stable fallback...)
What I still don't know is why my both NVidias on WinXP fail. Both should
support OpenGL3.3.
Kind regards,
Georg
On Sa, 26.07.2014, 18:24, Fabien Chéreau wrote:
> Hi Georg,
>
> now that I'm back from holidays, I could acutally try the code, and I have
> some more general comments about your (very very good!) work:
>
> - we should rename "IP Query" to something less technical, like "Get
> location from Network"
>
> - I think the IP location is such an improvement that it should be the
> default for all new install, and also probably used by default for
> installs
> where the location was never set (set to Paris). This would imply that we
> transform at startup all older config.ini from location = Paris, France to
> location = auto. And use this "auto" value to trigger IP Lookup instead of
> adding a new "init_location/
>
> - Also when the lookup is successful, we could save the last know location
> into an "init_location/
> without network.
>
> Sorry to give these feedbacks so late, I hope they make sense, what do you
> think? In ...
Alexander Wolf (alexwolf) wrote : Posted in a previous version of this proposal | # |
IMHO we can merge this branch and improve some features.
Alexander Wolf (alexwolf) wrote : Posted in a previous version of this proposal | # |
OK. I updated code to usage of this feature by default.
Alexander Wolf (alexwolf) : | # |
gzotti (georg-zotti) wrote : | # |
Hmm, if
in current merge/diff display, Line 27: (defaultLocatio
consider a (existence unknown to me) a place name "Antautorina", you never know what placenames exist... ;-) --> Should be ".equals()"
One place of even greater concern, but I did not test your changes of today:
line 183: setting Last_resort_
- 6938. By Alexander Wolf
-
avoid Antautorina's bug
- 6939. By Alexander Wolf
-
avoid unknown location's bug (location not exists in stellarium database)
Alexander Wolf (alexwolf) wrote : | # |
OK. I fixed both issues.
gzotti (georg-zotti) wrote : | # |
Some more usability things:
config.ini, name "last_resort_
I tried: switch off LAN, start without config.ini. It loads, displays 0.00/0.00 for a second, then goes to Paris. OK.
switch on LAN, start. IP lookup, correctly displaying even place name (this time IP answer was more complete than at my place.)
restart Stellarium, name lookup of course again leads to correct display.
switch off LAN, restart Stellarium, loads coordinates of last[_resort?
Also, I think that after the first successful IP lookup, this function should be off by default. Else we may put too much traffic onto the free service, and/or people may even complain about unwanted network traffic (?), but this is my opinion only. What do the others say?
Alexander Wolf (alexwolf) wrote : | # |
> switch off LAN, restart Stellarium, loads coordinates of last[_resort?
In last_resort_
- 6940. By Alexander Wolf
-
renamed last_resort_
location to last_location
gzotti (georg-zotti) wrote : | # |
Sure, but the displayed name is random numbers, not the coordinates used!
Example: The stored last_[remove"
Displayed in lower left corner: Earth, 147°23' 133°34'
(I did not copy these numbers from live display, but this should just
illustrate their randomness. No connection I can see with the real data.)
Alexander Wolf (alexwolf) wrote : | # |
Oh, yes! I'll look it tomorrow.
- 6941. By Alexander Wolf
-
fixed issue of display coordinates of location
Alexander Wolf (alexwolf) wrote : | # |
OK. It's done.
gzotti (georg-zotti) wrote : | # |
OK, looks fine now.
- 6942. By Alexander Wolf
-
avoid rounding issue and extend unit tests
Alexander Wolf (alexwolf) wrote : | # |
Fabien, please review this code.
Marcos Cardinot (cardinot) wrote : | # |
I have just a small suggestion, IMHO the button "Return to default location" should be placed on the left side, above "Use current location as default"... it means put the horizontalSpacer between "Delete" and "Return to default location"...
Alexander Wolf (alexwolf) : | # |
Preview Diff
1 | === modified file 'data/default_config.ini.cmake' |
2 | --- data/default_config.ini.cmake 2014-07-31 19:02:38 +0000 |
3 | +++ data/default_config.ini.cmake 2014-08-08 12:24:49 +0000 |
4 | @@ -242,7 +242,7 @@ |
5 | nebula_magnitude_limit = 8.5 |
6 | |
7 | [init_location] |
8 | -location = Paris, France |
9 | +location = auto |
10 | landscape_name = guereins |
11 | |
12 | [files] |
13 | |
14 | === modified file 'src/core/StelCore.cpp' |
15 | --- src/core/StelCore.cpp 2014-04-14 17:55:46 +0000 |
16 | +++ src/core/StelCore.cpp 2014-08-08 12:24:49 +0000 |
17 | @@ -111,10 +111,19 @@ |
18 | { |
19 | QSettings* conf = StelApp::getInstance().getSettings(); |
20 | |
21 | - defaultLocationID = conf->value("init_location/location","error").toString(); |
22 | + defaultLocationID = conf->value("init_location/location", "auto").toString(); |
23 | bool ok; |
24 | StelLocationMgr* locationMgr = &StelApp::getInstance().getLocationMgr(); |
25 | - StelLocation location = locationMgr->locationForString(defaultLocationID); |
26 | + StelLocation location; |
27 | + if (defaultLocationID == "auto") |
28 | + { |
29 | + locationMgr->locationFromIP(); |
30 | + } |
31 | + else |
32 | + { |
33 | + location = locationMgr->locationForString(defaultLocationID); |
34 | + } |
35 | + |
36 | if (!location.isValid()) |
37 | { |
38 | qWarning() << "Warning: location" << defaultLocationID << "is unknown."; |
39 | |
40 | === modified file 'src/core/StelLocation.cpp' |
41 | --- src/core/StelLocation.cpp 2014-02-15 15:37:23 +0000 |
42 | +++ src/core/StelLocation.cpp 2014-08-08 12:24:49 +0000 |
43 | @@ -125,3 +125,10 @@ |
44 | return loc; |
45 | } |
46 | |
47 | +// Compute great-circle distance between two locations |
48 | +float StelLocation::distanceDegrees(const float long1, const float lat1, const float long2, const float lat2) |
49 | +{ |
50 | + const float DEGREES=M_PI/180.0f; |
51 | + return std::acos( std::sin(lat1*DEGREES)*std::sin(lat2*DEGREES) + |
52 | + std::cos(lat1*DEGREES)*std::cos(lat2*DEGREES)*std::cos((long1-long2)*DEGREES) ) / DEGREES; |
53 | +} |
54 | |
55 | === modified file 'src/core/StelLocation.hpp' |
56 | --- src/core/StelLocation.hpp 2014-04-15 17:10:07 +0000 |
57 | +++ src/core/StelLocation.hpp 2014-08-08 12:24:49 +0000 |
58 | @@ -74,6 +74,9 @@ |
59 | //! Parse a location from a line serialization |
60 | static StelLocation createFromLine(const QString& line); |
61 | |
62 | + //! Compute great-circle distance between two locations |
63 | + static float distanceDegrees(const float long1, const float lat1, const float long2, const float lat2); |
64 | + |
65 | //! Used privately by the StelLocationMgr |
66 | bool isUserLocation; |
67 | |
68 | |
69 | === modified file 'src/core/StelLocationMgr.cpp' |
70 | --- src/core/StelLocationMgr.cpp 2014-06-12 15:47:22 +0000 |
71 | +++ src/core/StelLocationMgr.cpp 2014-08-08 12:24:49 +0000 |
72 | @@ -17,6 +17,7 @@ |
73 | */ |
74 | |
75 | #include "StelApp.hpp" |
76 | +#include "StelCore.hpp" |
77 | #include "StelFileMgr.hpp" |
78 | #include "StelLocationMgr.hpp" |
79 | #include "StelUtils.hpp" |
80 | @@ -25,9 +26,18 @@ |
81 | #include <QDebug> |
82 | #include <QFile> |
83 | #include <QDir> |
84 | +#include <QtNetwork/QNetworkInterface> |
85 | +#include <QtNetwork/QNetworkAccessManager> |
86 | +#include <QNetworkRequest> |
87 | +#include <QNetworkReply> |
88 | +#include <QUrl> |
89 | +#include <QUrlQuery> |
90 | +#include <QSettings> |
91 | |
92 | StelLocationMgr::StelLocationMgr() |
93 | { |
94 | + QSettings* conf = StelApp::getInstance().getSettings(); |
95 | + |
96 | // The line below allows to re-generate the location file, you still need to gunzip it manually afterward. |
97 | // generateBinaryLocationFile("data/base_locations.txt", false, "data/base_locations.bin"); |
98 | |
99 | @@ -36,9 +46,10 @@ |
100 | |
101 | modelAllLocation = new QStringListModel(this); |
102 | modelAllLocation->setStringList(locations.keys()); |
103 | + modelPickedLocation = new QStringListModel(this); // keep empty for now. |
104 | |
105 | // Init to Paris France because it's the center of the world. |
106 | - lastResortLocation = locationForString("Paris, France"); |
107 | + lastResortLocation = locationForString(conf->value("init_location/last_location", "Paris, France").toString()); |
108 | } |
109 | |
110 | void StelLocationMgr::generateBinaryLocationFile(const QString& fileName, bool isUserLocation, const QString& binFilePath) const |
111 | @@ -144,6 +155,10 @@ |
112 | |
113 | StelLocationMgr::~StelLocationMgr() |
114 | { |
115 | + delete modelPickedLocation; |
116 | + modelPickedLocation=NULL; |
117 | + delete modelAllLocation; |
118 | + modelAllLocation=NULL; |
119 | } |
120 | |
121 | static float parseAngle(const QString& s, bool* ok) |
122 | @@ -307,3 +322,102 @@ |
123 | sourcefile.close(); |
124 | return true; |
125 | } |
126 | + |
127 | +// lookup location from IP address. |
128 | +void StelLocationMgr::locationFromIP() |
129 | +{ |
130 | + QNetworkRequest req( QUrl( QString("http://freegeoip.net/csv/") ) ); |
131 | + networkReply=StelApp::getInstance().getNetworkAccessManager()->get(req); |
132 | + connect(networkReply, SIGNAL(finished()), this, SLOT(changeLocationFromNetworkLookup())); |
133 | +} |
134 | + |
135 | +// slot that receives IP-based location data from the network. |
136 | +void StelLocationMgr::changeLocationFromNetworkLookup() |
137 | +{ |
138 | + StelLocation location; |
139 | + StelCore *core=StelApp::getInstance().getCore(); |
140 | + if (networkReply->error() == QNetworkReply::NoError) { |
141 | + //success |
142 | + // Tested with and without working network connection. |
143 | + QByteArray answer=networkReply->readAll(); |
144 | + // answer/splitline example: "222.222.222.222","AT","Austria","","","","","47.3333","13.3333","","" |
145 | + // The parts from freegeoip are: ip,country_code,country_name,region_code,region_name,city,zipcode,latitude,longitude,metro_code,area_code |
146 | + // longitude and latitude should always be filled. |
147 | + // A few tests: |
148 | + if ((answer.count('"') != 22 ) || (answer.count(',') != 10 )) |
149 | + { |
150 | + qDebug() << "StelLocationMgr: Malformatted answer in IP-based location lookup: \n\t" << answer; |
151 | + qDebug() << "StelLocationMgr: Will not change location."; |
152 | + networkReply->deleteLater(); |
153 | + return; |
154 | + } |
155 | + const QStringList& splitline = QString(answer).split(","); |
156 | + if (splitline.count() != 11 ) |
157 | + { |
158 | + qDebug() << "StelLocationMgr: Unexpected answer in IP-based location lookup: \n\t" << answer; |
159 | + qDebug() << "StelLocationMgr: Will not change location."; |
160 | + networkReply->deleteLater(); |
161 | + return; |
162 | + } |
163 | + if ((splitline.at(7)=="\"\"") || (splitline.at(8)=="\"\"")) // empty coordinates? |
164 | + { |
165 | + qDebug() << "StelLocationMgr: Invalid coordinates from IP-based lookup. Ignoring: \n\t" << answer; |
166 | + networkReply->deleteLater(); |
167 | + return; |
168 | + } |
169 | + float latitude=splitline.at(7).mid(1, splitline.at(7).length()-2).toFloat(); |
170 | + float longitude=splitline.at(8).mid(1, splitline.at(8).length()-2).toFloat(); |
171 | + QString locLine= // we re-pack into a new line that will be parsed back by StelLocation... |
172 | + QString("%1\t%2\t%3\t%4\t%5\t%6\t%7\t0") |
173 | + .arg(splitline.at(5).length()>2 ? splitline.at(5).mid(1, splitline.at(5).length()-2) : QString("IP%1").arg(splitline.at(0).mid(1, splitline.at(0).length()-2))) |
174 | + .arg(splitline.at(4).length()>2 ? splitline.at(4).mid(1, splitline.at(4).length()-2) : "IPregion") |
175 | + .arg(splitline.at(2).length()>2 ? splitline.at(2).mid(1, splitline.at(2).length()-2) : "IPcountry") // country |
176 | + .arg("X") // role: X=user-defined |
177 | + .arg(0) // population: unknown |
178 | + .arg(latitude<0 ? QString("%1S").arg(-latitude, 0, 'f', 6) : QString("%1N").arg(latitude, 0, 'f', 6)) |
179 | + .arg(longitude<0 ? QString("%1W").arg(-longitude, 0, 'f', 6) : QString("%1E").arg(longitude, 0, 'f', 6)); |
180 | + location=StelLocation::createFromLine(locLine); // in lack of a regular constructor ;-) |
181 | + core->moveObserverTo(location, 0.0f, 0.0f); |
182 | + QSettings* conf = StelApp::getInstance().getSettings(); |
183 | + conf->setValue("init_location/last_location", QString("%1, %2").arg(latitude).arg(longitude)); |
184 | + } |
185 | + else |
186 | + { |
187 | + qDebug() << "Failure getting IP-based location: \n\t" <<networkReply->errorString(); |
188 | + core->moveObserverTo(lastResortLocation, 0.0f, 0.0f); |
189 | + } |
190 | + networkReply->deleteLater(); |
191 | +} |
192 | + |
193 | +void StelLocationMgr::pickLocationsNearby(const QString planetName, const float longitude, const float latitude, const float radiusDegrees) |
194 | +{ |
195 | + pickedLocations.clear(); |
196 | + QMapIterator<QString, StelLocation> iter(locations); |
197 | + while (iter.hasNext()) |
198 | + { |
199 | + iter.next(); |
200 | + const StelLocation *loc=&iter.value(); |
201 | + if ( (loc->planetName == planetName) && |
202 | + (StelLocation::distanceDegrees(longitude, latitude, loc->longitude, loc->latitude) <= radiusDegrees) ) |
203 | + { |
204 | + pickedLocations.insert(iter.key(), iter.value()); |
205 | + } |
206 | + } |
207 | + modelPickedLocation->setStringList(pickedLocations.keys()); |
208 | +} |
209 | + |
210 | +void StelLocationMgr::pickLocationsInCountry(const QString country) |
211 | +{ |
212 | + pickedLocations.clear(); |
213 | + QMapIterator<QString, StelLocation> iter(locations); |
214 | + while (iter.hasNext()) |
215 | + { |
216 | + iter.next(); |
217 | + const StelLocation *loc=&iter.value(); |
218 | + if (loc->country == country) |
219 | + { |
220 | + pickedLocations.insert(iter.key(), iter.value()); |
221 | + } |
222 | + } |
223 | + modelPickedLocation->setStringList(pickedLocations.keys()); |
224 | +} |
225 | |
226 | === modified file 'src/core/StelLocationMgr.hpp' |
227 | --- src/core/StelLocationMgr.hpp 2013-10-14 07:43:06 +0000 |
228 | +++ src/core/StelLocationMgr.hpp 2014-08-08 12:24:49 +0000 |
229 | @@ -26,6 +26,7 @@ |
230 | #include <QMap> |
231 | |
232 | class QStringListModel; |
233 | +class QNetworkReply; |
234 | |
235 | //! @class StelLocationMgr |
236 | //! Manage the list of available location. |
237 | @@ -41,6 +42,8 @@ |
238 | |
239 | //! Return the model containing all the city |
240 | QStringListModel* getModelAll() {return modelAllLocation;} |
241 | + //! Return the model containing picked (nearby) cities or cities from a single country, or other preselection. |
242 | + QStringListModel* getModelPicked() {return modelPickedLocation;} |
243 | |
244 | //! Return the list of all loaded locations |
245 | QList<StelLocation> getAll() const {return locations.values();} |
246 | @@ -70,6 +73,20 @@ |
247 | //! @param id the location ID |
248 | bool deleteUserLocation(const QString& id); |
249 | |
250 | + //! Find location via online lookup of IP address |
251 | + void locationFromIP(); |
252 | + |
253 | + //! Preselect list of locations within @param radiusDegrees of selected (usually screen-clicked) coordinates. |
254 | + //! The list can be retrieved by calling @name getModelPicked(). |
255 | + void pickLocationsNearby(const QString planetName, const float longitude, const float latitude, const float radiusDegrees); |
256 | + //! Preselect list of locations in a particular country only. |
257 | + //! The list can be retrieved by calling @name getModelPicked(). |
258 | + void pickLocationsInCountry(const QString country); |
259 | + |
260 | +public slots: |
261 | + //! Process answer from online lookup of IP address |
262 | + void changeLocationFromNetworkLookup(); |
263 | + |
264 | private: |
265 | void generateBinaryLocationFile(const QString& txtFile, bool isUserLocation, const QString& binFile) const; |
266 | |
267 | @@ -79,11 +96,19 @@ |
268 | |
269 | //! Model containing all the city information |
270 | QStringListModel* modelAllLocation; |
271 | + //! Model containing selected city information |
272 | + QStringListModel* modelPickedLocation; |
273 | |
274 | //! The list of all loaded locations |
275 | QMap<QString, StelLocation> locations; |
276 | + //! A list of locations generated on-the-fly by filtering from @name locations |
277 | + QMap<QString, StelLocation> pickedLocations; |
278 | |
279 | StelLocation lastResortLocation; |
280 | + |
281 | + //! For IP-based location lookup |
282 | + QNetworkReply *networkReply; |
283 | + |
284 | }; |
285 | |
286 | #endif // _STELLOCATIONMGR_HPP_ |
287 | |
288 | === modified file 'src/core/StelUtils.cpp' |
289 | --- src/core/StelUtils.cpp 2014-07-05 15:16:58 +0000 |
290 | +++ src/core/StelUtils.cpp 2014-08-08 12:24:49 +0000 |
291 | @@ -370,6 +370,40 @@ |
292 | return str; |
293 | } |
294 | |
295 | +void decDegToDms(double angle, bool &sign, unsigned int &d, unsigned int &m, double &s) |
296 | +{ |
297 | + sign = true; |
298 | + if (angle<0.) |
299 | + { |
300 | + sign = false; |
301 | + angle *= -1; |
302 | + } |
303 | + |
304 | + d = (unsigned int)angle; |
305 | + m = (unsigned int)((angle-d)*60); |
306 | + s = (angle-d)*3600.-60.*m; |
307 | + |
308 | + if (s==60.) |
309 | + { |
310 | + s = 0.; |
311 | + m += 1; |
312 | + } |
313 | + if (m==60) |
314 | + { |
315 | + m = 0; |
316 | + d += 1; |
317 | + } |
318 | +} |
319 | + |
320 | +// Convert an angle in decimal degrees to a dms formatted string |
321 | +QString decDegToDmsStr(const double angle) |
322 | +{ |
323 | + bool sign; |
324 | + double s; |
325 | + unsigned int d, m; |
326 | + decDegToDms(angle, sign, d, m, s); |
327 | + return QString("%1%2%3%4\'%5\"").arg(sign?'+':'-').arg(d).arg(QChar(0x00B0)).arg(m,2,10,QLatin1Char('0')).arg((unsigned int)s,2,10,QLatin1Char('0')); |
328 | +} |
329 | |
330 | // Convert a dms formatted string to an angle in radian |
331 | double dmsStrToRad(const QString& s) |
332 | |
333 | === modified file 'src/core/StelUtils.hpp' |
334 | --- src/core/StelUtils.hpp 2014-06-22 14:08:40 +0000 |
335 | +++ src/core/StelUtils.hpp 2014-08-08 12:24:49 +0000 |
336 | @@ -99,6 +99,18 @@ |
337 | //! @param decimal output decimal second value |
338 | QString radToDmsStr(const double angle, const bool decimal=false, const bool useD=false); |
339 | |
340 | + //! Convert an angle in decimal degree to +-dms format. |
341 | + //! @param angle input angle in decimal degree |
342 | + //! @param sign true if positive, false otherwise |
343 | + //! @param d degree component |
344 | + //! @param m minute component |
345 | + //! @param s second component |
346 | + void decDegToDms(double angle, bool& sign, unsigned int& d, unsigned int& m, double& s); |
347 | + |
348 | + //! Convert an angle in decimal degrees to a dms formatted string. |
349 | + //! @param angle input angle in decimal degrees |
350 | + QString decDegToDmsStr(const double angle); |
351 | + |
352 | //! Convert a dms formatted string to an angle in radian |
353 | //! @param s The input string |
354 | double dmsStrToRad(const QString& s); |
355 | |
356 | === modified file 'src/gui/LocationDialog.cpp' |
357 | --- src/gui/LocationDialog.cpp 2014-03-21 18:03:55 +0000 |
358 | +++ src/gui/LocationDialog.cpp 2014-08-08 12:24:49 +0000 |
359 | @@ -99,22 +99,30 @@ |
360 | connect(ui->mapLabel, SIGNAL(positionChanged(double, double)), this, SLOT(setPositionFromMap(double, double))); |
361 | |
362 | connect(ui->addLocationToListPushButton, SIGNAL(clicked()), this, SLOT(addCurrentLocationToList())); |
363 | - connect(ui->deleteLocationFromListPushButton, SIGNAL(clicked()), this, SLOT(deleteCurrentLocationFromList())); |
364 | + connect(ui->deleteLocationFromListPushButton, SIGNAL(clicked()), this, SLOT(deleteCurrentLocationFromList())); |
365 | + connect(ui->resetListPushButton, SIGNAL(clicked()), this, SLOT(resetCompleteList())); |
366 | + connect(ui->countryNameComboBox, SIGNAL(activated(const QString &)), this, SLOT(filterSitesByCountry())); |
367 | |
368 | StelCore* core = StelApp::getInstance().getCore(); |
369 | const StelLocation& currentLocation = core->getCurrentLocation(); |
370 | + bool b = (currentLocation.getID() == core->getDefaultLocationID()); |
371 | + QSettings* conf = StelApp::getInstance().getSettings(); |
372 | + if (conf->value("init_location/location", "auto").toString() == "auto") |
373 | + { |
374 | + ui->useIpQueryCheckBox->setChecked(true); |
375 | + b = false; |
376 | + } |
377 | + |
378 | setFieldsFromLocation(currentLocation); |
379 | - |
380 | - const bool b = (currentLocation.getID() == core->getDefaultLocationID()); |
381 | updateDefaultLocationControls(b); |
382 | - connect(ui->useAsDefaultLocationCheckBox, SIGNAL(clicked()), this, SLOT(setDefaultLocation())); |
383 | - connect(ui->pushButtonReturnToDefault, SIGNAL(clicked()), |
384 | - core, SLOT(returnToDefaultLocation())); |
385 | + |
386 | + connect(ui->useIpQueryCheckBox, SIGNAL(clicked(bool)), this, SLOT(ipQueryLocation(bool))); |
387 | + connect(ui->useAsDefaultLocationCheckBox, SIGNAL(clicked(bool)), this, SLOT(setDefaultLocation(bool))); |
388 | + connect(ui->pushButtonReturnToDefault, SIGNAL(clicked()), core, SLOT(returnToDefaultLocation())); |
389 | |
390 | connectEditSignals(); |
391 | |
392 | - connect(core, SIGNAL(locationChanged(StelLocation)), |
393 | - this, SLOT(updateFromProgram(StelLocation))); |
394 | + connect(core, SIGNAL(locationChanged(StelLocation)), this, SLOT(updateFromProgram(StelLocation))); |
395 | |
396 | ui->citySearchLineEdit->setFocus(); |
397 | } |
398 | @@ -138,7 +146,12 @@ |
399 | // Check that the use as default check box needs to be updated |
400 | // Move to setFieldsFromLocation()? --BM? |
401 | const bool b = currentLocation.getID() == stelCore->getDefaultLocationID(); |
402 | - updateDefaultLocationControls(b); |
403 | + QSettings* conf = StelApp::getInstance().getSettings(); |
404 | + if (conf->value("init_location/location", "auto").toString() != ("auto")) |
405 | + { |
406 | + updateDefaultLocationControls(b); |
407 | + ui->pushButtonReturnToDefault->setEnabled(!b); |
408 | + } |
409 | |
410 | const QString& key1 = currentLocation.getID(); |
411 | const QString& key2 = locationFromFields().getID(); |
412 | @@ -169,8 +182,7 @@ |
413 | disconnect(ui->countryNameComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(reportEdit())); |
414 | // Why an edit should be reported even if the country is not changed? --BM |
415 | //disconnect(ui->countryNameComboBox, SIGNAL(activated(const QString&)), this, SLOT(comboBoxChanged(const QString&))); |
416 | - disconnect(ui->cityNameLineEdit, SIGNAL(textEdited(const QString&)), |
417 | - this, SLOT(reportEdit())); |
418 | + disconnect(ui->cityNameLineEdit, SIGNAL(textEdited(const QString&)), this, SLOT(reportEdit())); |
419 | } |
420 | |
421 | void LocationDialog::connectEditSignals() |
422 | @@ -182,8 +194,7 @@ |
423 | connect(ui->countryNameComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(reportEdit())); |
424 | // Why an edit should be reported even if the country is not changed? --BM |
425 | //connect(ui->countryNameComboBox, SIGNAL(activated(const QString&)), this, SLOT(comboBoxChanged(const QString&))); |
426 | - connect(ui->cityNameLineEdit, SIGNAL(textEdited(const QString&)), |
427 | - this, SLOT(reportEdit())); |
428 | + connect(ui->cityNameLineEdit, SIGNAL(textEdited(const QString&)), this, SLOT(reportEdit())); |
429 | } |
430 | |
431 | void LocationDialog::setFieldsFromLocation(const StelLocation& loc) |
432 | @@ -235,7 +246,7 @@ |
433 | // Update the map for the given location. |
434 | void LocationDialog::setMapForLocation(const StelLocation& loc) |
435 | { |
436 | - // Avoids usless processing |
437 | + // Avoids useless processing |
438 | if (lastPlanet==loc.planetName) |
439 | return; |
440 | |
441 | @@ -358,6 +369,15 @@ |
442 | loc.longitude = longitude; |
443 | setFieldsFromLocation(loc); |
444 | StelApp::getInstance().getCore()->moveObserverTo(loc, 0.); |
445 | + // GZ: Filter location list for nearby sites. I assume Earth locations are better known. With only few locations on other planets in the list, 30 degrees seem OK. |
446 | + StelApp::getInstance().getLocationMgr().pickLocationsNearby(loc.planetName, longitude, latitude, loc.planetName=="Earth" ? 3.0f: 30.0f); |
447 | + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); |
448 | + proxyModel->setSourceModel((QAbstractItemModel*)StelApp::getInstance().getLocationMgr().getModelPicked()); |
449 | + proxyModel->sort(0, Qt::AscendingOrder); |
450 | + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); |
451 | + ui->citiesListView->setModel(proxyModel); |
452 | + ui->citySearchLineEdit->clear(); |
453 | + connect(ui->citySearchLineEdit, SIGNAL(textChanged(const QString&)), proxyModel, SLOT(setFilterWildcard(const QString&))); |
454 | } |
455 | |
456 | // Called when the planet name is changed by hand |
457 | @@ -380,6 +400,24 @@ |
458 | ls->setCurrentLandscapeID(ls->getDefaultLandscapeID()); |
459 | } |
460 | |
461 | + // GZ populate site list with sites only from that planet, or full list for Earth (faster than removing the ~50 non-Earth positions...). |
462 | + StelLocationMgr &locMgr=StelApp::getInstance().getLocationMgr(); |
463 | + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); |
464 | + if (loc.planetName == "Earth") |
465 | + { |
466 | + proxyModel->setSourceModel((QAbstractItemModel*)locMgr.getModelAll()); |
467 | + } |
468 | + else |
469 | + { |
470 | + locMgr.pickLocationsNearby(loc.planetName, 0.0f, 0.0f, 180.0f); |
471 | + proxyModel->setSourceModel((QAbstractItemModel*)locMgr.getModelPicked()); |
472 | + } |
473 | + proxyModel->sort(0, Qt::AscendingOrder); |
474 | + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); |
475 | + ui->citiesListView->setModel(proxyModel); |
476 | + ui->citySearchLineEdit->clear(); |
477 | + connect(ui->citySearchLineEdit, SIGNAL(textChanged(const QString&)), proxyModel, SLOT(setFilterWildcard(const QString&))); |
478 | + ui->citySearchLineEdit->setFocus(); |
479 | } |
480 | // Planet transition time also set to null to prevent uglyness when |
481 | // "use landscape location" is enabled for that planet's landscape. --BM |
482 | @@ -429,7 +467,7 @@ |
483 | ui->deleteLocationFromListPushButton->setEnabled(locationMgr.canDeleteUserLocation(loc.getID())); |
484 | } |
485 | |
486 | -// Called when the user clic on the save button |
487 | +// Called when the user clicks on the save button |
488 | void LocationDialog::addCurrentLocationToList() |
489 | { |
490 | const StelLocation& loc = locationFromFields(); |
491 | @@ -456,22 +494,27 @@ |
492 | } |
493 | |
494 | // Called when the user wants to use the current location as default |
495 | -void LocationDialog::setDefaultLocation() |
496 | +void LocationDialog::setDefaultLocation(bool state) |
497 | { |
498 | - StelCore* core = StelApp::getInstance().getCore(); |
499 | - QString currentLocationId = core->getCurrentLocation().getID(); |
500 | - core->setDefaultLocationID(currentLocationId); |
501 | + if (state) |
502 | + { |
503 | + StelCore* core = StelApp::getInstance().getCore(); |
504 | + QString currentLocationId = core->getCurrentLocation().getID(); |
505 | + core->setDefaultLocationID(currentLocationId); |
506 | |
507 | - // Why this code even exists? After the previous code, this should always |
508 | - // be true, except if setting the default location somehow fails. --BM |
509 | - bool isDefault = (currentLocationId == core->getDefaultLocationID()); |
510 | - disconnectEditSignals(); |
511 | - updateDefaultLocationControls(isDefault); |
512 | - //The focus need to be switched to another control, otherwise |
513 | - //ui->latitudeSpinBox receives it and emits a valueChanged() signal when |
514 | - //the window is closed. |
515 | - ui->citySearchLineEdit->setFocus(); |
516 | - connectEditSignals(); |
517 | + // Why this code even exists? After the previous code, this should always |
518 | + // be true, except if setting the default location somehow fails. --BM |
519 | + bool isDefault = (currentLocationId == core->getDefaultLocationID()); |
520 | + disconnectEditSignals(); |
521 | + updateDefaultLocationControls(isDefault); |
522 | + ui->pushButtonReturnToDefault->setEnabled(!isDefault); |
523 | + ui->useIpQueryCheckBox->setChecked(!state); |
524 | + //The focus need to be switched to another control, otherwise |
525 | + //ui->latitudeSpinBox receives it and emits a valueChanged() signal when |
526 | + //the window is closed. |
527 | + ui->citySearchLineEdit->setFocus(); |
528 | + connectEditSignals(); |
529 | + } |
530 | } |
531 | |
532 | // Called when the user clicks on the delete button |
533 | @@ -484,6 +527,54 @@ |
534 | void LocationDialog::updateDefaultLocationControls(bool currentIsDefault) |
535 | { |
536 | ui->useAsDefaultLocationCheckBox->setChecked(currentIsDefault); |
537 | - ui->useAsDefaultLocationCheckBox->setEnabled(!currentIsDefault); |
538 | - ui->pushButtonReturnToDefault->setEnabled(!currentIsDefault); |
539 | + ui->useAsDefaultLocationCheckBox->setEnabled(!currentIsDefault); |
540 | +} |
541 | + |
542 | +// called when the user clicks on the IP Query button |
543 | +void LocationDialog::ipQueryLocation(bool state) |
544 | +{ |
545 | + if (state) |
546 | + { |
547 | + QSettings* conf = StelApp::getInstance().getSettings(); |
548 | + conf->setValue("init_location/location", "auto"); |
549 | + disconnectEditSignals(); |
550 | + resetCompleteList(); // in case we are on Moon/Mars, we must get list back to show all (earth) locations... |
551 | + StelLocationMgr &locMgr=StelApp::getInstance().getLocationMgr(); |
552 | + locMgr.locationFromIP(); // This just triggers asynchronous lookup. |
553 | + ui->useAsDefaultLocationCheckBox->setChecked(!state); |
554 | + ui->pushButtonReturnToDefault->setEnabled(!state); |
555 | + connectEditSignals(); |
556 | + ui->citySearchLineEdit->setFocus(); |
557 | + } |
558 | +} |
559 | + |
560 | +// called when user clicks "reset list" |
561 | +void LocationDialog::resetCompleteList() |
562 | +{ |
563 | + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); |
564 | + proxyModel->setSourceModel((QAbstractItemModel*)StelApp::getInstance().getLocationMgr().getModelAll()); |
565 | + proxyModel->sort(0, Qt::AscendingOrder); |
566 | + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); |
567 | + ui->citiesListView->setModel(proxyModel); |
568 | + ui->citySearchLineEdit->clear(); |
569 | + connect(ui->citySearchLineEdit, SIGNAL(textChanged(const QString&)), proxyModel, SLOT(setFilterWildcard(const QString&))); |
570 | + ui->citySearchLineEdit->setFocus(); |
571 | +} |
572 | + |
573 | +// called when user clicks in the country combobox and selects a country. The locations in the list are updated to select only sites in that country. |
574 | +void LocationDialog::filterSitesByCountry() |
575 | +{ |
576 | + QString country=ui->countryNameComboBox->currentData().toString(); |
577 | + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel(this); |
578 | + StelLocationMgr &locMgr=StelApp::getInstance().getLocationMgr(); |
579 | + |
580 | + locMgr.pickLocationsInCountry(country); |
581 | + proxyModel->setSourceModel((QAbstractItemModel*)locMgr.getModelPicked()); |
582 | + |
583 | + proxyModel->sort(0, Qt::AscendingOrder); |
584 | + proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); |
585 | + ui->citiesListView->setModel(proxyModel); |
586 | + ui->citySearchLineEdit->clear(); |
587 | + connect(ui->citySearchLineEdit, SIGNAL(textChanged(const QString&)), proxyModel, SLOT(setFilterWildcard(const QString&))); |
588 | + ui->citySearchLineEdit->setFocus(); |
589 | } |
590 | |
591 | === modified file 'src/gui/LocationDialog.hpp' |
592 | --- src/gui/LocationDialog.hpp 2013-10-14 09:27:54 +0000 |
593 | +++ src/gui/LocationDialog.hpp 2014-08-08 12:24:49 +0000 |
594 | @@ -82,6 +82,7 @@ |
595 | void updateFromProgram(const StelLocation& location); |
596 | |
597 | //! Called when the map is clicked. |
598 | + //! GZ_New: create new list for places nearby and feed into location list box. |
599 | void setPositionFromMap(double longitude, double latitude); |
600 | |
601 | //! Called when the user activates an item from the locations list. |
602 | @@ -97,9 +98,18 @@ |
603 | |
604 | //! Called when the user clicks on the delete button |
605 | void deleteCurrentLocationFromList(); |
606 | + |
607 | + //! filter city list to show entries from single country only |
608 | + void filterSitesByCountry(); |
609 | + |
610 | + //! reset city list to complete list (may have been reduced to picked list) |
611 | + void resetCompleteList(); |
612 | + |
613 | + //! called when the user wants get location from network |
614 | + void ipQueryLocation(bool state); |
615 | |
616 | //! Called when the user wants to use the current location as default |
617 | - void setDefaultLocation(); |
618 | + void setDefaultLocation(bool state); |
619 | |
620 | private: |
621 | QString lastPlanet; |
622 | |
623 | === modified file 'src/gui/StelGuiItems.cpp' |
624 | --- src/gui/StelGuiItems.cpp 2014-06-09 01:02:28 +0000 |
625 | +++ src/gui/StelGuiItems.cpp 2014-08-08 12:24:49 +0000 |
626 | @@ -579,9 +579,7 @@ |
627 | } |
628 | if (flagShowLocation && loc->name.isEmpty()) |
629 | { |
630 | - newLocation = q_(loc->planetName)+", " |
631 | - +StelUtils::radToDmsStr(loc->latitude)+", " |
632 | - +StelUtils::radToDmsStr(loc->longitude); |
633 | + newLocation = q_(loc->planetName)+", "+StelUtils::decDegToDmsStr(loc->latitude)+", "+StelUtils::decDegToDmsStr(loc->longitude); |
634 | } |
635 | if (location->text()!=newLocation) |
636 | { |
637 | @@ -593,12 +591,18 @@ |
638 | if (lat >= 0) |
639 | pm = "N"; |
640 | else |
641 | + { |
642 | pm = "S"; |
643 | + lat *= -1; |
644 | + } |
645 | latStr = QString("%1%2%3").arg(pm).arg(lat).arg(QChar(0x00B0)); |
646 | - if (lat >= 0) |
647 | + if (lon >= 0) |
648 | pm = "E"; |
649 | else |
650 | + { |
651 | pm = "W"; |
652 | + lon *= -1; |
653 | + } |
654 | lonStr = QString("%1%2%3").arg(pm).arg(lon).arg(QChar(0x00B0)); |
655 | location->setToolTip(QString("%1 %2").arg(latStr).arg(lonStr)); |
656 | } |
657 | |
658 | === modified file 'src/gui/locationDialogGui.ui' |
659 | --- src/gui/locationDialogGui.ui 2014-06-16 13:43:31 +0000 |
660 | +++ src/gui/locationDialogGui.ui 2014-08-08 12:24:49 +0000 |
661 | @@ -7,7 +7,7 @@ |
662 | <x>0</x> |
663 | <y>0</y> |
664 | <width>700</width> |
665 | - <height>452</height> |
666 | + <height>460</height> |
667 | </rect> |
668 | </property> |
669 | <property name="styleSheet"> |
670 | @@ -359,6 +359,16 @@ |
671 | </property> |
672 | </widget> |
673 | </item> |
674 | + <item> |
675 | + <widget class="QPushButton" name="resetListPushButton"> |
676 | + <property name="toolTip"> |
677 | + <string>Reset location list to show all known locations</string> |
678 | + </property> |
679 | + <property name="text"> |
680 | + <string>Reset Location List</string> |
681 | + </property> |
682 | + </widget> |
683 | + </item> |
684 | </layout> |
685 | </widget> |
686 | </item> |
687 | @@ -383,113 +393,20 @@ |
688 | <property name="bottomMargin"> |
689 | <number>0</number> |
690 | </property> |
691 | - <item row="2" column="0" colspan="3"> |
692 | - <widget class="QFrame" name="frame_3"> |
693 | - <property name="minimumSize"> |
694 | + <item row="1" column="2" colspan="2"> |
695 | + <spacer name="verticalSpacer"> |
696 | + <property name="orientation"> |
697 | + <enum>Qt::Vertical</enum> |
698 | + </property> |
699 | + <property name="sizeHint" stdset="0"> |
700 | <size> |
701 | - <width>0</width> |
702 | - <height>0</height> |
703 | + <width>20</width> |
704 | + <height>40</height> |
705 | </size> |
706 | </property> |
707 | - <property name="frameShape"> |
708 | - <enum>QFrame::StyledPanel</enum> |
709 | - </property> |
710 | - <property name="frameShadow"> |
711 | - <enum>QFrame::Raised</enum> |
712 | - </property> |
713 | - <layout class="QHBoxLayout" name="horizontalLayout"> |
714 | - <property name="leftMargin"> |
715 | - <number>0</number> |
716 | - </property> |
717 | - <property name="topMargin"> |
718 | - <number>0</number> |
719 | - </property> |
720 | - <property name="rightMargin"> |
721 | - <number>0</number> |
722 | - </property> |
723 | - <property name="bottomMargin"> |
724 | - <number>0</number> |
725 | - </property> |
726 | - <item> |
727 | - <widget class="QCheckBox" name="useAsDefaultLocationCheckBox"> |
728 | - <property name="font"> |
729 | - <font> |
730 | - <stylestrategy>PreferDefault</stylestrategy> |
731 | - </font> |
732 | - </property> |
733 | - <property name="focusPolicy"> |
734 | - <enum>Qt::NoFocus</enum> |
735 | - </property> |
736 | - <property name="text"> |
737 | - <string>Use as default</string> |
738 | - </property> |
739 | - </widget> |
740 | - </item> |
741 | - <item> |
742 | - <widget class="QPushButton" name="pushButtonReturnToDefault"> |
743 | - <property name="focusPolicy"> |
744 | - <enum>Qt::NoFocus</enum> |
745 | - </property> |
746 | - <property name="text"> |
747 | - <string>Return to default</string> |
748 | - </property> |
749 | - </widget> |
750 | - </item> |
751 | - <item> |
752 | - <spacer name="horizontalSpacer"> |
753 | - <property name="orientation"> |
754 | - <enum>Qt::Horizontal</enum> |
755 | - </property> |
756 | - <property name="sizeHint" stdset="0"> |
757 | - <size> |
758 | - <width>40</width> |
759 | - <height>20</height> |
760 | - </size> |
761 | - </property> |
762 | - </spacer> |
763 | - </item> |
764 | - <item> |
765 | - <widget class="QPushButton" name="deleteLocationFromListPushButton"> |
766 | - <property name="enabled"> |
767 | - <bool>false</bool> |
768 | - </property> |
769 | - <property name="minimumSize"> |
770 | - <size> |
771 | - <width>60</width> |
772 | - <height>0</height> |
773 | - </size> |
774 | - </property> |
775 | - <property name="focusPolicy"> |
776 | - <enum>Qt::NoFocus</enum> |
777 | - </property> |
778 | - <property name="text"> |
779 | - <string>Delete</string> |
780 | - </property> |
781 | - </widget> |
782 | - </item> |
783 | - <item> |
784 | - <widget class="QPushButton" name="addLocationToListPushButton"> |
785 | - <property name="enabled"> |
786 | - <bool>false</bool> |
787 | - </property> |
788 | - <property name="minimumSize"> |
789 | - <size> |
790 | - <width>100</width> |
791 | - <height>0</height> |
792 | - </size> |
793 | - </property> |
794 | - <property name="focusPolicy"> |
795 | - <enum>Qt::NoFocus</enum> |
796 | - </property> |
797 | - <property name="text"> |
798 | - <string>Add to list</string> |
799 | - </property> |
800 | - </widget> |
801 | - </item> |
802 | - </layout> |
803 | - </widget> |
804 | + </spacer> |
805 | </item> |
806 | - <item row="0" column="0"> |
807 | + <item row="0" column="1"> |
808 | <widget class="QFrame" name="frame_4"> |
809 | <property name="minimumSize"> |
810 | <size> |
811 | @@ -603,7 +520,114 @@ |
812 | </layout> |
813 | </widget> |
814 | </item> |
815 | + <item row="2" column="1" colspan="3"> |
816 | + <widget class="QFrame" name="frame_3"> |
817 | + <property name="minimumSize"> |
818 | + <size> |
819 | + <width>0</width> |
820 | + <height>0</height> |
821 | + </size> |
822 | + </property> |
823 | + <property name="frameShape"> |
824 | + <enum>QFrame::StyledPanel</enum> |
825 | + </property> |
826 | + <property name="frameShadow"> |
827 | + <enum>QFrame::Raised</enum> |
828 | + </property> |
829 | + <layout class="QHBoxLayout" name="horizontalLayout"> |
830 | + <property name="leftMargin"> |
831 | + <number>0</number> |
832 | + </property> |
833 | + <property name="topMargin"> |
834 | + <number>0</number> |
835 | + </property> |
836 | + <property name="rightMargin"> |
837 | + <number>0</number> |
838 | + </property> |
839 | + <property name="bottomMargin"> |
840 | + <number>0</number> |
841 | + </property> |
842 | + <item> |
843 | + <spacer name="horizontalSpacer"> |
844 | + <property name="orientation"> |
845 | + <enum>Qt::Horizontal</enum> |
846 | + </property> |
847 | + <property name="sizeHint" stdset="0"> |
848 | + <size> |
849 | + <width>40</width> |
850 | + <height>20</height> |
851 | + </size> |
852 | + </property> |
853 | + </spacer> |
854 | + </item> |
855 | + <item> |
856 | + <widget class="QPushButton" name="pushButtonReturnToDefault"> |
857 | + <property name="enabled"> |
858 | + <bool>false</bool> |
859 | + </property> |
860 | + <property name="focusPolicy"> |
861 | + <enum>Qt::NoFocus</enum> |
862 | + </property> |
863 | + <property name="text"> |
864 | + <string>Return to default location</string> |
865 | + </property> |
866 | + </widget> |
867 | + </item> |
868 | + <item> |
869 | + <widget class="QPushButton" name="deleteLocationFromListPushButton"> |
870 | + <property name="enabled"> |
871 | + <bool>false</bool> |
872 | + </property> |
873 | + <property name="minimumSize"> |
874 | + <size> |
875 | + <width>60</width> |
876 | + <height>0</height> |
877 | + </size> |
878 | + </property> |
879 | + <property name="focusPolicy"> |
880 | + <enum>Qt::NoFocus</enum> |
881 | + </property> |
882 | + <property name="text"> |
883 | + <string>Delete</string> |
884 | + </property> |
885 | + </widget> |
886 | + </item> |
887 | + <item> |
888 | + <widget class="QPushButton" name="addLocationToListPushButton"> |
889 | + <property name="enabled"> |
890 | + <bool>false</bool> |
891 | + </property> |
892 | + <property name="minimumSize"> |
893 | + <size> |
894 | + <width>100</width> |
895 | + <height>0</height> |
896 | + </size> |
897 | + </property> |
898 | + <property name="focusPolicy"> |
899 | + <enum>Qt::NoFocus</enum> |
900 | + </property> |
901 | + <property name="text"> |
902 | + <string>Add to list</string> |
903 | + </property> |
904 | + </widget> |
905 | + </item> |
906 | + </layout> |
907 | + </widget> |
908 | + </item> |
909 | <item row="0" column="2"> |
910 | + <spacer name="horizontalSpacer_2"> |
911 | + <property name="orientation"> |
912 | + <enum>Qt::Horizontal</enum> |
913 | + </property> |
914 | + <property name="sizeHint" stdset="0"> |
915 | + <size> |
916 | + <width>40</width> |
917 | + <height>20</height> |
918 | + </size> |
919 | + </property> |
920 | + </spacer> |
921 | + </item> |
922 | + <item row="0" column="3"> |
923 | <widget class="QFrame" name="frame_5"> |
924 | <property name="minimumSize"> |
925 | <size> |
926 | @@ -717,31 +741,19 @@ |
927 | </layout> |
928 | </widget> |
929 | </item> |
930 | - <item row="1" column="1" colspan="2"> |
931 | - <spacer name="verticalSpacer"> |
932 | - <property name="orientation"> |
933 | - <enum>Qt::Vertical</enum> |
934 | - </property> |
935 | - <property name="sizeHint" stdset="0"> |
936 | - <size> |
937 | - <width>20</width> |
938 | - <height>40</height> |
939 | - </size> |
940 | - </property> |
941 | - </spacer> |
942 | + <item row="3" column="1"> |
943 | + <widget class="QCheckBox" name="useAsDefaultLocationCheckBox"> |
944 | + <property name="text"> |
945 | + <string>Use current location as default</string> |
946 | + </property> |
947 | + </widget> |
948 | </item> |
949 | - <item row="0" column="1"> |
950 | - <spacer name="horizontalSpacer_2"> |
951 | - <property name="orientation"> |
952 | - <enum>Qt::Horizontal</enum> |
953 | - </property> |
954 | - <property name="sizeHint" stdset="0"> |
955 | - <size> |
956 | - <width>40</width> |
957 | - <height>20</height> |
958 | - </size> |
959 | - </property> |
960 | - </spacer> |
961 | + <item row="3" column="3"> |
962 | + <widget class="QCheckBox" name="useIpQueryCheckBox"> |
963 | + <property name="text"> |
964 | + <string>Get location from Network</string> |
965 | + </property> |
966 | + </widget> |
967 | </item> |
968 | </layout> |
969 | </widget> |
970 | |
971 | === modified file 'src/tests/testConversions.cpp' |
972 | --- src/tests/testConversions.cpp 2014-06-06 18:02:00 +0000 |
973 | +++ src/tests/testConversions.cpp 2014-08-08 12:24:49 +0000 |
974 | @@ -171,3 +171,44 @@ |
975 | QVERIFY2(std::abs(angle1-angle2)<=ERROR_LIMIT, qPrintable(QString("%1rad=%2%3d%4m%5s").arg(rad).arg(s).arg(dego).arg(mino).arg(seco))); |
976 | } |
977 | } |
978 | + |
979 | +void TestConversions::testDDToDMS() |
980 | +{ |
981 | + QVariantList data; |
982 | + |
983 | + data << 0. << 0 << 0 << 0.; |
984 | + data << 10. << 10 << 0 << 0.; |
985 | + data << -13.5 << -13 << 30 << 0.; |
986 | + data << 30.263888889 << 30 << 15 << 50.; |
987 | + data << -90.1 << -90 << 6 << 0.; |
988 | + data << 128.9999 << 128 << 59 << 59.64; |
989 | + data << 360.6 << 360 << 36 << 0.; |
990 | + data << -180.786 << -180 << 47 << 9.6; |
991 | + data << -0.01 << -0 << 0 << 36.; |
992 | + data << -0.039 << -0 << 2 << 20.4; |
993 | + |
994 | + while (data.count()>=4) |
995 | + { |
996 | + double angle, sec, seco, angle1, angle2; |
997 | + int deg, min; |
998 | + unsigned int dego, mino; |
999 | + bool sign; |
1000 | + QString s = "+"; |
1001 | + angle = data.takeFirst().toDouble(); |
1002 | + deg = data.takeFirst().toInt(); |
1003 | + min = data.takeFirst().toInt(); |
1004 | + sec = data.takeFirst().toDouble(); |
1005 | + if (angle>=0) |
1006 | + angle1 = sec+min*60+deg*3600; |
1007 | + else |
1008 | + angle1 = -1*(sec+min*60+std::abs((double)deg)*3600); |
1009 | + StelUtils::decDegToDms(angle, sign, dego, mino, seco); |
1010 | + angle2 = seco+mino*60+dego*3600; |
1011 | + if (!sign) |
1012 | + { |
1013 | + angle2 *= -1; |
1014 | + s = "-"; |
1015 | + } |
1016 | + QVERIFY2(std::abs(angle1-angle2)<=ERROR_LIMIT, qPrintable(QString("%1degrees=%2%3d%4m%5s").arg(angle).arg(s).arg(dego).arg(mino).arg(seco))); |
1017 | + } |
1018 | +} |
1019 | |
1020 | === modified file 'src/tests/testConversions.hpp' |
1021 | --- src/tests/testConversions.hpp 2014-06-07 11:39:09 +0000 |
1022 | +++ src/tests/testConversions.hpp 2014-08-08 12:24:49 +0000 |
1023 | @@ -31,6 +31,7 @@ |
1024 | void testDMSToRad(); |
1025 | void testRadToHMS(); |
1026 | void testRadToDMS(); |
1027 | + void testDDToDMS(); |
1028 | }; |
1029 | |
1030 | #endif // _TESTCONVERSIONS_HPP_ |
I checked this feature and it good work! But one moment: I think that label "IP Query" on button is not very informative and we should add tooltip and describe it.