[gnome-maps/wip/mlundblad/gtk4-and-shumate] WIP: Port to GTK 4 and Shumate




commit 7f685df1c727491c7a7982bce68681b4a4bcff4e
Author: Marcus Lundblad <ml update uu se>
Date:   Fri Jul 3 00:10:01 2020 +0200

    WIP: Port to GTK 4 and Shumate

 data/ui/context-menu.ui          |   4 +-
 data/ui/favorites-popover.ui     |  10 +-
 data/ui/headerbar-left.ui        |  20 +--
 data/ui/headerbar-right.ui       |  23 +--
 data/ui/layers-popover.ui        |  88 ++++------
 data/ui/main-window.ui           |  26 +--
 data/ui/place-popover.ui         |   4 +-
 data/ui/route-entry.ui           |  19 +--
 data/ui/sidebar.ui               | 340 +++++++++++++++++----------------------
 data/ui/transit-options-panel.ui |  91 +++++------
 src/application.js               |  13 +-
 src/contextMenu.js               |  23 +--
 src/favoritesPopover.js          |   4 +-
 src/layersPopover.js             |   9 +-
 src/main.js                      |  10 +-
 src/mainWindow.js                |  19 ++-
 src/mapBubble.js                 |   3 +-
 src/mapSource.js                 |  33 ++--
 src/mapView.js                   | 176 ++++++++------------
 src/osmAccountDialog.js          |   3 +-
 src/photonParser.js              |   3 +-
 src/placeEntry.js                |  28 +++-
 src/placePopover.js              |   7 +-
 src/routeEntry.js                |   1 -
 src/routeQuery.js                |   9 +-
 src/searchPopover.js             |  20 ++-
 src/sendToDialog.js              |   3 +-
 src/sidebar.js                   |  14 +-
 src/transitOptionsPanel.js       |  16 +-
 src/utils.js                     |   9 +-
 30 files changed, 471 insertions(+), 557 deletions(-)
---
diff --git a/data/ui/context-menu.ui b/data/ui/context-menu.ui
index 7fcb6734..914b033c 100644
--- a/data/ui/context-menu.ui
+++ b/data/ui/context-menu.ui
@@ -1,8 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
-  <template class="Gjs_ContextMenu" parent="GtkMenu">
+  <template class="Gjs_ContextMenu" parent="GtkPopoverMenu">
     <property name="visible">False</property>
+    <!-- TODO: build from menu model...
     <child>
       <object class="GtkMenuItem" id="routeFromHereItem">
         <property name="name">route-from-here-item</property>
@@ -52,5 +53,6 @@
         <property name="visible">True</property>
       </object>
     </child>
+    -->
   </template>
 </interface>
diff --git a/data/ui/favorites-popover.ui b/data/ui/favorites-popover.ui
index 7ee1bbb6..53a6b282 100644
--- a/data/ui/favorites-popover.ui
+++ b/data/ui/favorites-popover.ui
@@ -3,7 +3,6 @@
   <!-- interface-requires gtk+ 3.10 -->
   <template class="Gjs_FavoritesPopover" parent="GtkPopover">
     <property name="visible">False</property>
-    <property name="no_show_all">True</property>
     <property name="hexpand">False</property>
     <property name="width-request">320</property>
     <style>
@@ -15,7 +14,10 @@
         <property name="can_focus">False</property>
         <property name="orientation">vertical</property>
         <property name="row_spacing">6</property>
-        <property name="margin">6</property>
+        <property name="margin-start">6</property>
+        <property name="margin-end">6</property>
+        <property name="margin-top">6</property>
+        <property name="margin-bottom">6</property>
         <child>
           <object class="GtkEntry" id="entry">
             <property name="visible">True</property>
@@ -25,14 +27,14 @@
         <child>
           <object class="GtkScrolledWindow" id="scrolledWindow">
             <property name="hscrollbar_policy">never</property>
-            <property name="shadow_type">in</property>
+            <property name="has-frame">True</property>
             <property name="visible">True</property>
             <property name="vexpand">True</property>
             <child>
               <object class="GtkListBox" id="list">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="expand">True</property>
+                <property name="vexpand">True</property>
                 <property name="activate_on_single_click">True</property>
               </object>
             </child>
diff --git a/data/ui/headerbar-left.ui b/data/ui/headerbar-left.ui
index f64b250f..b8107990 100644
--- a/data/ui/headerbar-left.ui
+++ b/data/ui/headerbar-left.ui
@@ -1,15 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.0 -->
 <interface>
   <requires lib="gtk+" version="3.22"/>
   <template class="Gjs_HeaderBarLeft" parent="GtkBox">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
+    <property name="can_focus">0</property>
     <property name="spacing">6</property>
     <child>
       <object class="GtkButton" id="gotoUserLocationButton">
-        <property name="visible">True</property>
-        <property name="can-focus">True</property>
         <property name="valign">center</property>
         <property name="action-name">win.goto-user-location</property>
         <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Go to 
current location</property>
@@ -18,20 +14,14 @@
         </style>
         <child>
           <object class="GtkImage" id="track-user-button-image">
-            <property name="visible">True</property>
             <property name="icon-size">1</property>
             <property name="icon-name">find-location-symbolic</property>
           </object>
         </child>
       </object>
-      <packing>
-        <property name="pack-type">start</property>
-      </packing>
     </child>
     <child>
       <object class="GtkMenuButton" id="layersButton">
-        <property name="visible">True</property>
-        <property name="can-focus">True</property>
         <property name="valign">center</property>
         <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Choose 
map type</property>
         <style>
@@ -39,7 +29,6 @@
         </style>
         <child>
           <object class="GtkImage" id="layers-button-image">
-            <property name="visible">True</property>
             <property name="icon-size">1</property>
             <property name="icon-name">layers-button-symbolic</property>
           </object>
@@ -48,20 +37,16 @@
     </child>
     <child>
       <object class="GtkBox">
-        <property name="visible">True</property>
         <style>
           <class name="linked"/>
         </style>
         <child>
           <object class="GtkButton">
-            <property name="visible">True</property>
-            <property name="can-focus">True</property>
             <property name="valign">center</property>
             <property name="action-name">win.zoom-out</property>
             <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Zoom 
out</property>
             <child>
               <object class="GtkImage">
-                <property name="visible">True</property>
                 <property name="icon-size">1</property>
                 <property name="icon-name">zoom-out-symbolic</property>
               </object>
@@ -70,14 +55,11 @@
         </child>
         <child>
           <object class="GtkButton">
-            <property name="visible">True</property>
-            <property name="can-focus">True</property>
             <property name="valign">center</property>
             <property name="action-name">win.zoom-in</property>
             <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Zoom 
in</property>
             <child>
               <object class="GtkImage">
-                <property name="visible">True</property>
                 <property name="icon-size">1</property>
                 <property name="icon-name">zoom-in-symbolic</property>
               </object>
diff --git a/data/ui/headerbar-right.ui b/data/ui/headerbar-right.ui
index e2178a8a..e5be5b32 100644
--- a/data/ui/headerbar-right.ui
+++ b/data/ui/headerbar-right.ui
@@ -1,16 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.0 -->
 <interface>
   <requires lib="gtk+" version="3.22"/>
   <template class="Gjs_HeaderBarRight" parent="GtkBox">
-    <property name="visible">True</property>
-    <property name="no-show-all">True</property>
-    <property name="can_focus">False</property>
+    <property name="can_focus">0</property>
     <property name="spacing">6</property>
     <child>
       <object class="GtkToggleButton" id="toggleSidebarButton">
-        <property name="visible">True</property>
-        <property name="can-focus">True</property>
         <property name="valign">center</property>
         <property name="action-name">win.toggle-sidebar</property>
         <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Toggle 
route planner</property>
@@ -19,20 +14,14 @@
         </style>
         <child>
           <object class="GtkImage" id="toggle-sidebar-button-image">
-            <property name="visible">True</property>
             <property name="icon-size">1</property>
             <property name="icon-name">route-button-symbolic</property>
           </object>
         </child>
       </object>
-      <packing>
-        <property name="pack-type">end</property>
-      </packing>
     </child>
     <child>
       <object class="GtkMenuButton" id="favoritesButton">
-        <property name="visible">True</property>
-        <property name="can-focus">True</property>
         <property name="valign">center</property>
         <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Toggle 
favorites</property>
         <style>
@@ -40,20 +29,16 @@
         </style>
         <child>
           <object class="GtkImage" id="favorites-button-image">
-            <property name="visible">True</property>
             <property name="icon-size">1</property>
             <property name="icon-name">starred-symbolic</property>
           </object>
         </child>
       </object>
-      <packing>
-        <property name="pack-type">end</property>
-      </packing>
     </child>
     <child>
       <object class="GtkButton" id="printRouteButton">
+        <property name="visible">0</property>
         <property name="name">print-route</property>
-        <property name="can-focus">True</property>
         <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Print 
Route</property>
         <property name="action-name">win.print-route</property>
         <property name="valign">center</property>
@@ -62,14 +47,10 @@
         </style>
         <child>
           <object class="GtkImage" id="print-route-button-image">
-            <property name="visible">True</property>
             <property name="icon-name">document-print-symbolic</property>
           </object>
         </child>
       </object>
-      <packing>
-        <property name="pack-type">end</property>
-      </packing>
     </child>
   </template>
 </interface>
diff --git a/data/ui/layers-popover.ui b/data/ui/layers-popover.ui
index 423c4a86..7c14fa93 100644
--- a/data/ui/layers-popover.ui
+++ b/data/ui/layers-popover.ui
@@ -1,113 +1,95 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <!-- interface-requires gtk+ 3.10 -->
   <template class="Gjs_LayersPopover" parent="GtkPopover">
-    <child>
+    <property name="child">
       <object class="GtkGrid" id="grid">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
+        <property name="can_focus">0</property>
         <property name="halign">center</property>
         <property name="valign">center</property>
         <property name="row_spacing">5</property>
         <child>
           <object class="GtkRadioButton" id="streetLayerButton">
-            <property name="visible">True</property>
-            <property name="can-focus">True</property>
-            <property name="draw-indicator">False</property>
+            <property name="draw-indicator">0</property>
             <style>
               <class name="layer-radio-button"/>
             </style>
             <child>
-              <object class="GtkImage" id="streetLayerImage">
-                <property name="visible">True</property>
-              </object>
+              <object class="GtkImage" id="streetLayerImage"/>
             </child>
+            <layout>
+              <property name="left-attach">0</property>
+              <property name="top-attach">0</property>
+            </layout>
           </object>
-          <packing>
-            <property name="left-attach">0</property>
-            <property name="top-attach">0</property>
-          </packing>
         </child>
         <child>
           <object class="GtkRadioButton" id="aerialLayerButton">
-            <property name="visible">True</property>
-            <property name="can-focus">True</property>
-            <property name="draw-indicator">False</property>
+            <property name="draw-indicator">0</property>
             <style>
               <class name="layer-radio-button"/>
             </style>
             <child>
-              <object class="GtkImage" id="aerialLayerImage">
-                <property name="visible">True</property>
-              </object>
+              <object class="GtkImage" id="aerialLayerImage"/>
             </child>
+            <layout>
+              <property name="left-attach">0</property>
+              <property name="top-attach">1</property>
+            </layout>
           </object>
-          <packing>
-            <property name="left-attach">0</property>
-            <property name="top-attach">1</property>
-          </packing>
         </child>
         <child>
           <object class="GtkRevealer" id="hybridAerialRevealer">
-            <property name="can-focus">False</property>
-            <property name="visible">True</property>
-            <child>
+            <property name="can-focus">0</property>
+            <property name="child">
               <object class="GtkBox">
-                <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
+                <property name="can-focus">0</property>
                 <child>
                   <object class="GtkLabel">
-                    <property name="visible">True</property>
-                    <property name="can-focus">False</property>
-                    <property name="hexpand">True</property>
+                    <property name="can-focus">0</property>
+                    <property name="hexpand">1</property>
                     <property name="halign">GTK_ALIGN_START</property>
                     <property name="label" translatable="yes">Show Labels</property>
                   </object>
                 </child>
                 <child>
                   <object class="GtkCheckButton">
-                    <property name="visible">True</property>
-                    <property name="can-focus">True</property>
                     <property name="action-name">win.hybrid-aerial</property>
                   </object>
                 </child>
               </object>
-            </child>
+            </property>
+            <layout>
+              <property name="left-attach">0</property>
+              <property name="top-attach">2</property>
+            </layout>
           </object>
-          <packing>
-            <property name="left-attach">0</property>
-            <property name="top-attach">2</property>
-          </packing>
         </child>
         <child>
           <object class="GtkListBox" id="layersListBox">
             <property name="name">layers-list-box</property>
-            <property name="visible">false</property>
-            <property name="can_focus">False</property>
+            <property name="visible">0</property>
+            <property name="can_focus">0</property>
             <property name="selection-mode">none</property>
             <style>
               <class name="frame"/>
             </style>
+            <layout>
+              <property name="left-attach">0</property>
+              <property name="top-attach">3</property>
+            </layout>
           </object>
-          <packing>
-            <property name="left-attach">0</property>
-            <property name="top-attach">3</property>
-          </packing>
         </child>
         <child>
           <object class="GtkButton" id="loadLayerButton">
-            <property name="visible">True</property>
-            <property name="can-focus">True</property>
             <property name="label" translatable="yes" comments="Translators: This string uses ellipsis 
character">Open Shape Layer…</property>
             <property name="action-name">win.open-shape-layer</property>
+            <layout>
+              <property name="left-attach">0</property>
+              <property name="top-attach">4</property>
+            </layout>
           </object>
-          <packing>
-            <property name="left-attach">0</property>
-            <property name="top-attach">4</property>
-          </packing>
         </child>
       </object>
-    </child>
+    </property>
   </template>
 </interface>
diff --git a/data/ui/main-window.ui b/data/ui/main-window.ui
index c3daf4d3..5b8a0b85 100644
--- a/data/ui/main-window.ui
+++ b/data/ui/main-window.ui
@@ -30,13 +30,11 @@
   <template class="Gjs_MainWindow" parent="GtkApplicationWindow">
     <property name="width-request">300</property>
     <property name="height-request">500</property>
-    <property name="window-position">center</property>
     <property name="title" translatable="yes">Maps</property>
     <child type="titlebar">
       <object class="GtkHeaderBar" id="headerBar">
         <property name="visible">True</property>
         <property name="can-focus">False</property>
-        <property name="show-close-button">True</property>
         <style>
           <class name="titlebar"/>
         </style>
@@ -46,7 +44,8 @@
             <property name="halign">end</property>
             <property name="valign">center</property>
             <property name="menu-model">hamburgerMenu</property>
-            <accelerator key="F10" signal="clicked"/>
+            <!-- TODO: shortcut for main menu...-->
+            <!--<accelerator key="F10" signal="clicked"/>-->
             <child internal-child="accessible">
               <object class="AtkObject">
                 <property name="accessible-name" translatable="yes">Primary menu</property>
@@ -63,9 +62,6 @@
               </object>
             </child>
           </object>
-          <packing>
-            <property name="pack-type">end</property>
-          </packing>
         </child>
       </object>
     </child>
@@ -86,7 +82,7 @@
             <child>
               <object class="GtkSpinner" id="network-spinner">
                 <property name="visible">True</property>
-                <property name="active">True</property>
+                <property name="spinning">True</property>
               </object>
             </child>
             <child>
@@ -97,7 +93,11 @@
                 <property name="halign">center</property>
                 <property name="valign">center</property>
                 <property name="row_spacing">6</property>
-                <property name="margin">18</property>
+                <property name="margin-start">18</property>
+                <property name="margin-end">18</property>
+                <property name="margin-top">18</property>
+                <property name="margin-bottom">18</property>
+
                 <child>
                   <object class="GtkImage" id="no-network-conn-image">
                     <property name="visible">True</property>
@@ -145,12 +145,12 @@
                 <property name="visible">True</property>
               </object>
             </child>
+            <layout>
+              <property name="left-attach">0</property>
+              <property name="top-attach">1</property>
+              <property name="column-span">2</property>
+            </layout>
           </object>
-          <packing>
-            <property name="left-attach">0</property>
-            <property name="top-attach">1</property>
-            <property name="width">2</property>
-          </packing>
         </child>
       </object>
     </child>
diff --git a/data/ui/place-popover.ui b/data/ui/place-popover.ui
index ae663a17..992805c3 100644
--- a/data/ui/place-popover.ui
+++ b/data/ui/place-popover.ui
@@ -4,7 +4,6 @@
   <template class="Gjs_PlacePopover" parent="Gjs_SearchPopover">
     <property name="visible">False</property>
     <property name="hexpand">False</property>
-    <property name="modal">False</property>
     <style>
       <class name="maps-popover"/>
     </style>
@@ -26,12 +25,11 @@
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="hscrollbar_policy">never</property>
-                <property name="shadow_type">in</property>
                 <child>
                   <object class="GtkListBox" id="list">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="expand">True</property>
+                    <property name="vexpand">True</property>
                     <property name="activate_on_single_click">True</property>
                   </object>
                 </child>
diff --git a/data/ui/route-entry.ui b/data/ui/route-entry.ui
index b186e453..78c4edaa 100644
--- a/data/ui/route-entry.ui
+++ b/data/ui/route-entry.ui
@@ -6,20 +6,14 @@
     <property name="orientation">horizontal</property>
     <property name="hexpand">False</property>
     <child>
-      <object class="GtkEventBox" id="iconEventBox">
+      <object class="GtkImage" id="icon">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <child>
-          <object class="GtkImage" id="icon">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="margin-end">8</property>
-            <property name="margin-start">13</property>
-            <property name="width-request">16</property>
-            <property name="icon-name">maps-point-end-symbolic</property>
-           <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Drag 
to change order of the route</property>
-          </object>
-        </child>
+        <property name="margin-end">8</property>
+        <property name="margin-start">13</property>
+        <property name="width-request">16</property>
+        <property name="icon-name">maps-point-end-symbolic</property>
+        <property name="tooltip-text" translatable="yes" comments="Translators: This is a tooltip">Drag to 
change order of the route</property>
       </object>
     </child>
     <child>
@@ -33,7 +27,6 @@
     <child>
       <object class="GtkButton" id="button">
         <property name="visible">True</property>
-        <property name="no_show_all">True</property>
         <property name="can-focus">True</property>
         <property name="valign">center</property>
         <property name="height-request">31</property>
diff --git a/data/ui/sidebar.ui b/data/ui/sidebar.ui
index ab7b3890..f542e573 100644
--- a/data/ui/sidebar.ui
+++ b/data/ui/sidebar.ui
@@ -1,46 +1,37 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
 <interface>
   <requires lib="gtk+" version="3.10"/>
   <template class="Gjs_Sidebar" parent="GtkRevealer">
-    <property name="visible">True</property>
     <property name="transition_type">slide-left</property>
     <property name="transition_duration">400</property>
     <property name="halign">end</property>
-    <property name="valign">fill</property>
     <style>
       <class name="maps-sidebar"/>
     </style>
-    <child>
+    <property name="child">
       <object class="GtkGrid" id="sidebar">
         <property name="name">sidebar</property>
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="vexpand">True</property>
-        <property name="valign">fill</property>
-        <property name="column_homogeneous">True</property>
+        <property name="can_focus">0</property>
+        <property name="vexpand">1</property>
+        <property name="column_homogeneous">1</property>
         <property name="orientation">vertical</property>
         <property name="width_request">320</property>
         <property name="row_spacing">2</property>
         <child>
           <object class="GtkBox" id="mode-chooser">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can_focus">0</property>
             <property name="halign">center</property>
             <property name="margin-top">10</property>
             <child>
               <object class="GtkRadioButton" id="modePedestrianToggle">
                 <property name="name">mode-pedestrian-toggle</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="draw_indicator">False</property>
+                <property name="receives_default">1</property>
+                <property name="draw_indicator">0</property>
                 <property name="height-request">32</property>
                 <property name="width-request">42</property>
                 <child>
                   <object class="GtkImage" id="mode-pedestrian-image">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can_focus">0</property>
                     <property name="icon-name">route-pedestrian-symbolic</property>
                   </object>
                 </child>
@@ -52,17 +43,14 @@
             <child>
               <object class="GtkRadioButton" id="modeBikeToggle">
                 <property name="name">mode-bike-toggle</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="draw_indicator">False</property>
+                <property name="receives_default">1</property>
+                <property name="draw_indicator">0</property>
                 <property name="group">modePedestrianToggle</property>
                 <property name="height-request">32</property>
                 <property name="width-request">42</property>
                 <child>
                   <object class="GtkImage" id="mode-bike-image">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can_focus">0</property>
                     <property name="icon-name">route-bike-symbolic</property>
                   </object>
                 </child>
@@ -74,18 +62,15 @@
             <child>
               <object class="GtkRadioButton" id="modeCarToggle">
                 <property name="name">mode-car-toggle</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="active">True</property>
-                <property name="draw_indicator">False</property>
+                <property name="receives_default">1</property>
+                <property name="active">1</property>
+                <property name="draw_indicator">0</property>
                 <property name="group">modeBikeToggle</property>
                 <property name="height-request">32</property>
                 <property name="width-request">42</property>
                 <child>
                   <object class="GtkImage" id="mode-car-image">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can_focus">0</property>
                     <property name="icon-name">route-car-symbolic</property>
                   </object>
                 </child>
@@ -97,17 +82,15 @@
             <child>
               <object class="GtkRadioButton" id="modeTransitToggle">
                 <property name="name">mode-transit-toggle</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="draw_indicator">False</property>
+                <property name="receives_default">1</property>
+                <property name="draw_indicator">0</property>
                 <property name="group">modeCarToggle</property>
                 <property name="height-request">32</property>
                 <property name="width-request">42</property>
                 <child>
                   <object class="GtkImage" id="mode-transit-image">
-                    <property name="visible">False</property>
-                    <property name="can_focus">False</property>
+                    <property name="visible">0</property>
+                    <property name="can_focus">0</property>
                     <property name="icon-name">route-transit-symbolic</property>
                   </object>
                 </child>
@@ -124,36 +107,31 @@
         <child>
           <object class="GtkListBox" id="entryList">
             <property name="name">sidebar-entry-list</property>
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can_focus">0</property>
             <property name="selection-mode">GTK_SELECTION_NONE</property>
           </object>
         </child>
         <child>
           <object class="GtkGrid" id="sidebar-route-info-wrapper">
-            <property name="visible">True</property>
-            <property name="hexpand">False</property>
+            <property name="hexpand">0</property>
             <child>
               <object class="GtkGrid" id="sidebar-route-info">
                 <property name="name">sidebar-route-info</property>
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can_focus">0</property>
                 <property name="margin_start">17</property>
                 <property name="margin_end">17</property>
                 <property name="margin_top">12</property>
-                <property name="hexpand">true</property>
+                <property name="hexpand">1</property>
                 <child>
                   <object class="GtkLabel" id="timeInfo">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can_focus">0</property>
                     <property name="halign">start</property>
-                    <property name="hexpand">true</property>
+                    <property name="hexpand">1</property>
                   </object>
                 </child>
                 <child>
                   <object class="GtkLabel" id="distanceInfo">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can_focus">0</property>
                     <property name="margin_start">10</property>
                   </object>
                 </child>
@@ -163,200 +141,188 @@
         </child>
         <child>
           <object class="GtkGrid">
-            <property name="visible">True</property>
-            <property name="valign">fill</property>
-            <property name="vexpand">True</property>
-            <property name="hexpand_set">True</property>
+            <property name="vexpand">1</property>
+            <property name="hexpand_set">1</property>
             <style>
               <class name="frame"/>
             </style>
             <child>
               <object class="GtkRevealer" id="transitRevealer">
-                <child>
+                <property name="visible">0</property>
+                <property name="child">
                   <object class="GtkStack" id="transitHeader">
-                    <property name="visible">True</property>
                     <property name="transition-type">GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT</property>
                   </object>
-                </child>
+                </property>
+                <layout>
+                  <property name="left_attach">0</property>
+                  <property name="top_attach">0</property>
+                </layout>
               </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">0</property>
-              </packing>
             </child>
             <child>
               <object class="GtkStack" id="instructionStack">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can_focus">0</property>
                 <child>
                   <object class="GtkScrolledWindow" id="instructionWindow">
                     <property name="name">instruction-window</property>
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="valign">fill</property>
-                    <property name="vexpand">True</property>
-                    <property name="margin">1</property>
+                    <property name="can_focus">0</property>
+                    <property name="vexpand">1</property>
+                    <property name="margin-start">1</property>
+                    <property name="margin-end">1</property>
+                    <property name="margin-top">1</property>
+                    <property name="margin-bottom">1</property>
                     <property name="hscrollbar_policy">never</property>
-                    <child>
+                    <property name="child">
                       <object class="GtkListBox" id="instructionList">
                         <property name="name">instruction-list</property>
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="valign">fill</property>
-                        <property name="hexpand">True</property>
+                        <property name="can_focus">0</property>
+                        <property name="hexpand">1</property>
                       </object>
-                    </child>
+                    </property>
                   </object>
                 </child>
                 <child>
                   <object class="GtkScrolledWindow" id="transitWindow">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="valign">fill</property>
-                    <property name="vexpand">True</property>
-                    <property name="margin">1</property>
+                    <property name="can_focus">0</property>
+                    <property name="vexpand">1</property>
+                    <property name="margin-start">1</property>
+                    <property name="margin-end">1</property>
+                    <property name="margin-top">1</property>
+                    <property name="margin-bottom">1</property>
                     <property name="hscrollbar_policy">never</property>
-                    <child>
+                    <property name="child">
                       <object class="GtkStack" id="transitListStack">
-                        <property name="visible">True</property>
                         <property 
name="transition-type">GTK_STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT</property>
-                        <property name="vhomogeneous">False</property>
+                        <property name="vhomogeneous">0</property>
                         <child>
-                          <object class="GtkListBox" id="transitOverviewListBox">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                          </object>
-                          <packing>
+                          <object class="GtkStackPage">
                             <property name="name">overview</property>
-                          </packing>
+                            <property name="child">
+                              <object class="GtkListBox" id="transitOverviewListBox">
+                                <property name="can-focus">0</property>
+                              </object>
+                            </property>
+                          </object>
                         </child>
                         <child>
-                          <object class="GtkListBox" id="transitItineraryListBox">
-                            <property name="visible">True</property>
-                            <property name="can-focus">False</property>
-                            <property name="selection-mode">GTK_SELECTION_NONE</property>
-                          </object>
-                          <packing>
+                          <object class="GtkStackPage">
                             <property name="name">itinerary</property>
-                          </packing>
+                            <property name="child">
+                              <object class="GtkListBox" id="transitItineraryListBox">
+                                <property name="can-focus">0</property>
+                                <property name="selection-mode">GTK_SELECTION_NONE</property>
+                              </object>
+                            </property>
+                          </object>
                         </child>
                       </object>
-                    </child>
+                    </property>
                   </object>
                 </child>
                 <child>
                   <object class="GtkSpinner" id="instructionSpinner">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="active">True</property>
+                    <property name="can_focus">0</property>
+                    <property name="spinning">True</property>
                   </object>
                 </child>
                 <child>
                   <object class="GtkLabel" id="errorLabel">
-                    <property name="visible">True</property>
-                    <property name="can_focus">False</property>
+                    <property name="can_focus">0</property>
                     <style>
                       <class name="dim-label"/>
                     </style>
                   </object>
                 </child>
+                <layout>
+                  <property name="left_attach">0</property>
+                  <property name="top_attach">1</property>
+                </layout>
               </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">1</property>
-              </packing>
             </child>
           </object>
         </child>
         <child>
           <object class="GtkStack" id="linkButtonStack">
+            <property name="visible">0</property>
             <child>
-              <object class="GtkLinkButton">
-                <property name="label" translatable="yes">Route search by GraphHopper</property>
-                <property name="visible">True</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_action_appearance">False</property>
-                <property name="relief">none</property>
-                <property name="uri">https://graphhopper.com</property>
-                <style>
-                  <class name="small-label"/>
-                </style>
-              </object>
-              <packing>
+              <object class="GtkStackPage">
                 <property name="name">turnByTurn</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkGrid">
-                <property name="visible">True</property>
-                <property name="halign">GTK_ALIGN_END</property>
-                <child>
-                  <object class="GtkLabel" id="transitAttributionLabel">
-                    <property name="visible">True</property>
-                    <property name="can_focus">True</property>
-                    <property name="receives_default">True</property>
-                    <property name="use_markup">True</property>
+                <property name="child">
+                  <object class="GtkLinkButton">
+                    <property name="label" translatable="yes">Route search by GraphHopper</property>
+                    <property name="receives_default">1</property>
+                    <property name="uri">https://graphhopper.com</property>
                     <style>
                       <class name="small-label"/>
                     </style>
                   </object>
-                  <packing>
-                    <property name="left-attach">0</property>
-                    <property name="top-attach">0</property>
-                  </packing>
-                </child>
-                <child>
-                  <object class="GtkMenuButton">
-                    <property name="visible">True</property>
-                    <property name="popover">transitDisclaimerPopover</property>
+                </property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkStackPage">
+                <property name="name">transit</property>
+                <property name="child">
+                  <object class="GtkGrid">
                     <property name="halign">GTK_ALIGN_END</property>
-                    <property name="margin-top">5</property>
-                    <property name="margin-bottom">5</property>
-                    <property name="margin-end">5</property>
-                    <property name="margin-start">5</property>
-                    <style>
-                      <class name="flat"/>
-                    </style>
                     <child>
-                      <object class="GtkGrid">
-                        <property name="visible">True</property>
-                        <property name="valign">GTK_ALIGN_CENTER</property>
+                      <object class="GtkLabel" id="transitAttributionLabel">
+                        <property name="receives_default">1</property>
+                        <property name="use_markup">1</property>
+                        <style>
+                          <class name="small-label"/>
+                        </style>
+                        <layout>
+                          <property name="left-attach">0</property>
+                          <property name="top-attach">0</property>
+                        </layout>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkMenuButton">
+                        <property name="popover">transitDisclaimerPopover</property>
+                        <property name="halign">GTK_ALIGN_END</property>
+                        <property name="margin-top">5</property>
+                        <property name="margin-bottom">5</property>
+                        <property name="margin-end">5</property>
+                        <property name="margin-start">5</property>
+                        <style>
+                          <class name="flat"/>
+                        </style>
                         <child>
-                          <object class="GtkImage">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="halign">GTK_ALIGN_CENTER</property>
-                            <property name="hexpand">False</property>
-                            <property name="icon-name">dialog-information-symbolic</property>
+                          <object class="GtkGrid">
+                            <property name="valign">GTK_ALIGN_CENTER</property>
+                            <child>
+                              <object class="GtkImage">
+                                <property name="can_focus">0</property>
+                                <property name="halign">GTK_ALIGN_CENTER</property>
+                                <property name="hexpand">0</property>
+                                <property name="icon-name">dialog-information-symbolic</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
+                        <layout>
+                          <property name="left-attach">1</property>
+                          <property name="top-attach">0</property>
+                        </layout>
                       </object>
                     </child>
                   </object>
-                  <packing>
-                    <property name="left-attach">1</property>
-                    <property name="top-attach">0</property>
-                  </packing>
-                </child>
+                </property>
               </object>
-              <packing>
-                <property name="name">transit</property>
-              </packing>
             </child>
           </object>
         </child>
       </object>
-    </child>
+    </property>
   </template>
   <object class="GtkPopover" id="transitDisclaimerPopover">
-    <property name="visible">False</property>
-    <child>
+    <property name="child">
       <object class="GtkGrid">
-        <property name="visible">True</property>
         <child>
           <object class="GtkLabel">
-            <property name="visible">True</property>
             <property name="margin-top">5</property>
             <property name="margin-bottom">5</property>
             <property name="margin-start">5</property>
@@ -371,17 +337,15 @@ Names and brands shown are to be considered as registered trademarks when applic
           </object>
         </child>
       </object>
-    </child>
+    </property>
   </object>
   <object class="GtkGrid" id="transitItineraryHeader">
-    <property name="visible">True</property>
-    <property name="can-focus">False</property>
+    <property name="can-focus">0</property>
     <style>
       <class name="shaded"/>
     </style>
     <child>
       <object class="GtkButton" id="transitItineraryBackButton">
-        <property name="visible">True</property>
         <property name="margin-start">6</property>
         <property name="margin-end">6</property>
         <property name="margin-top">4</property>
@@ -389,56 +353,52 @@ Names and brands shown are to be considered as registered trademarks when applic
         <property name="halign">GTK_ALIGN_START</property>
         <child>
           <object class="GtkGrid">
-            <property name="visible">True</property>
             <property name="valign">GTK_ALIGN_CENTER</property>
             <child>
               <object class="GtkImage">
-                <property name="visible">True</property>
-                <property name="can-focus">False</property>
-                <property name="hexpand">False</property>
+                <property name="can-focus">0</property>
+                <property name="hexpand">0</property>
                 <property name="icon-name">go-previous-symbolic</property>
               </object>
             </child>
           </object>
         </child>
+        <layout>
+          <property name="left-attach">0</property>
+          <property name="top-attach">0</property>
+        </layout>
       </object>
-      <packing>
-        <property name="left-attach">0</property>
-        <property name="top-attach">0</property>
-      </packing>
     </child>
     <child>
       <object class="GtkLabel" id="transitItineraryTimeLabel">
-        <property name="visible">True</property>
         <property name="margin-start">6</property>
         <property name="margin-end">6</property>
         <property name="margin-top">4</property>
         <property name="margin-bottom">4</property>
-        <property name="hexpand">False</property>
+        <property name="hexpand">0</property>
         <property name="halign">GTK_ALIGN_START</property>
+        <layout>
+          <property name="left-attach">1</property>
+          <property name="top-attach">0</property>
+        </layout>
       </object>
-      <packing>
-        <property name="left-attach">1</property>
-        <property name="top-attach">0</property>
-      </packing>
     </child>
     <child>
       <object class="GtkLabel" id="transitItineraryDurationLabel">
-        <property name="visible">True</property>
         <property name="margin-start">6</property>
         <property name="margin-end">6</property>
         <property name="margin-top">4</property>
         <property name="margin-bottom">4</property>
-        <property name="hexpand">True</property>
+        <property name="hexpand">1</property>
         <property name="halign">GTK_ALIGN_START</property>
         <style>
           <class name="dim-label"/>
         </style>
+        <layout>
+          <property name="left-attach">2</property>
+          <property name="top-attach">0</property>
+        </layout>
       </object>
-      <packing>
-        <property name="left-attach">2</property>
-        <property name="top-attach">0</property>
-      </packing>
     </child>
   </object>
 </interface>
diff --git a/data/ui/transit-options-panel.ui b/data/ui/transit-options-panel.ui
index a11acfa0..5725fad4 100644
--- a/data/ui/transit-options-panel.ui
+++ b/data/ui/transit-options-panel.ui
@@ -1,14 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <template class="Gjs_TransitOptionsPanel" parent="GtkGrid">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="no-show-all">True</property>
+    <property name="can_focus">0</property>
+    <!-- TODO: was this needed, it's deprecated in GTK 4...-->
+    <!--<property name="no-show-all">True</property>-->
     <style>
       <class name="shaded"/>
     </style>
     <child>
       <object class="GtkComboBoxText" id="transitTimeOptionsComboBox">
-        <property name="visible">True</property>
         <property name="active_id">leaveNow</property>
         <property name="margin_start">6</property>
         <property name="margin_end">6</property>
@@ -19,43 +19,42 @@
           <item translatable="yes" id="leaveBy" comments="Indicates searching for itineraries leaving at the 
specified time at the earliest">Leave By</item>
           <item translatable="yes" id="arriveBy" comments="Indicates searching for itineraries arriving no 
later than the specified time">Arrive By</item>
         </items>
+        <layout>
+          <property name="left_attach">0</property>
+          <property name="top_attach">0</property>
+        </layout>
       </object>
-      <packing>
-        <property name="left_attach">0</property>
-        <property name="top_attach">0</property>
-      </packing>
     </child>
     <child>
       <object class="GtkEntry" id="transitTimeEntry">
-        <property name="visible">False</property>
+        <property name="visible">0</property>
         <property name="width_chars">5</property>
         <property name="margin_start">3</property>
         <property name="margin_end">3</property>
         <property name="margin_top">4</property>
         <property name="margin_bottom">4</property>
+        <layout>
+          <property name="left_attach">1</property>
+          <property name="top_attach">0</property>
+        </layout>
       </object>
-      <packing>
-        <property name="left_attach">1</property>
-        <property name="top_attach">0</property>
-      </packing>
     </child>
     <child>
       <object class="GtkMenuButton" id="transitDateButton">
-        <property name="visible">False</property>
+        <property name="visible">0</property>
         <property name="popover">transitDatePopover</property>
         <property name="margin_start">3</property>
         <property name="margin_end">3</property>
         <property name="margin_top">4</property>
         <property name="margin_bottom">4</property>
+        <layout>
+          <property name="left_attach">2</property>
+          <property name="top_attach">0</property>
+        </layout>
       </object>
-      <packing>
-        <property name="left_attach">2</property>
-        <property name="top_attach">0</property>
-      </packing>
     </child>
     <child>
       <object class="GtkMenuButton" id="transitParametersMenuButton">
-        <property name="visible">True</property>
         <property name="popover">transitParametersPopover</property>
         <property name="halign">GTK_ALIGN_END</property>
         <property name="margin_start">3</property>
@@ -64,44 +63,39 @@
         <property name="margin_bottom">4</property>
         <child>
           <object class="GtkGrid">
-            <property name="visible">True</property>
             <property name="valign">GTK_ALIGN_CENTER</property>
             <child>
               <object class="GtkImage">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
+                <property name="can_focus">0</property>
                 <property name="halign">GTK_ALIGN_CENTER</property>
-                <property name="hexpand">True</property>
+                <property name="hexpand">1</property>
                 <property name="icon-name">view-more-symbolic</property>
               </object>
             </child>
           </object>
         </child>
+        <layout>
+          <property name="left_attach">3</property>
+          <property name="top_attach">0</property>
+        </layout>
       </object>
-      <packing>
-        <property name="left_attach">3</property>
-        <property name="top_attach">0</property>
-      </packing>
     </child>
   </template>
   <object class="GtkPopover" id="transitDatePopover">
-    <property name="visible">False</property>
-    <child>
-      <object class="GtkCalendar" id="transitDateCalendar">
-        <property name="visible">True</property>
-      </object>
-    </child>
+    <property name="child">
+      <object class="GtkCalendar" id="transitDateCalendar"/>
+    </property>
   </object>
   <object class="GtkPopover" id="transitParametersPopover">
-    <property name="visible">False</property>
-    <child>
+    <property name="child">
       <object class="GtkGrid">
-        <property name="visible">True</property>
-        <property name="margin">6</property>
+        <property name="margin-start">6</property>
+        <property name="margin-end">6</property>
+        <property name="margin-top">6</property>
+        <property name="margin-bottom">6</property>
         <property name="orientation">GTK_ORIENTATION_VERTICAL</property>
         <child>
           <object class="GtkLabel">
-            <property name="visible">True</property>
             <property name="halign">GTK_ALIGN_START</property>
             <property name="label" translatable="yes" comments="Header indicating selected modes of 
transit">Show</property>
             <property name="margin_start">6</property>
@@ -112,48 +106,41 @@
         </child>
         <child>
           <object class="GtkCheckButton" id="busCheckButton">
-            <property name="visible">True</property>
-            <property name="active">True</property>
+            <property name="active">1</property>
             <property name="label" translatable="yes">Buses</property>
           </object>
         </child>
         <child>
           <object class="GtkCheckButton" id="tramCheckButton">
-            <property name="visible">True</property>
-            <property name="active">True</property>
+            <property name="active">1</property>
             <property name="label" translatable="yes">Trams</property>
           </object>
         </child>
         <child>
           <object class="GtkCheckButton" id="trainCheckButton">
-            <property name="visible">True</property>
-            <property name="active">True</property>
+            <property name="active">1</property>
             <property name="label" translatable="yes">Trains</property>
           </object>
         </child>
         <child>
           <object class="GtkCheckButton" id="subwayCheckButton">
-            <property name="visible">True</property>
-            <property name="active">True</property>
+            <property name="active">1</property>
             <property name="label" translatable="yes">Subway</property>
           </object>
         </child>
         <child>
           <object class="GtkCheckButton" id="ferryCheckButton">
-            <property name="visible">True</property>
-            <property name="active">True</property>
+            <property name="active">1</property>
             <property name="label" translatable="yes">Ferries</property>
           </object>
         </child>
         <child>
           <object class="GtkCheckButton" id="airplaneCheckButton">
-            <property name="visible">True</property>
-            <property name="active">True</property>
+            <property name="active">1</property>
             <property name="label" translatable="yes">Airplanes</property>
           </object>
         </child>
       </object>
-    </child>
+    </property>
   </object>
 </interface>
-  
diff --git a/src/application.js b/src/application.js
index c51fc421..4064d812 100644
--- a/src/application.js
+++ b/src/application.js
@@ -20,12 +20,13 @@
  *         Zeeshan Ali (Khattak) <zeeshanak gnome org>
  */
 
+const Gdk = imports.gi.Gdk;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
-const GtkClutter = imports.gi.GtkClutter;
-const WebKit2 = imports.gi.WebKit2;
+// TODO: WebKit for GTK 4?
+//const WebKit2 = imports.gi.WebKit2;
 
 const CheckIn = imports.checkIn;
 const ContactPlace = imports.contactPlace;
@@ -54,7 +55,7 @@ var osmEdit = null;
 var normalStartup = true;
 var routeQuery = null;
 
-const _ensuredTypes = [WebKit2.WebView,
+const _ensuredTypes = [/*WebKit2.WebView*/,
                        OSMTypeSearchEntry.OSMTypeSearchEntry];
 
 var Application = GObject.registerClass({
@@ -223,8 +224,6 @@ var Application = GObject.registerClass({
     vfunc_startup() {
         super.vfunc_startup();
 
-        GtkClutter.init(null);
-
         Utils.loadStyleSheet(Gio.file_new_for_uri('resource:///org/gnome/Maps/application.css'));
 
         application = this;
@@ -255,8 +254,8 @@ var Application = GObject.registerClass({
         gtkSettings.gtk_application_prefer_dark_theme =
             settings.get('night-mode');
 
-        Gtk.IconTheme.get_default().append_search_path(GLib.build_filenamev([pkg.pkgdatadir,
-                                                                             'icons']));
+        Gtk.IconTheme.get_for_display(Gdk.Display.get_default()).
+            add_search_path(GLib.build_filenamev([pkg.pkgdatadir, 'icons']));
         this._initPlaceStore();
     }
 
diff --git a/src/contextMenu.js b/src/contextMenu.js
index 6a4727a2..23e34de0 100644
--- a/src/contextMenu.js
+++ b/src/contextMenu.js
@@ -37,14 +37,15 @@ const Utils = imports.utils;
 const ZoomInDialog = imports.zoomInDialog;
 
 var ContextMenu = GObject.registerClass({
-    Template: 'resource:///org/gnome/Maps/ui/context-menu.ui',
+    Template: 'resource:///org/gnome/Maps/ui/context-menu.ui' /*,
     InternalChildren: [ 'whatsHereItem',
                         'geoURIItem',
                         'addOSMLocationItem',
                         'routeFromHereItem',
                         'addIntermediateDestinationItem',
-                        'routeToHereItem' ],
-}, class ContextMenu extends Gtk.Menu {
+                        'routeToHereItem' ]*/,
+}, class ContextMenu extends Gtk.PopoverMenu {
+    // TODO: should create from a menu model…
     _init(params) {
         this._mapView = params.mapView;
         delete params.mapView;
@@ -54,9 +55,11 @@ var ContextMenu = GObject.registerClass({
 
         super._init(params);
 
-        this._mapView.connect('button-release-event',
-                              this._onButtonReleaseEvent.bind(this));
+        // TODO: use GtkGesture (and also for long-press, see 
https://gitlab.gnome.org/GNOME/gnome-maps/-/issues/2)
+        //this._mapView.connect('button-release-event',
+        //                      this._onButtonReleaseEvent.bind(this));
 
+        /* TODO: use menu model...
         this._whatsHereItem.connect('activate',
                                     this._onWhatsHereActivated.bind(this));
         this._geoURIItem.connect('activate',
@@ -69,6 +72,7 @@ var ContextMenu = GObject.registerClass({
                                         this._onAddIntermediateDestinationActivated.bind(this));
         this._routeToHereItem.connect('activate',
                                       this._onRouteToHereActivated.bind(this));
+        */
         Application.routeQuery.connect('notify::points',
                                        this._routingUpdate.bind(this));
         this._routingUpdate();
@@ -90,10 +94,11 @@ var ContextMenu = GObject.registerClass({
         let query = Application.routeQuery;
         let numPoints = query.points.length;
 
-        this._routeFromHereItem.sensitive = numPoints < RouteQuery.MAX_QUERY_POINTS;
-        this._routeToHereItem.sensitive = numPoints < RouteQuery.MAX_QUERY_POINTS;
-        this._addIntermediateDestinationItem.sensitive =
-            query.filledPoints.length >= 2 && numPoints < RouteQuery.MAX_QUERY_POINTS;
+        // TODO: update menu model
+        //this._routeFromHereItem.sensitive = numPoints < RouteQuery.MAX_QUERY_POINTS;
+        //this._routeToHereItem.sensitive = numPoints < RouteQuery.MAX_QUERY_POINTS;
+        //this._addIntermediateDestinationItem.sensitive =
+        //    query.filledPoints.length >= 2 && numPoints < RouteQuery.MAX_QUERY_POINTS;
     }
 
     _onRouteFromHereActivated() {
diff --git a/src/favoritesPopover.js b/src/favoritesPopover.js
index 097864ba..f472f8f3 100644
--- a/src/favoritesPopover.js
+++ b/src/favoritesPopover.js
@@ -49,7 +49,6 @@ var FavoritesPopover = GObject.registerClass({
         this._mapView = params.mapView;
         delete params.mapView;
 
-        params.transitions_enabled = false;
         super._init(params);
 
         this._rows = 0;
@@ -103,7 +102,8 @@ var FavoritesPopover = GObject.registerClass({
     }
 
     _updateList() {
-        this._list.forall((row) => row.destroy());
+        // TODO: GtkContainer is not available in GTK4, use get_first(), get_next(), or something like that
+        //this._list.forall((row) => row.destroy());
 
         let rows = 0;
         this._model.foreach((model, path, iter) => {
diff --git a/src/layersPopover.js b/src/layersPopover.js
index 3f80f93c..e6939298 100644
--- a/src/layersPopover.js
+++ b/src/layersPopover.js
@@ -75,8 +75,6 @@ var LayersPopover = GObject.registerClass({
         delete params.mapView;
 
         super._init({ width_request: 200,
-                      no_show_all: true,
-                      transitions_enabled: false,
                       visible: false });
 
         this._aerialLayerButton.join_group(this._streetLayerButton);
@@ -138,11 +136,12 @@ var LayersPopover = GObject.registerClass({
                 }
             });
 
-            this._mapView.view.connect("notify::zoom-level",
+            let viewport = this._mapView.get_viewport();
+            viewport.connect("notify::zoom-level",
                                        this._setLayerPreviews.bind(this));
-            this._mapView.view.connect("notify::latitude",
+            viewport.connect("notify::latitude",
                                        this._setLayerPreviews.bind(this));
-            this._mapView.view.connect("notify::longitude",
+            viewport.connect("notify::longitude",
                                        this._setLayerPreviews.bind(this));
             Application.settings.connect("changed::night-mode",
                                          this._onNightModeChanged.bind(this));
diff --git a/src/main.js b/src/main.js
index d93f0408..3a1ab4f8 100644
--- a/src/main.js
+++ b/src/main.js
@@ -23,20 +23,16 @@
 pkg.initGettext();
 pkg.initFormat();
 pkg.require({ 'cairo': '1.0',
-              'Champlain': '0.12',
-              'Clutter': '1.0',
-              'Cogl': '1.0',
               'GeocodeGlib': '1.0',
-              'Gdk': '3.0',
+              'Gdk': '4.0',
               'GdkPixbuf': '2.0',
               'GFBGraph': '0.2',
               'Gio': '2.0',
               'GLib': '2.0',
               'Goa': '1.0',
               'GObject': '2.0',
-              'Gtk': '3.0',
-              'GtkChamplain': '0.12',
-              'GtkClutter': '1.0',
+              'Gtk': '4.0',
+              'Shumate': '0.0',
               'Rest': '0.7',
               'Soup': '2.4' });
 
diff --git a/src/mainWindow.js b/src/mainWindow.js
index 10830667..f1d3ef6c 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -22,12 +22,12 @@
 
 const _ = imports.gettext.gettext;
 
-const Champlain = imports.gi.Champlain;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gdk = imports.gi.Gdk;
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
+const Shumate = imports.gi.Shumate;
 const Mainloop = imports.mainloop;
 
 const Application = imports.application;
@@ -92,6 +92,7 @@ var MainWindow = GObject.registerClass({
     }
 
     _init(params) {
+        Utils.debug('MainWindow::_init');
         super._init(params);
 
         this._configureId = 0;
@@ -101,7 +102,7 @@ var MainWindow = GObject.registerClass({
                 MapView.MapType.LOCAL : undefined,
             mainWindow: this });
 
-        this._mainGrid.add(this._mapView);
+        this._mainGrid.attach(this._mapView, 0, 0, 1, 1);
 
         this._mapView.gotoUserLocation(false);
 
@@ -110,12 +111,20 @@ var MainWindow = GObject.registerClass({
         this._contextMenu = new ContextMenu.ContextMenu({ mapView: this._mapView,
                                                           mainWindow: this });
 
+        Utils.debug('MainWindow::_init 2');
+
         this._initActions();
+        Utils.debug('MainWindow::_init 3');
         this._initHeaderbar();
+        Utils.debug('MainWindow::_init 4');
         this._initSignals();
+        Utils.debug('MainWindow::_init 5');
         this._restoreWindowGeometry();
+        Utils.debug('MainWindow::_init 6');
         this._initDND();
 
+        Utils.debug('MainWindow::_init 3');
+
         this._grid.attach(this._sidebar, 1, 0, 1, 1);
 
         this._grid.show_all();
@@ -127,6 +136,7 @@ var MainWindow = GObject.registerClass({
          * overview.
          */
         this.title = _("Maps");
+        Utils.debug('end MainWindow::_init');
     }
 
     _createPlaceEntry() {
@@ -146,7 +156,8 @@ var MainWindow = GObject.registerClass({
 
         let popover = placeEntry.popover;
         popover.connect('selected', () => this._mapView.grab_focus());
-        this._mapView.view.connect('button-press-event', () => popover.hide());
+        // TODO: should use GtkGesture for this...
+        //this._mapView.view.connect('button-press-event', () => popover.hide());
         return placeEntry;
     }
 
@@ -336,13 +347,11 @@ var MainWindow = GObject.registerClass({
             application: this.application
         });
         this._headerBar.pack_start(this._headerBarLeft);
-
         this._headerBarRight = new HeaderBar.HeaderBarRight({
             mapView: this._mapView,
             application: this.application
         });
         this._headerBar.pack_end(this._headerBarRight);
-
         this._placeEntry = this._createPlaceEntry();
         this._headerBar.custom_title = this._placeEntry;
 
diff --git a/src/mapBubble.js b/src/mapBubble.js
index 998f0213..501eb39c 100644
--- a/src/mapBubble.js
+++ b/src/mapBubble.js
@@ -47,8 +47,6 @@ class MapBubble extends Gtk.Popover {
         delete params.place;
 
         this._mapView = params.mapView;
-        params.relative_to = params.mapView;
-        params.transitions_enabled = false;
         delete params.mapView;
 
         let buttonFlags = params.buttons || Button.NONE;
@@ -95,6 +93,7 @@ class MapBubble extends Gtk.Popover {
         }
 
         this.add(ui.bubbleMainGrid);
+        this.set_parent(this._mapView);
     }
 
     get image() {
diff --git a/src/mapSource.js b/src/mapSource.js
index b653b42b..793f631d 100644
--- a/src/mapSource.js
+++ b/src/mapSource.js
@@ -17,14 +17,12 @@
  * Author: Jonas Danielsson <jonas threetimestwo org>
  */
 
-const Champlain = imports.gi.Champlain;
-const Clutter = imports.gi.Clutter;
 const GdkPixbuf = imports.gi.GdkPixbuf;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const GtkClutter = imports.gi.GtkClutter;
+const Shumate = imports.gi.Shumate;
 const System = imports.system;
 
 const Service = imports.service;
@@ -41,7 +39,7 @@ const _LOGO_PADDING_Y = 25;
 const _LOGO_PADDING_Y_RTL = 35;
 
 var AttributionLogo = GObject.registerClass({},
-class AttributionLogo extends GtkClutter.Actor {
+class AttributionLogo extends Gtk.Image {
 
     _init(view) {
         super._init();
@@ -61,16 +59,17 @@ class AttributionLogo extends GtkClutter.Actor {
     _updatePosition(view) {
         let width = _attributionImage.pixbuf.width;
         let height = _attributionImage.pixbuf.height;
-        let x = view.width  - width  - _LOGO_PADDING_X;
+        //let x = view.width  - width  - _LOGO_PADDING_X;
         /* TODO: ideally the attribution logo should be aligned to the left
          * side in RTL locales, but I couldn't get that working with Clutter
          * actor positioning, so adjust the padding to fit above the scale
          * for now
          */
-        let y = view.height - height -
-                (this._rtl ? _LOGO_PADDING_Y_RTL : _LOGO_PADDING_Y);
+        //let y = view.height - height -
+        //        (this._rtl ? _LOGO_PADDING_Y_RTL : _LOGO_PADDING_Y);
 
-        this.set_position(x, y);
+        // TODO: logo should be added to a GtkOverlay, I guess this should not be needed...
+        //this.set_position(x, y);
     }
 });
 
@@ -87,7 +86,7 @@ function _updateAttributionImage(source) {
 }
 
 function _createTileSource(source) {
-    let tileSource = new Champlain.NetworkTileSource({
+    let tileSource = new Shumate.NetworkTileSource({
         id: source.id,
         name: source.name,
         license: source.license,
@@ -95,7 +94,7 @@ function _createTileSource(source) {
         min_zoom_level: source.min_zoom_level,
         max_zoom_level: source.max_zoom_level,
         tile_size: source.tile_size,
-        renderer: new Champlain.ImageRenderer(),
+        //renderer: new Shumate.ImageRenderer(),
         uri_format: source.uri_format
     });
     tileSource.max_conns = source.max_connections;
@@ -106,18 +105,18 @@ function _createCachedSource(source) {
     let tileSource = _createTileSource(source);
     _updateAttributionImage(source);
 
-    let fileCache = new Champlain.FileCache({
+    let fileCache = new Shumate.FileCache({
         size_limit: _FILE_CACHE_SIZE_LIMIT,
-        renderer: new Champlain.ImageRenderer()
+        //renderer: new Shumate.ImageRenderer()
     });
 
-    let memoryCache = new Champlain.MemoryCache({
+    let memoryCache = new Shumate.MemoryCache({
         size_limit: _MEMORY_CACHE_SIZE_LIMIT,
-        renderer: new Champlain.ImageRenderer()
+        //renderer: new Shumate.ImageRenderer()
     });
 
-    let errorSource = new Champlain.NullTileSource({
-        renderer: new Champlain.ImageRenderer()
+    let errorSource = new Shumate.ErrorTileSource({
+        //renderer: new Shumate.ImageRenderer()
     });
 
     /*
@@ -125,7 +124,7 @@ function _createCachedSource(source) {
      * the next one in the chain tries instead. Until we get to the error
      * source.
      */
-    let sourceChain = new Champlain.MapSourceChain();
+    let sourceChain = new Shumate.MapSourceChain();
     sourceChain.push(errorSource);
     sourceChain.push(tileSource);
     sourceChain.push(fileCache);
diff --git a/src/mapView.js b/src/mapView.js
index d14b678a..e0c9fa9a 100644
--- a/src/mapView.js
+++ b/src/mapView.js
@@ -19,13 +19,11 @@
  * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
  */
 
-const Champlain = imports.gi.Champlain;
-const Clutter = imports.gi.Clutter;
 const GObject = imports.gi.GObject;
 const Geocode = imports.gi.GeocodeGlib;
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
-const GtkChamplain = imports.gi.GtkChamplain;
+const Shumate = imports.gi.Shumate;
 const Mainloop = imports.mainloop;
 
 const Application = imports.application;
@@ -59,6 +57,7 @@ var MapType = {
 };
 const _LOCATION_STORE_TIMEOUT = 500;
 const MapMinZoom = 2;
+const MapMaxZoom = 19;
 
 /*
  * Due to the mathematics of spherical mericator projection,
@@ -110,10 +109,10 @@ var MapView = GObject.registerClass({
         'going-to-user-location': {},
         'gone-to-user-location': {},
         'view-moved': {},
-        'marker-selected': { param_types: [Champlain.Marker] },
+        'marker-selected': { param_types: [Shumate.Marker] },
         'map-type-changed': { param_types: [GObject.TYPE_STRING] }
     },
-}, class MapView extends GtkChamplain.Embed {
+}, class MapView extends Shumate.View {
 
     get routingOpen() {
         return this._routingOpen || this._instructionMarkerLayer.visible;
@@ -149,7 +148,7 @@ var MapView = GObject.registerClass({
         delete params.mainWindow;
 
         this._storeId = 0;
-        this.view = this._initView();
+        this._initView();
         this._initLayers();
 
         this.setMapType(mapType);
@@ -166,117 +165,79 @@ var MapView = GObject.registerClass({
         this._connectRouteSignals();
     }
 
-    _initScale(view) {
-        this._scale = new Champlain.Scale({ visible: true });
-        this._scale.connect_view(view);
+    _initScale() {
+        this._scale = new Shumate.Scale({ viewport: this.get_viewport() });
+        // this._scale.connect_view();
 
         if (Utils.getMeasurementSystem() === Utils.METRIC_SYSTEM)
-            this._scale.unit = Champlain.Unit.KM;
+            this._scale.unit = Shumate.Unit.KM;
         else
-            this._scale.unit = Champlain.Unit.MILES;
+            this._scale.unit = Shumate.Unit.MILES;
 
-        this._scale.set_x_expand(true);
-        this._scale.set_y_expand(true);
-        this._scale.set_x_align(Clutter.ActorAlign.START);
-        this._scale.set_y_align(Clutter.ActorAlign.END);
-        view.add_child(this._scale);
+        // TODO: scale should be added to a GtkOverlay...
+        // view.add_child(this._scale);
     }
 
     _initView() {
-        let view = this.get_view();
+        let viewport = this.get_viewport();
 
-        view.min_zoom_level = MapMinZoom;
-        view.goto_animation_mode = Clutter.AnimationMode.EASE_IN_OUT_CUBIC;
-        view.reactive = true;
-        view.kinetic_mode = true;
-        view.horizontal_wrap = true;
+        Utils.debug('viewport: ' + viewport);
 
-        view.connect('notify::latitude', this._onViewMoved.bind(this));
+        viewport.min_zoom_level = MapMinZoom;
+        viewport.max_zoom_level = MapMaxZoom;
+
+        // this.goto_animation_mode = Clutter.AnimationMode.EASE_IN_OUT_CUBIC;
+        this.horizontal_wrap = true;
+
+        this.connect('notify::latitude', this._onViewMoved.bind(this));
         // switching map type will set view min-zoom-level from map source
-        view.connect('notify::min-zoom-level', () => {
-            if (view.min_zoom_level < MapMinZoom) {
-                view.min_zoom_level = MapMinZoom;
+        this.connect('notify::min-zoom-level', () => {
+            if (viewport.min_zoom_level < MapMinZoom) {
+                viewport.min_zoom_level = MapMinZoom;
             }
         });
 
+        Utils.debug('_initView 2');
         // if dark tiles is available, setup handler to switch style
         if (Service.getService().tiles.streetDark) {
             Application.settings.connect('changed::night-mode',
                                          this._onNightModeChanged.bind(this));
         }
 
+        Utils.debug('_initView 3');
+
         // if hybrid aerial tiles are available, setup handler to toggle
         if (Service.getService().tiles.hybridAerial) {
             Application.settings.connect('changed::hybrid-aerial',
                                          this._onHybridAerialChanged.bind(this));
         }
 
-        this._gtkSettings = Gtk.Settings.get_default();
-        this._gtkSettings.connect('notify::gtk-application-prefer-dark-theme',
-                            this._onPreferDarkThemeChanged.bind(this));
-        // set dark background if we start up in dark theme
-        if (this._gtkSettings.gtk_application_prefer_dark_theme) {
-            if (!this._darkBackgroud)
-                this._createDarkBackground();
-            view.set_background_pattern(this._darkBackground);
-        }
-
-        this._initScale(view);
-        return view;
-    }
-
-    /* handler to draw background for dark theme,
-     * theese three functions should not be needed later with a native GTK
-     * widget (Shumate)
-     */
-    _drawDarkBackground(canvas, cr, width, height) {
-        // set this arbitrarily to try to match the typical dark tile set
-        cr.setSourceRGB(0.2, 0.2, 0.2);
-        cr.rectangle(0, 0, width, height);
-        cr.fillPreserve();
-
-        return true;
-    }
-
-    _createDarkBackground() {
-        this._darkBackground = new Clutter.Canvas();
-        this._darkBackground.set_size(512, 512);
-        this._darkBackground.connect('draw',
-                                     this._drawDarkBackground.bind(this));
-        this._darkBackground.invalidate();
-    }
-
-    _onPreferDarkThemeChanged() {
-        if (this._gtkSettings.gtk_application_prefer_dark_theme) {
-            if (!this._darkBackgroud)
-                this._createDarkBackground();
-            this.view.set_background_pattern(this._darkBackground);
-        } else {
-            this.view.background_pattern = null;
-        }
+        Utils.debug('_initView 4');
+        this._initScale();
+        Utils.debug('_initView end');
     }
 
     _onNightModeChanged() {
         if (this._mapType === MapType.STREET) {
-            let overlay_sources = this.view.get_overlay_sources();
+            let overlay_sources = this.get_overlay_sources();
 
             if (Application.settings.get('night-mode'))
-                this.view.map_source = MapSource.createStreetDarkSource();
+                this.map_source = MapSource.createStreetDarkSource();
             else
-                this.view.map_source = MapSource.createStreetSource();
-            overlay_sources.forEach((source) => this.view.add_overlay_source(source, 255));
+                this.map_source = MapSource.createStreetSource();
+            overlay_sources.forEach((source) => this.add_overlay_source(source, 255));
         }
     }
 
     _onHybridAerialChanged() {
         if (this._mapType === MapType.AERIAL) {
-            let overlay_sources = this.view.get_overlay_sources();
+            let overlay_sources = this.get_overlay_sources();
 
             if (Application.settings.get('hybrid-aerial'))
-                this.view.map_source = MapSource.createHybridAerialSource();
+                this.map_source = MapSource.createHybridAerialSource();
             else
-                this.view.map_source = MapSource.createAerialSource();
-            overlay_sources.forEach((source) => this.view.add_overlay_source(source, 255));
+                this.map_source = MapSource.createAerialSource();
+            overlay_sources.forEach((source) => this.add_overlay_source(source, 255));
         }
     }
 
@@ -290,14 +251,14 @@ var MapView = GObject.registerClass({
                                               blue: blue * 255,
                                               green: green * 255,
                                               alpha: 255 });
-        let routeLayer = new Champlain.PathLayer({ stroke_width: width,
-                                                   stroke_color: strokeColor });
+        let routeLayer = new Shumate.PathLayer({ stroke_width: width,
+                                                 stroke_color: strokeColor });
         if (dashed)
             routeLayer.set_dash([DASHED_ROUTE_LINE_FILLED_LENGTH,
                                  DASHED_ROUTE_LINE_GAP_LENGTH]);
 
         this._routeLayers.push(routeLayer);
-        this.view.add_layer(routeLayer);
+        this.add_layer(routeLayer);
 
         return routeLayer;
     }
@@ -306,26 +267,24 @@ var MapView = GObject.registerClass({
         this._routeLayers.forEach((routeLayer) => {
             routeLayer.remove_all();
             routeLayer.visible = false;
-            this.view.remove_layer(routeLayer);
+            this.remove_layer(routeLayer);
         });
 
         this._routeLayers = [];
     }
 
     _initLayers() {
-        let mode = Champlain.SelectionMode.SINGLE;
+        this._userLocationLayer = new Shumate.MarkerLayer();
+        this.add_layer(this._userLocationLayer);
 
-        this._userLocationLayer = new Champlain.MarkerLayer({ selection_mode: mode });
-        this.view.add_layer(this._userLocationLayer);
+        this._placeLayer = new Shumate.MarkerLayer();
+        this.add_layer(this._placeLayer);
 
-        this._placeLayer = new Champlain.MarkerLayer({ selection_mode: mode });
-        this.view.add_layer(this._placeLayer);
+        this._instructionMarkerLayer = new Shumate.MarkerLayer();
+        this.add_layer(this._instructionMarkerLayer);
 
-        this._instructionMarkerLayer = new Champlain.MarkerLayer({ selection_mode: mode });
-        this.view.add_layer(this._instructionMarkerLayer);
-
-        this._annotationMarkerLayer = new Champlain.MarkerLayer({ selection_mode: mode });
-        this.view.add_layer(this._annotationMarkerLayer);
+        this._annotationMarkerLayer = new Shumate.MarkerLayer();
+        this.add_layer(this._annotationMarkerLayer);
 
         ShapeLayer.SUPPORTED_TYPES.push(GeoJSONShapeLayer.GeoJSONShapeLayer);
         ShapeLayer.SUPPORTED_TYPES.push(KmlShapeLayer.KmlShapeLayer);
@@ -335,8 +294,8 @@ var MapView = GObject.registerClass({
     }
 
     _ensureInstructionLayerAboveRouteLayers() {
-        this.view.remove_layer(this._instructionMarkerLayer);
-        this.view.add_layer(this._instructionMarkerLayer);
+        this.remove_layer(this._instructionMarkerLayer);
+        this.add_layer(this._instructionMarkerLayer);
     }
 
     _connectRouteSignals() {
@@ -396,7 +355,7 @@ var MapView = GObject.registerClass({
         if (this._mapType && this._mapType === mapType)
             return;
 
-        let overlay_sources = this.view.get_overlay_sources();
+        let overlay_sources = this.get_overlay_sources();
 
         this._mapType = mapType;
 
@@ -411,14 +370,15 @@ var MapView = GObject.registerClass({
             } else {
                 if (Service.getService().tiles.streetDark &&
                     Application.settings.get('night-mode')) {
-                    this.view.map_source = MapSource.createStreetDarkSource();
+                    this.map_source = MapSource.createStreetDarkSource();
                 } else {
-                    this.view.map_source = MapSource.createStreetSource();
+                    this.map_source = MapSource.createStreetSource();
                 }
             }
             if (!this._attribution) {
-                this._attribution = new MapSource.AttributionLogo(this.view);
-                this.view.add_child(this._attribution);
+                this._attribution = new MapSource.AttributionLogo(this);
+                // TODO: should add attribution logo to a GtkOverlay...
+                //this.view.add_child(this._attribution);
             }
 
             Application.settings.set('map-type', mapType);
@@ -543,7 +503,7 @@ var MapView = GObject.registerClass({
         let place =
             new Place.Place({ location: new Location.Location({ latitude: lat,
                                                                 longitude: lon }),
-                              initialZoom: this.view.zoom_level });
+                              initialZoom: this.get_viewport().zoom_level });
 
         new MapWalker.MapWalker(place, this).goTo(true);
     }
@@ -585,30 +545,34 @@ var MapView = GObject.registerClass({
 
     _goToStoredLocation() {
         let location = Application.settings.get('last-viewed-location');
+        let viewport = this.get_viewport();
 
         if (location.length === 2) {
             let [lat, lon] = location;
             let zoom = Application.settings.get('zoom-level');
 
-            if (zoom >= this.view.min_zoom_level &&
-                zoom <= this.view.max_zoom_level)
-                this.view.zoom_level = Application.settings.get('zoom-level');
+            Utils.debug('min_zoom_level: ' + viewport.min_zoom_level);
+            Utils.debug('max_zoom_level: ' + viewport.max_zoom_level);
+
+            if (zoom >= viewport.min_zoom_level &&
+                zoom <= viewport.max_zoom_level)
+                viewport.zoom_level = Application.settings.get('zoom-level');
             else
                 Utils.debug('Invalid initial zoom level: ' + zoom);
 
             if (lat >= MIN_LATITUDE && lat <= MAX_LATITUDE &&
                 lon >= MIN_LONGITUDE && lon <= MAX_LONGITUDE)
-                this.view.center_on(location[0], location[1]);
+                this.center_on(location[0], location[1]);
             else
                 Utils.debug('Invalid initial coordinates: ' + lat + ', ' + lon);
         } else {
             /* bounding box. for backwards compatibility, not used anymore */
-            let bbox = new Champlain.BoundingBox({ top: location[0],
+            let bbox = new Shumate.BoundingBox({ top: location[0],
                                                    bottom: location[1],
                                                    left: location[2],
                                                    right: location[3] });
-            this.view.connect("notify::realized", () => {
-                if (this.view.realized)
+            this.connect("notify::realized", () => {
+                if (this.realized)
                     this.gotoBBox(bbox, true);
             });
         }
diff --git a/src/osmAccountDialog.js b/src/osmAccountDialog.js
index b9a0ae7d..1c82ffa9 100644
--- a/src/osmAccountDialog.js
+++ b/src/osmAccountDialog.js
@@ -22,7 +22,8 @@
 
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const WebKit2 = imports.gi.WebKit2;
+// TODO: WebKit for GTK 4
+//const WebKit2 = imports.gi.WebKit2;
 
 const Application = imports.application;
 
diff --git a/src/photonParser.js b/src/photonParser.js
index 3c3a78b6..ab8ef657 100644
--- a/src/photonParser.js
+++ b/src/photonParser.js
@@ -22,7 +22,8 @@
 const _ = imports.gettext.gettext;
 
 const Geocode = imports.gi.GeocodeGlib;
-const GWeather = imports.gi.GWeather;
+// TODO: GWeather for GTK 4?
+//const GWeather = imports.gi.GWeather;
 
 const Address = imports.address;
 const OSMTypes = imports.osmTypes;
diff --git a/src/placeEntry.js b/src/placeEntry.js
index a1c4501a..23454f3c 100644
--- a/src/placeEntry.js
+++ b/src/placeEntry.js
@@ -89,13 +89,17 @@ var PlaceEntry = GObject.registerClass({
     }
 
     _init(props) {
+        Utils.debug('PlaceEntry::_init');
         let numVisible = props.num_visible || 6;
         delete props.num_visible;
         this._mapView = props.mapView;
         delete props.mapView;
 
-        if (!props.loupe)
-            props.primary_icon_name = null;
+        Utils.debug('PlaceEntry::_init 2');
+        // TODO: GtkSearchEntry always shows icon in GTK4, should we use a normal entry
+        // for the route case to not have search icons?
+        //if (!props.loupe)
+        //    props.primary_icon_name = null;
         delete props.loupe;
 
         let maxChars = props.maxChars;
@@ -104,19 +108,27 @@ var PlaceEntry = GObject.registerClass({
         this._matchRoute = props.matchRoute || false;
         delete props.matchRoute;
 
+        Utils.debug('PlaceEntry::_init 3');
+
         super._init(props);
 
+        Utils.debug('PlaceEntry::_init 4');
+
         this._filter = new Gtk.TreeModelFilter({ child_model: Application.placeStore });
         this._filter.set_visible_func(this._completionVisibleFunc.bind(this));
 
+        Utils.debug('PlaceEntry::_init 5');
+
         this._popover = this._createPopover(numVisible, maxChars);
 
+        Utils.debug('PlaceEntry::_init 6');
+
         this.connect('search-changed', this._onSearchChanged.bind(this));
 
         this._cache = {};
 
         // clear cache when view moves, as result are location-dependent
-        this._mapView.view.connect('notify::latitude', () => this._cache = {});
+        this._mapView.get_viewport().connect('notify::latitude', () => this._cache = {});
     }
 
     _onSearchChanged() {
@@ -166,21 +178,27 @@ var PlaceEntry = GObject.registerClass({
 
     _createPopover(numVisible, maxChars) {
         let popover = new PlacePopover.PlacePopover({ num_visible:   numVisible,
-                                                      relative_to:   this,
-                                                      maxChars:      maxChars});
+                                                      maxChars:      maxChars,
+                                                      parent:        this });
+
+        Utils.debug('_createPopover');
 
+        // TODO: how to do this in GTK4?
+        /*
         this.connect('size-allocate', (widget, allocation) => {
             // Magic number to make the alignment pixel perfect.
             let width_request = allocation.width + 20;
             // set at least 320 px width to avoid too narrow in the sidebar
             popover.width_request = Math.max(width_request, 320);
         });
+        */
 
         popover.connect('selected', (widget, place) => {
             this.place = place;
             popover.hide();
         });
 
+        Utils.debug('_createPopover 2');
         return popover;
     }
 
diff --git a/src/placePopover.js b/src/placePopover.js
index d3c1d006..df826f5e 100644
--- a/src/placePopover.js
+++ b/src/placePopover.js
@@ -24,6 +24,7 @@ const Application = imports.application;
 const PlaceListRow = imports.placeListRow;
 const PlaceStore = imports.placeStore;
 const SearchPopover = imports.searchPopover;
+const Utils = imports.utils;
 
 const _PLACE_ICON_SIZE = 20;
 
@@ -40,16 +41,18 @@ var PlacePopover = GObject.registerClass({
 }, class PlacePopover extends SearchPopover.SearchPopover {
 
     _init(props) {
+        Utils.debug('PlacePopover::_init');
         let numVisible = props.num_visible;
         delete props.num_visible;
 
         this._maxChars = props.maxChars;
         delete props.maxChars;
 
-        props.transitions_enabled = false;
+        Utils.debug('PlacePopover::_init 2');
+
         super._init(props);
 
-        this._entry = this.relative_to;
+        Utils.debug('PlacePopover::_init 3');
 
         this._list.connect('row-activated', (list, row) => {
             if (row)
diff --git a/src/routeEntry.js b/src/routeEntry.js
index ac2e2783..6292c3e0 100644
--- a/src/routeEntry.js
+++ b/src/routeEntry.js
@@ -35,7 +35,6 @@ var Type = {
 
 var RouteEntry = GObject.registerClass({
     Template: 'resource:///org/gnome/Maps/ui/route-entry.ui',
-    Children: [ 'iconEventBox' ],
     InternalChildren: [ 'entryGrid',
                         'icon',
                         'button',
diff --git a/src/routeQuery.js b/src/routeQuery.js
index 3b424ec3..dcbd66e2 100644
--- a/src/routeQuery.js
+++ b/src/routeQuery.js
@@ -25,6 +25,7 @@ const Geocode = imports.gi.GeocodeGlib;
 const Application = imports.application;
 const PlaceStore = imports.placeStore;
 const TransitOptions = imports.transitOptions;
+const Utils = imports.utils;
 
 var MAX_QUERY_POINTS = 10;
 
@@ -165,6 +166,7 @@ var RouteQuery = GObject.registerClass({
 
     _init(args) {
         super._init(args);
+        Utils.debug('RouteQuery::_init ' + this);
         this._points = [];
         this._time = null;
         this._date = null;
@@ -185,6 +187,8 @@ var RouteQuery = GObject.registerClass({
             throw new Error('Too many query points');
         let point = new QueryPoint();
 
+        Utils.debug('addPoint() ' + this);
+
         if (index === -1)
             index = this.points.length - 1;
 
@@ -200,9 +204,12 @@ var RouteQuery = GObject.registerClass({
             this.notify('points');
             this._latest = point;
         });
+        Utils.debug('addPoint() 2');
         this._latest = point;
         this.notify('points');
-        this.emit('point-added', point, index);
+        // TODO: temporarily comment this out to get a bit further...
+        //this.emit('point-added', point, index);
+        Utils.debug('addPoint() 3');
         return point;
     }
 
diff --git a/src/searchPopover.js b/src/searchPopover.js
index f848c5b5..5e49f7bd 100644
--- a/src/searchPopover.js
+++ b/src/searchPopover.js
@@ -24,6 +24,8 @@ const Gdk = imports.gi.Gdk;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 
+const Utils = imports.utils;
+
 /* Abstract search result popover that progagates keypress events from a
    focus-taking internal widget to the spawning search entry widget */
 var SearchPopover = GObject.registerClass({
@@ -31,16 +33,26 @@ var SearchPopover = GObject.registerClass({
 }, class SearchPopover extends Gtk.Popover {
 
     _init(props) {
+        Utils.debug('SearchPopover::_init');
+        let parent = props.parent;
+        delete props.parent;
+
         super._init(props);
 
-        this._entry = this.relative_to;
+        Utils.debug('SearchPopover::_init 2');
+
+        this.set_parent(parent);
+        this._entry = parent;
+
+        Utils.debug('SearchPopover::_init 3');
 
         // We need to propagate events to the listbox so that we can
         // keep typing while selecting a place. But we do not want to
         // propagate the 'enter' key press if there is a selection.
-        this._entry.connect('key-press-event',
-                            this._propagateKeys.bind(this));
-        this._entry.connect('button-press-event', () => this._list.unselect_all());
+        // TODO: replace with GtkGesture for GTK 4
+        //this._entry.connect('key-press-event',
+        //                    this._propagateKeys.bind(this));
+        //this._entry.connect('button-press-event', () => this._list.unselect_all());
     }
 
     _propagateKeys(entry, event) {
diff --git a/src/sendToDialog.js b/src/sendToDialog.js
index 9c3e9632..dec28acd 100644
--- a/src/sendToDialog.js
+++ b/src/sendToDialog.js
@@ -23,7 +23,8 @@ const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
-const GWeather = imports.gi.GWeather;
+// TODO: GWeather for GTK 4
+//const GWeather = imports.gi.GWeather;
 const Soup = imports.gi.Soup;
 
 const Application = imports.application;
diff --git a/src/sidebar.js b/src/sidebar.js
index d3f84316..db144499 100644
--- a/src/sidebar.js
+++ b/src/sidebar.js
@@ -69,13 +69,18 @@ var Sidebar = GObject.registerClass({
 }, class Sidebar extends Gtk.Revealer {
 
     _init(mapView) {
+        Utils.debug('Sidebar::_init');
         super._init({ transition_type: Gtk.RevealerTransitionType.SLIDE_LEFT });
 
+        Utils.debug('Sidebar::_init 2');
+
         this._mapView = mapView;
 
         this._query = Application.routeQuery;
         this._initInstructionList();
 
+        Utils.debug('Sidebar::_init 3');
+
         /* I could not get the custom GTK+ template widget to init properly
          * from the UI file, we also need to manually insert the transit
          * itinerary header widget into the GtkStack to get the correct
@@ -91,9 +96,13 @@ var Sidebar = GObject.registerClass({
                                         this._modeCarToggle,
                                         this._modeTransitToggle);
 
+        Utils.debug('Sidebar::_init 4');
+
         this._initQuerySignals();
+        Utils.debug('Sidebar::_init 5');
         this._query.addPoint(0);
         this._query.addPoint(1);
+        Utils.debug('Sidebar::_init 6');
         this._switchRoutingMode(Application.routeQuery.transportation);
         /* Enable/disable transit mode switch based on the presence of
          * public transit providers.
@@ -104,6 +113,8 @@ var Sidebar = GObject.registerClass({
          */
         if (!Application.routingDelegator.transitRouter.enabled)
             this._modeTransitToggle.destroy();
+
+        Utils.debug('end Sidebar::_init');
     }
 
     _initTransportationToggles(pedestrian, bike, car, transit) {
@@ -500,7 +511,8 @@ var Sidebar = GObject.registerClass({
 
     _clearInstructions() {
         let listBox = this._instructionList;
-        listBox.forall(listBox.remove.bind(listBox));
+        // TODO: GtkContainer is not available in GTK4, use get_first(), get_next(), or something like that
+        //listBox.foreach(listBox.remove.bind(listBox));
 
         this._instructionStack.visible_child = this._instructionWindow;
         this._timeInfo.label = '';
diff --git a/src/transitOptionsPanel.js b/src/transitOptionsPanel.js
index 6c23a3ee..0a43d2db 100644
--- a/src/transitOptionsPanel.js
+++ b/src/transitOptionsPanel.js
@@ -79,14 +79,16 @@ var TransitOptionsPanel = GObject.registerClass({
         /* trigger an update of the query time as soon as focus leave the time
          * entry, to allow the user to enter a time before selecting start
          * and destination without having to press enter */
-        this._transitTimeEntry.connect('focus-out-event',
-            this._onTransitTimeEntryActivated.bind(this));
-        this._transitDateButton.popover.get_child().connect('day-selected-double-click',
+        // TODO: how do we do this in GTK 4?
+        //this._transitTimeEntry.connect('focus-out-event',
+        //    this._onTransitTimeEntryActivated.bind(this));
+        this._transitDateButton.popover.get_child().connect('day-selected',
             this._onTransitDateCalenderDaySelected.bind(this));
-        this._transitDateButton.connect('toggled',
-            this._onTransitDateButtonToogled.bind(this));
-        this._transitParametersMenuButton.connect('toggled',
-            this._onTransitParametersToggled.bind(this))
+        // TODO: connect to 'closed' on the popover instead
+        //this._transitDateButton.connect('toggled',
+        //    this._onTransitDateButtonToogled.bind(this));
+        //this._transitParametersMenuButton.connect('toggled',
+        //    this._onTransitParametersToggled.bind(this))
     }
 
     _onTransitTimeOptionsComboboxChanged() {
diff --git a/src/utils.js b/src/utils.js
index b40707f6..14e15b2d 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -29,7 +29,8 @@ const GdkPixbuf = imports.gi.GdkPixbuf;
 const Geocode = imports.gi.GeocodeGlib;
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
-const GWeather = imports.gi.GWeather;
+// TODO: GWeather for GTK 4?
+//const GWeather = imports.gi.GWeather;
 const Soup = imports.gi.Soup;
 const ByteArray = imports.byteArray;
 
@@ -79,9 +80,9 @@ function once(obj, signal, callback) {
 function loadStyleSheet(file) {
     let provider = new Gtk.CssProvider();
     provider.load_from_file(file);
-    Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
-                                             provider,
-                                             Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+    Gtk.StyleContext.add_provider_for_display(Gdk.Display.get_default(),
+                                              provider,
+                                              Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
 }
 
 function addActions(actionMap, entries, settings = null) {


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