Bug 358779 - dgml is missing an option center the map (lonlat) [patch]
Summary: dgml is missing an option center the map (lonlat) [patch]
Status: RESOLVED FIXED
Alias: None
Product: marble
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: unspecified All
: NOR wishlist
Target Milestone: ---
Assignee: marble-bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-01-30 16:36 UTC by boris.sh.1983+kde.bugzilla
Modified: 2023-04-25 17:43 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
[PATCH] lonlat from dgml (13.42 KB, patch)
2016-01-30 16:40 UTC, boris.sh.1983+kde.bugzilla
Details

Note You need to log in before you can comment on or make changes to this bug.
Description boris.sh.1983+kde.bugzilla 2016-01-30 16:36:22 UTC
Some custom map providers will not provide a maps for the entire world , but rather to a small area.

While there is a command line option to start marble to point to a location , it is not a feasible solution when requesting a non technical person to start with command line options (In addition to the need for asking a person to put files a directory)



Reproducible: Always

Steps to Reproduce:
1. take a dgml with a custom server that does not support world wide tiles
2. choose dgml in marble


Actual Results:  
no easy way to set the center location in the dgml.

Expected Results:  
an option to set center location in the dgml file.

From 79afd8a250b40ae76de950708a991c07b8a58853 Mon Sep 17 00:00:00 2001
From: boris <boris@bugs.local>
Date: Sat, 30 Jan 2016 13:17:09 +0200
Subject: [PATCH] lonlat from dgml

When loading a dgml file , a feature needed to center the map on a specific location.
usecase :
big boss need to see a map that will start on a custom tile server (which only show the city).
it is hard enough for an IT/dev person to ask him to download and unpack a theme file,
  asking him to run something from command line is asking for trouble.
---
 src/apps/marble-kde/KdeMainWindow.cpp              | 18 ++++++++
 src/apps/marble-kde/KdeMainWindow.h                |  1 +
 src/apps/marble-qt/QtMainWindow.cpp                | 22 +++++++++-
 src/apps/marble-qt/QtMainWindow.h                  |  1 +
 src/lib/marble/geodata/CMakeLists.txt              |  2 +
 .../geodata/handlers/dgml/DgmlCenterTagHandler.cpp | 48 ++++++++++++++++++++++
 .../geodata/handlers/dgml/DgmlCenterTagHandler.h   | 41 ++++++++++++++++++
 .../handlers/dgml/DgmlElementDictionary.cpp        |  1 +
 .../geodata/handlers/dgml/DgmlElementDictionary.h  |  1 +
 src/lib/marble/geodata/scene/GeoSceneMap.cpp       | 22 ++++++++++
 src/lib/marble/geodata/scene/GeoSceneMap.h         | 13 +++++-
 11 files changed, 168 insertions(+), 2 deletions(-)
 create mode 100644 src/lib/marble/geodata/handlers/dgml/DgmlCenterTagHandler.cpp
 create mode 100644 src/lib/marble/geodata/handlers/dgml/DgmlCenterTagHandler.h

diff --git a/src/apps/marble-kde/KdeMainWindow.cpp b/src/apps/marble-kde/KdeMainWindow.cpp
index c4fd3b1..932acf8 100644
--- a/src/apps/marble-kde/KdeMainWindow.cpp
+++ b/src/apps/marble-kde/KdeMainWindow.cpp
@@ -71,6 +71,9 @@ MainWindow::MainWindow( const QString& marbleDataPath, QWidget *parent )
 
     connect( marbleWidget(), SIGNAL(themeChanged(QString)),
             this, SLOT(setMapTitle()));
+    connect( marbleWidget(), SIGNAL(themeChanged(QString)),
+            this, SLOT(updateCenterFromTheme()));
+
 }
 
 MainWindow::~MainWindow()
@@ -97,6 +100,21 @@ void MainWindow::setMapTitle()
     }
 }
 
+void MainWindow::updateCenterFromTheme()
+{
+   //A scene provider may provide only a subset of the globe, use scene properties read from a dgml as a starting point
+   GeoSceneDocument * theme = m_controlView->marbleModel()->mapTheme(); 
+   if (theme) {
+       const GeoSceneMap* map =   theme->map();
+       if (map) {
+           const QVariantList lonLat = map->center();
+           if (! lonLat.empty()) {
+                m_controlView->marbleWidget()->centerOn( lonLat.at(0).toDouble(), lonLat.at(1).toDouble() );
+           }
+       }
+   }
+}
+
 void MainWindow::changeViewSize( QAction* action )
 {
     mDebug()<<size();
diff --git a/src/apps/marble-kde/KdeMainWindow.h b/src/apps/marble-kde/KdeMainWindow.h
index b961c6f..f0e45ac 100644
--- a/src/apps/marble-kde/KdeMainWindow.h
+++ b/src/apps/marble-kde/KdeMainWindow.h
@@ -41,6 +41,7 @@ class MainWindow : public KXmlGuiWindow
  public slots:
     void setMapTitle();
     void changeViewSize( QAction* );
+    void updateCenterFromTheme();
 
  protected:
     void closeEvent( QCloseEvent *event );
diff --git a/src/apps/marble-qt/QtMainWindow.cpp b/src/apps/marble-qt/QtMainWindow.cpp
index a0491a3..1535afc 100644
--- a/src/apps/marble-qt/QtMainWindow.cpp
+++ b/src/apps/marble-qt/QtMainWindow.cpp
@@ -65,6 +65,8 @@
 #include "NewBookmarkFolderDialog.h"
 #include "GeoSceneDocument.h"
 #include "GeoSceneHead.h"
+#include "GeoSceneMap.h"
+
 #include "GeoDataCoordinates.h"
 #include "GeoDataDocument.h"
 #include "GeoDataFolder.h"
@@ -219,6 +221,9 @@ MainWindow::MainWindow(const QString& marbleDataPath, const QVariantMap& cmdLine
              this, SLOT(updateMapEditButtonVisibility(QString)) );
     connect(m_controlView->marbleModel(), SIGNAL(themeChanged(QString)),
             this, SLOT(updateApplicationTitle(QString)));
+    connect(m_controlView->marbleModel(), SIGNAL(themeChanged(QString)),
+            this, SLOT(updateCenterFromTheme()));
+
     connect( m_controlView, SIGNAL(showMapWizard()), this, SLOT(showMapWizard()) );
     connect( m_controlView, SIGNAL(mapThemeDeleted()), this, SLOT(fallBackToDefaultTheme()) );
 
@@ -1626,6 +1631,22 @@ void MainWindow::updateApplicationTitle(const QString&)
     }
 }
 
+void MainWindow::updateCenterFromTheme()
+{
+   //A scene provider may provide only a subset of the globe, use scene properties read from a dgml as a starting point
+   GeoSceneDocument * theme = m_controlView->marbleModel()->mapTheme(); 
+   if (theme) {
+       const GeoSceneMap* map =   theme->map();
+       if (map) {
+           const QVariantList lonLat = map->center();
+           if (! lonLat.empty()) {
+                qDebug() << __FUNCTION__ << " lonlat:" << QString::number(lonLat.at(0).toDouble()) << "," << QString::number(lonLat.at(1).toDouble()) ;
+                m_controlView->marbleWidget()->centerOn( lonLat.at(0).toDouble(), lonLat.at(1).toDouble() );
+           }
+      }
+   }
+}
+
 void MainWindow::showMapWizard()
 {
     QPointer<MapWizard> mapWizard = new MapWizard();
@@ -1686,5 +1707,4 @@ void MainWindow::changeViewSize( QAction* action )
         m_savedSize.setHeight( -1 );
     }
 }
-
 #include "moc_QtMainWindow.cpp"
diff --git a/src/apps/marble-qt/QtMainWindow.h b/src/apps/marble-qt/QtMainWindow.h
index ff82641..430edb8 100644
--- a/src/apps/marble-qt/QtMainWindow.h
+++ b/src/apps/marble-qt/QtMainWindow.h
@@ -85,6 +85,7 @@ private Q_SLOTS:
     void  changeRecordingState();
 
     void  updateApplicationTitle(const QString&);
+    void  updateCenterFromTheme();
 
     // File Menu
     void  openFile();
diff --git a/src/lib/marble/geodata/CMakeLists.txt b/src/lib/marble/geodata/CMakeLists.txt
index fe0a919..20e73a1 100644
--- a/src/lib/marble/geodata/CMakeLists.txt
+++ b/src/lib/marble/geodata/CMakeLists.txt
@@ -143,6 +143,7 @@ SET ( geodata_handlers_dgml_SRCS
         geodata/handlers/dgml/DgmlThemeTagHandler.h
         geodata/handlers/dgml/DgmlSettingsTagHandler.h
         geodata/handlers/dgml/DgmlDescriptionTagHandler.h
+       geodata/handlers/dgml/DgmlCenterTagHandler.h
         geodata/handlers/dgml/DgmlBrushTagHandler.cpp
         geodata/handlers/dgml/DgmlSectionTagHandler.h
         geodata/handlers/dgml/DgmlTextureTagHandler.h
@@ -162,6 +163,7 @@ SET ( geodata_handlers_dgml_SRCS
         geodata/handlers/dgml/DgmlTileSizeTagHandler.cpp
         geodata/handlers/dgml/DgmlTextureTagHandler.cpp
         geodata/handlers/dgml/DgmlPenTagHandler.cpp
+        geodata/handlers/dgml/DgmlCenterTagHandler.cpp
         geodata/handlers/dgml/DgmlDescriptionTagHandler.cpp
         geodata/handlers/dgml/DgmlElementDictionary.h
         geodata/handlers/dgml/DgmlIconTagHandler.cpp
diff --git a/src/lib/marble/geodata/handlers/dgml/DgmlCenterTagHandler.cpp b/src/lib/marble/geodata/handlers/dgml/DgmlCenterTagHandler.cpp
new file mode 100644
index 0000000..8289709
--- /dev/null
+++ b/src/lib/marble/geodata/handlers/dgml/DgmlCenterTagHandler.cpp
@@ -0,0 +1,48 @@
+/*
+    Copyright (C) 2015 Boris Shtrasman
+
+    This file is part of the KDE project
+
+    This library is free software you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    aint with this library see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "DgmlCenterTagHandler.h"
+
+#include "DgmlElementDictionary.h"
+#include "GeoParser.h"
+#include "GeoSceneMap.h"
+
+namespace Marble
+{
+namespace dgml
+{
+DGML_DEFINE_TAG_HANDLER(Center)
+
+GeoNode* DgmlCenterTagHandler::parse(GeoParser& parser) const
+{
+    // Check whether the tag is valid
+    Q_ASSERT(parser.isStartElement() && parser.isValidElement(dgmlTag_Center));
+
+    // Checking for parent item
+    GeoStackItem parentItem = parser.parentElement();
+    if (parentItem.represents(dgmlTag_Map))
+        parentItem.nodeAs<GeoSceneMap>()->setCenter( parser.readElementText().trimmed() );
+
+    return 0;
+}
+
+}
+}
diff --git a/src/lib/marble/geodata/handlers/dgml/DgmlCenterTagHandler.h b/src/lib/marble/geodata/handlers/dgml/DgmlCenterTagHandler.h
new file mode 100644
index 0000000..1605a74
--- /dev/null
+++ b/src/lib/marble/geodata/handlers/dgml/DgmlCenterTagHandler.h
@@ -0,0 +1,41 @@
+/*
+    Copyright (C) 2015 Boris Shtrasman
+
+    This file is part of the KDE project
+
+    This library is free software you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    aint with this library see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef MARBLE_DGML_CENTERTAGHANDLER_H
+#define MARBLE_DGML_CENTERTAGHANDLER_H
+
+#include "GeoTagHandler.h"
+
+namespace Marble
+{
+namespace dgml
+{
+
+class DgmlCenterTagHandler : public GeoTagHandler
+{
+public:
+    virtual GeoNode* parse(GeoParser&) const;
+};
+
+}
+}
+
+#endif
diff --git a/src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.cpp b/src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.cpp
index 96d26e3..0a83b71 100644
--- a/src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.cpp
+++ b/src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.cpp
@@ -34,6 +34,7 @@ const char* dgmlTag_Available = "available";
 const char* dgmlTag_Blending = "blending";
 const char* dgmlTag_Brush = "brush";
 const char* dgmlTag_Color = "color";
+const char* dgmlTag_Center = "center";
 const char* dgmlTag_CustomPlugin = "customplugin";
 const char* dgmlTag_Dem = "dem";
 const char* dgmlTag_Description = "description";
diff --git a/src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.h b/src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.h
index b08c3c3..1fedaf1 100644
--- a/src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.h
+++ b/src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.h
@@ -36,6 +36,7 @@ namespace dgml
     extern  const char* dgmlTag_Available;
     extern  const char* dgmlTag_Blending;
     extern  const char* dgmlTag_Brush;
+    extern  const char* dgmlTag_Center;
     extern  const char* dgmlTag_Color;
     extern  const char* dgmlTag_CustomPlugin;
     extern  const char* dgmlTag_Dem;
diff --git a/src/lib/marble/geodata/scene/GeoSceneMap.cpp b/src/lib/marble/geodata/scene/GeoSceneMap.cpp
index 9b4966e..7c49508 100644
--- a/src/lib/marble/geodata/scene/GeoSceneMap.cpp
+++ b/src/lib/marble/geodata/scene/GeoSceneMap.cpp
@@ -26,6 +26,8 @@
 #include "GeoSceneFilter.h"
 #include "DgmlAuxillaryDictionary.h"
 
+#include <GeoDataCoordinates.h>
+
 namespace Marble
 {
 
@@ -50,6 +52,8 @@ class GeoSceneMapPrivate
         return GeoSceneTypes::GeoSceneMapType;
     }
 
+    QVariantList  m_center;
+
     /// The vector holding all the sections in the legend.
     /// (We want to preserve the order and don't care 
     /// much about speed here), so we don't use a hash
@@ -166,6 +170,24 @@ void GeoSceneMap::addFilter( GeoSceneFilter* filter )
     }
 }
 
+QVariantList GeoSceneMap::center() const
+{
+  return d->m_center;
+}
+
+void GeoSceneMap::setCenter(const QString & coordinatesString)
+{
+  bool success = false;
+  const GeoDataCoordinates coordinates = GeoDataCoordinates::fromString(coordinatesString, success);
+
+  if ( success ) {
+      QVariantList lonLat;
+      lonLat << QVariant( coordinates.longitude(GeoDataCoordinates::Degree) )
+             << QVariant( coordinates.latitude(GeoDataCoordinates::Degree) );
+      d->m_center = lonLat;
+  }
+}
+
 GeoSceneFilter* GeoSceneMap::filter( const QString& name )
 {
     GeoSceneFilter* filter = 0;
diff --git a/src/lib/marble/geodata/scene/GeoSceneMap.h b/src/lib/marble/geodata/scene/GeoSceneMap.h
index 42db5b4..f01b387 100644
--- a/src/lib/marble/geodata/scene/GeoSceneMap.h
+++ b/src/lib/marble/geodata/scene/GeoSceneMap.h
@@ -25,6 +25,7 @@
 #include <QColor>
 #include <QString>
 #include <QVector>
+#include <QVariant>
 
 #include <geodata_export.h>
 
@@ -64,7 +65,17 @@ class GEODATA_EXPORT GeoSceneMap : public GeoNode
      * @param  section  The new layer
      */
     void addLayer( GeoSceneLayer* );
-
+    /**
+     * @ brief Set starting center with lon lat cooredinates
+     * used if a scene downloadUrl do not handle elements in other locations
+     */
+    void setCenter(const QString & coordinateString);
+    /**
+     * @breif Get starting center with cooredinates
+     * used if a scene downloadUrl do not handle elements in other locations
+     * return A QVariantList of lon lat as specified in the dgml
+     */
+    QVariantList center() const;
     /**
      * @brief  Return a layer by its name
      * @param  name  The name of the layer
-- 
2.7.0
Comment 1 boris.sh.1983+kde.bugzilla 2016-01-30 16:40:44 UTC
Created attachment 96928 [details]
[PATCH] lonlat from dgml
Comment 2 Torsten Rahn 2023-04-21 21:17:16 UTC
Sorry, this nice patch got completely "drowned" and remained undiscovered in our bug database. A better place for submission would have been Gitlab at https://invent.kde.org/education/marble/-/merge_requests

Thanks for the contribution - this is indeed a feature that I had planned since long to get implemented.
I will review this and will add this (likely with modifications) to our codebase.

Thanks a lot!
Comment 3 Torsten Rahn 2023-04-22 13:02:07 UTC
My need for this patch arises from the usecase of creating WMS-based dgml-themes. Many WMS services just cover a particular geodetic bounding box (and many are only meant as an overlay to be used for "groundlayers").

Now there are two issues in this context which I currently consider:
- Ideally instead of "centerOn" I'd like to rather see "setViewLatLon(Alt)Box()" which would also steer the zoomlevel to ensure that a particular region gets centered and fully displayed. The case where the map should only be centered could be accomplished by using the same API with a boundingbox that has no size (and is a point).
- In the implementation of the patch the centering is done whenever the map theme changes if the map theme specifies a center-point. I'm not sure whether this is a good approach. During application startup we have the option to either center on the "home position" or to recall zoom level and center point last time when Marble was quit. Also we usually don't change the view when a map theme is changed.

I see several other usecases where one might want a different behavior:
- The centerOn/setViewLatLonAltBox would only get applied the first time the map theme gets invoked (however that is impossible to detect at the moment).
- The centerOn/setViewLatLonAltBox would only get applied if the current point that Marble focuses on is not in the valid boundingbox specified for the map theme.  
- Or as this patch does we always enforce centerOn/setViewLatLonAltBox whenever the map theme is invoked. Of course we could add an option that would override this behavior (globally or restricted to this map theme) but that would make things increasingly complex.

Tough choice :-)
Comment 4 Torsten Rahn 2023-04-22 13:32:18 UTC
Another finding: Marble already has

void MarbleAbstractPresenter::centerOn(const GeoDataLatLonBox &box, bool animated)

implemented which is available in MarbleWidget and which tries to approximate the setViewLatLon(Alt)Box() behavior mentioned before.
The implementation of this method is not ideal (see https://bugs.kde.org/show_bug.cgi?id=461569) but should work well enough for a start.
Comment 5 Torsten Rahn 2023-04-24 11:55:45 UTC
Git commit a4aa19db604e1c233982b20e1ab886df76839094 by Torsten Rahn.
Committed on 24/04/2023 at 11:55.
Pushed by rahn into branch 'master'.

Patch by Boris Shhtrasman:
- dgml is missing an option center the map (lonlat)

In order to integrate this with MapWizard's WMS support I changed the
behavior by
- centering on the geodetic boundingbox instead of a geodetic point
- only center when the map theme is changed if the current view points
  outside the boundingbox of the map theme.

M  +35   -0    src/apps/marble-kde/KdeMainWindow.cpp
M  +1    -0    src/apps/marble-kde/KdeMainWindow.h
M  +35   -1    src/apps/marble-qt/QtMainWindow.cpp
M  +1    -0    src/apps/marble-qt/QtMainWindow.h
M  +12   -0    src/lib/marble/MapWizard.cpp
M  +36   -0    src/lib/marble/OwsServiceManager.cpp
M  +1    -0    src/lib/marble/OwsServiceManager.h
M  +2    -0    src/lib/marble/geodata/CMakeLists.txt
M  +1    -1    src/lib/marble/geodata/data/GeoDataCoordinates.h
M  +1    -0    src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.cpp
M  +1    -0    src/lib/marble/geodata/handlers/dgml/DgmlElementDictionary.h
M  +31   -0    src/lib/marble/geodata/scene/GeoSceneMap.cpp
M  +12   -1    src/lib/marble/geodata/scene/GeoSceneMap.h
M  +16   -1    src/lib/marble/geodata/writers/dgml/DgmlMapTagWriter.cpp

https://invent.kde.org/education/marble/commit/a4aa19db604e1c233982b20e1ab886df76839094
Comment 6 Torsten Rahn 2023-04-25 17:38:53 UTC
Hello Boris,

sorry, but for the lack of your realname I had looked up your name on the Internet and copied your name over from https://kdepim-bugs.kde.narkive.com/9IhS4B3v/akonadi-bug-339393-new-akonadi-fail-to-fetch-imap-folder-content-with-over-100mib-of-messages where this typo was unfortunately included.

Again sorry, and also sorry that this took so long. I had been basically on parental leave during the last few years (with a great wife and two marbleous kids).

Your patch has made the WMS improvements that I'm looking into a whole lot more enjoyable. Thanks for that! :-)
Comment 7 borissh1983 2023-04-25 17:43:48 UTC
Thank you a lot, sorry for that link as well. I need to see how that had happened in the first place :)

On Tuesday, 25 April 2023 20:38:53 IDT Torsten Rahn wrote:
> https://bugs.kde.org/show_bug.cgi?id=358779
> 
> --- Comment #6 from Torsten Rahn <rahn@kde.org> ---
> Hello Boris,
> 
> sorry, but for the lack of your realname I had looked up your name on the
> Internet and copied your name over from
> https://kdepim-bugs.kde.narkive.com/9IhS4B3v/akonadi-bug-339393-new-akonadi-fail-to-fetch-imap-folder-content-with-over-100mib-of-messages
> where this typo was unfortunately included.
> 
> Again sorry, and also sorry that this took so long. I had been basically on
> parental leave during the last few years (with a great wife and two marbleous
> kids).
> 
> Your patch has made the WMS improvements that I'm looking into a whole lot more
> enjoyable. Thanks for that! :-)
> 
>