[gnome-maps/wip/mlundblad/osm-add-location: 6/6] osmEdit: Add a context menu item for adding locations



commit c0507e1663df5aa2aeef17efa9edb6ccf39e2327
Author: Marcus Lundblad <ml update uu se>
Date:   Sun Jan 31 15:06:03 2016 +0100

    osmEdit: Add a context menu item for adding locations
    
    Launches the OSM edit dialog in add new location mode.
    Offer to zoom in if the zoom level is not one the two
    innermost ones.
    Also port the OSM account and edit/create dialogs to
    not use dialog.run().
    
    https://bugzilla.gnome.org/show_bug.cgi?id=761327

 data/org.gnome.Maps.data.gresource.xml |    1 +
 data/ui/context-menu.ui                |    7 ++++
 data/ui/zoom-in-notification.ui        |   25 ++++++++++++++
 po/POTFILES.in                         |    1 +
 src/contextMenu.js                     |   54 +++++++++++++++++++++++++++++++
 src/org.gnome.Maps.src.gresource.xml   |    1 +
 src/osmEdit.js                         |   28 +++++++++++-----
 src/placeBubble.js                     |   51 +++++++++++++++++++----------
 src/zoomInNotification.js              |   55 ++++++++++++++++++++++++++++++++
 9 files changed, 198 insertions(+), 25 deletions(-)
---
diff --git a/data/org.gnome.Maps.data.gresource.xml b/data/org.gnome.Maps.data.gresource.xml
index 7483d3d..70a43d9 100644
--- a/data/org.gnome.Maps.data.gresource.xml
+++ b/data/org.gnome.Maps.data.gresource.xml
@@ -32,6 +32,7 @@
     <file preprocess="xml-stripblanks">ui/social-place-row.ui</file>
     <file preprocess="xml-stripblanks">ui/user-location-bubble.ui</file>
     <file preprocess="xml-stripblanks">ui/zoom-control.ui</file>
+    <file preprocess="xml-stripblanks">ui/zoom-in-notification.ui</file>
     <file alias="application.css">gnome-maps.css</file>
     <file alias="ui/maptype-aerial.png">media/maptype-aerial.png</file>
     <file alias="ui/maptype-street.png">media/maptype-street.png</file>
diff --git a/data/ui/context-menu.ui b/data/ui/context-menu.ui
index eb2c7c8..90ce436 100644
--- a/data/ui/context-menu.ui
+++ b/data/ui/context-menu.ui
@@ -30,5 +30,12 @@
         <property name="visible">True</property>
       </object>
     </child>
+    <child>
+      <object class="GtkMenuItem" id="addOSMLocationItem">
+        <property name="name">add-osm-location-item</property>
+        <property name="label" translatable="yes">Add Location</property>
+        <property name="visible">True</property>
+      </object>
+    </child>
   </template>
 </interface>
diff --git a/data/ui/zoom-in-notification.ui b/data/ui/zoom-in-notification.ui
new file mode 100644
index 0000000..818302d
--- /dev/null
+++ b/data/ui/zoom-in-notification.ui
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <object class="GtkGrid" id="grid">
+    <property name="visible">True</property>
+    <property name="hexpand">False</property>
+    <property name="orientation">horizontal</property>
+    <child>
+      <object class="GtkLabel" id="label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="margin-end">30</property>
+        <property name="label" translatable="yes">You need to be zoomed-in to edit!</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkButton" id="zoomInButton">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label" translatable="yes">Zoom</property>
+        <property name="focus-on-click">False</property>
+        <property name="margin-end">5</property>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index bf77455..f945b26 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -21,6 +21,7 @@ data/org.gnome.Maps.gschema.xml
 [type: gettext/glade]data/ui/sidebar.ui
 [type: gettext/glade]data/ui/social-place-more-results-row.ui
 [type: gettext/glade]data/ui/user-location-bubble.ui
+[type: gettext/glade]data/ui/zoom-in-notification.ui
 lib/maps-file-tile-source.c
 lib/maps-osm.c
 src/application.js
diff --git a/src/contextMenu.js b/src/contextMenu.js
index 0a23522..a87434f 100644
--- a/src/contextMenu.js
+++ b/src/contextMenu.js
@@ -30,8 +30,12 @@ const Application = imports.application;
 const ExportViewDialog = imports.exportViewDialog;
 const Lang = imports.lang;
 const Location = imports.location;
+const OSMAccountDialog = imports.osmAccountDialog;
+const OSMEdit = imports.osmEdit;
+const OSMEditDialog = imports.osmEditDialog;
 const Place = imports.place;
 const Utils = imports.utils;
+const ZoomInNotification = imports.zoomInNotification;
 
 const ContextMenu = new Lang.Class({
     Name: 'ContextMenu',
@@ -40,6 +44,7 @@ const ContextMenu = new Lang.Class({
     InternalChildren: [ 'whatsHereItem',
                         'geoURIItem',
                         'exportItem',
+                        'addOSMLocationItem',
                         'routeItem' ],
 
     _init: function(params) {
@@ -57,6 +62,8 @@ const ContextMenu = new Lang.Class({
                                  this._onGeoURIActivated.bind(this));
         this._exportItem.connect('activate',
                                  this._onExportActivated.bind(this));
+        this._addOSMLocationItem.connect('activate',
+                                         this._onAddOSMLocationActivated.bind(this));
         this._routeItem.connect('activate',
                                 this._onRouteActivated.bind(this));
         Application.routeService.query.connect('notify::points',
@@ -132,6 +139,53 @@ const ContextMenu = new Lang.Class({
         clipboard.set_text(uri, uri.length);
     },
 
+    _onAddOSMLocationActivated: function() {
+        let osmEdit = Application.osmEdit;
+        /* if the user is not alread signed in, show the account dialog */
+        if (!osmEdit.isSignedIn) {
+            let dialog = osmEdit.createAccountDialog(this.get_toplevel(), true);
+
+            dialog.show();
+            dialog.connect('response', (function (response) {
+                dialog.destroy();
+                if (response === OSMAccountDialog.Response.SIGNED_IN)
+                    this._doAddOSMLocation();
+            }).bind(this));
+
+            return;
+        }
+
+        this._doAddOSMLocation();
+    },
+
+    _doAddOSMLocation: function() {
+        let osmEdit = Application.osmEdit;
+        /* if the user is not sufficently zoomed-in, show a notification
+           offering to zoom in */
+        if (this._mapView.view.get_zoom_level() < OSMEdit.MIN_ADD_LOCATION_ZOOM_LEVEL) {
+            let zoomInNotification =
+                new ZoomInNotification.ZoomInNotification({longitude: this._longitude,
+                                                           latitude: this._latitude,
+                                                           view: this._mapView.view});
+            Application.notificationManager.showNotification(zoomInNotification);
+            return;
+        }
+
+        let dialog =
+            osmEdit.createEditNewDialog(this.get_toplevel(),
+                                      this._latitude, this._longitude);
+
+        dialog.show();
+        dialog.connect('response', (function (response) {
+            dialog.destroy();
+            if (response === OSMEditDialog.Response.UPLOADED) {
+                /* show a notification on success */
+                Application.notificationManager.showMessage(
+                    _("Location was added to the map, note that it may take a while before it shows on the 
map and in search results."));
+            }
+        }).bind(this));
+    },
+
     _activateExport: function() {
         let view = this._mapView.view;
         let surface = view.to_surface(true);
diff --git a/src/org.gnome.Maps.src.gresource.xml b/src/org.gnome.Maps.src.gresource.xml
index ec88b7f..9545af1 100644
--- a/src/org.gnome.Maps.src.gresource.xml
+++ b/src/org.gnome.Maps.src.gresource.xml
@@ -70,6 +70,7 @@
     <file>userLocationMarker.js</file>
     <file>utils.js</file>
     <file>zoomControl.js</file>
+    <file>zoomInNotification.js</file>
     <file alias="geojsonvt/clip.js">clip.js</file>
     <file alias="geojsonvt/convert.js">convert.js</file>
     <file alias="geojsonvt/geojsonvt.js">index.js</file>
diff --git a/src/osmEdit.js b/src/osmEdit.js
index 62f15d5..741cb09 100644
--- a/src/osmEdit.js
+++ b/src/osmEdit.js
@@ -29,6 +29,9 @@ const OSMEditDialog = imports.osmEditDialog;
 const OSMConnection = imports.osmConnection;
 const Utils = imports.utils;
 
+/* minimum zoom level at which to offer adding a location */
+const MIN_ADD_LOCATION_ZOOM_LEVEL = 16;
+
 const OSMEdit = new Lang.Class({
     Name: 'OSMEdit',
     Extends: GObject.Object,
@@ -44,24 +47,33 @@ const OSMEdit = new Lang.Class({
         return this._osmObject;
     },
 
-    showEditDialog: function(parentWindow, place) {
+    createEditDialog: function(parentWindow, place) {
         let dialog = new OSMEditDialog.OSMEditDialog({
             transient_for: parentWindow,
             place: place
         });
-        let response = dialog.run();
-        dialog.destroy();
-        return response;
+
+        return dialog;
     },
 
-    showAccountDialog: function(parentWindow, closeOnSignIn) {
+    createEditNewDialog: function(parentWindow, latitude, longitude) {
+        let dialog = new OSMEditDialog.OSMEditDialog({
+            transient_for: parentWindow,
+            addLocation: true,
+            latitude: latitude,
+            longitude: longitude
+        });
+
+        return dialog;
+    },
+
+    createAccountDialog: function(parentWindow, closeOnSignIn) {
         let dialog = new OSMAccountDialog.OSMAccountDialog({
             transient_for: parentWindow,
             closeOnSignIn: closeOnSignIn
         });
-        let response = dialog.run();
-        dialog.destroy();
-        return response;
+
+        return dialog;
     },
 
     fetchObject: function(place, callback, cancellable) {
diff --git a/src/placeBubble.js b/src/placeBubble.js
index f1f0ec4..1d0f820 100644
--- a/src/placeBubble.js
+++ b/src/placeBubble.js
@@ -204,24 +204,41 @@ const PlaceBubble = new Lang.Class({
         let osmEdit = Application.osmEdit;
         /* if the user is not alread signed in, show the account dialog */
         if (!osmEdit.isSignedIn) {
-            let response = osmEdit.showAccountDialog(this.get_toplevel(), true);
-            if (response !== OSMAccountDialog.Response.SIGNED_IN)
-                return;
-        }
+            let dialog = osmEdit.createAccountDialog(this.get_toplevel(), true);
+
+            dialog.show();
+            dialog.connect('response', (function (response) {
+                dialog.destroy();
+                if (response === OSMAccountDialog.Response.SIGNED_IN)
+                    this._doEdit();
+            }).bind(this));
 
-        let response = osmEdit.showEditDialog(this.get_toplevel(), this._place);
-
-        switch (response) {
-        case OSMEditDialog.Response.UPLOADED:
-            // update place
-            let object = osmEdit.object;
-            OSMUtils.updatePlaceFromOSMObject(this._place, object);
-            // refresh place view
-            this._clearView();
-            this._populate(this._place);
-            break;
-        default:
-            break;
+            return;
         }
+
+        this._doEdit();
+    },
+
+    _doEdit: function() {
+        let osmEdit = Application.osmEdit;
+        let dialog = osmEdit.createEditDialog(this.get_toplevel(), this._place);
+
+        dialog.show();
+        dialog.connect('response', (function (response) {
+            dialog.destroy();
+
+            switch (response) {
+            case OSMEditDialog.Response.UPLOADED:
+                // update place
+                let object = osmEdit.object;
+                OSMUtils.updatePlaceFromOSMObject(this._place, object);
+                // refresh place view
+                this._clearView();
+                this._populate(this._place);
+                break;
+            default:
+                break;
+            }
+        }).bind(this));
     }
 });
diff --git a/src/zoomInNotification.js b/src/zoomInNotification.js
new file mode 100644
index 0000000..41894b4
--- /dev/null
+++ b/src/zoomInNotification.js
@@ -0,0 +1,55 @@
+/* -*- Mode: JS2; indent-tabs-mode: nil; js2-basic-offset: 4 -*- */
+/* vim: set et ts=4 sw=4: */
+/*
+ * Copyright (c) 2016 Marcus Lundblad.
+ *
+ * GNOME Maps is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * GNOME Maps 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 General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with GNOME Maps; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marcus Lundblad <ml update uu se>
+ */
+
+const Lang = imports.lang;
+
+const Application = imports.application;
+const Notification = imports.notification;
+const OSMEdit = imports.osmEdit;
+const Utils = imports.utils;
+
+const ZoomInNotification = Lang.Class({
+    Name: 'ZoomInNotification',
+    Extends: Notification.Notification,
+    InternalChildren: ['zoomInButton'],
+
+    _init: function(props) {
+        this._latitude = props.latitude;
+        this._longitude = props.longitude;
+        this._view = props.view;
+        this.parent();
+
+        let ui = Utils.getUIObject('zoom-in-notification', [ 'grid',
+                                                             'zoomInButton' ]);
+
+        ui.zoomInButton.connect('clicked', this._onZoomIn.bind(this));
+        this._ui.body.add(ui.grid);
+    },
+
+    _onZoomIn: function() {
+        this._view.zoom_level = OSMEdit.MIN_ADD_LOCATION_ZOOM_LEVEL;
+
+        /* center on the position first selected */
+        this._view.center_on(this._latitude, this._longitude);
+        this.dismiss();
+    }
+})
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]