[baobab/wip/cdavis/gtk4: 1/2] Port to GTK4+libadwaita




commit e55269355905273ed4fc438ad5bdcf5cccc441fd
Author: Christopher Davis <christopherdavis gnome org>
Date:   Fri Oct 1 01:49:07 2021 -0700

    Port to GTK4+libadwaita
    
    This commit ports baobab to GTK and makes use of libadwaita
    widgets and styling.
    
    Things depending on Events have been reworked to use
    shortcuts and eventcontrollers, like drag and drop or
    the various shortcuts for the treeview.
    
    There have also been tweaks to the styling made to fit
    in better with the new Adwaita look and feel.

 build-aux/flatpak/org.gnome.baobab.json |   3 +-
 data/baobab.css                         |  18 +-
 data/ui/baobab-excluded-row.ui          |  24 +--
 data/ui/baobab-folder-display.ui        |   2 -
 data/ui/baobab-location-list.ui         |  12 +-
 data/ui/baobab-location-row.ui          |  70 +++-----
 data/ui/baobab-main-window.ui           | 287 ++++++++++++++------------------
 data/ui/baobab-pathbutton.ui            |   3 -
 data/ui/baobab-preferences-dialog.ui    |  13 +-
 meson.build                             |   4 +-
 src/baobab-application.vala             |  10 +-
 src/baobab-cellrenderers.vala           |  62 +------
 src/baobab-chart.vala                   | 148 ++++++++--------
 src/baobab-location-list.vala           |  15 +-
 src/baobab-pathbar.vala                 |   6 +-
 src/baobab-preferences-dialog.vala      |  25 +--
 src/baobab-ringschart.vala              |   7 +-
 src/baobab-scanner.vala                 |   2 +-
 src/baobab-window.vala                  | 235 +++++++++++---------------
 19 files changed, 397 insertions(+), 549 deletions(-)
---
diff --git a/build-aux/flatpak/org.gnome.baobab.json b/build-aux/flatpak/org.gnome.baobab.json
index e5fb1f7..46478c4 100644
--- a/build-aux/flatpak/org.gnome.baobab.json
+++ b/build-aux/flatpak/org.gnome.baobab.json
@@ -20,7 +20,8 @@
         "--talk-name=org.gtk.vfs",
         "--talk-name=org.gtk.vfs.*",
         "--system-talk-name=org.freedesktop.hostname1",
-        "--share=network"
+        "--share=network",
+        "--device=dri"
     ],
     "build-options" : {
         "cflags" : "-O2 -g",
diff --git a/data/baobab.css b/data/baobab.css
index bfea7a6..093efb9 100644
--- a/data/baobab.css
+++ b/data/baobab.css
@@ -76,8 +76,8 @@ window.background stack treeview:hover:not(:selected) {
 
 .pathbar button {
     margin: 0;
-    border-width: 0 1px 0 0;
     border-radius: 0px;
+    box-shadow: 1px 0px @borders;
 }
 
 .pathbar button:first-child {
@@ -103,10 +103,15 @@ window infobar.error {
 @define-color level_color_hi #e0e2dd;
 
 @define-color chart_borders darker(@borders);
-ringschart {
-    padding: 13px 13px 13px 13px;
+.chart-grid:not(:dir(rtl)) {
+  box-shadow: 1px 0px inset @chart_borders;
+}
+
+.chart-grid:dir(rtl) {
+  box-shadow: -1px 0px inset @borders;
 }
 
+
 @define-color tooltip_bg_color rgba(0, 0, 0, 0.8);
 ringschart.subfolder-tip {
     color: white;
@@ -115,6 +120,9 @@ ringschart.subfolder-tip {
     padding: 3px 3px 3px 3px;
 }
 
-treemap {
-  border: solid 1px @chart_borders;
+:drop(active) .contents {
+  outline-style: solid;
+  outline-width: 3px;
+  outline-color: alpha(@accent_bg_color, 0.5);
+  outline-offset: -3px;
 }
diff --git a/data/ui/baobab-excluded-row.ui b/data/ui/baobab-excluded-row.ui
index a5d48f9..a5b0a9c 100644
--- a/data/ui/baobab-excluded-row.ui
+++ b/data/ui/baobab-excluded-row.ui
@@ -1,35 +1,25 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <template class="BaobabExcludedRow" parent="GtkListBoxRow">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
     <property name="activatable">False</property>
     <child>
       <object class="GtkGrid">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="margin">12</property>
+        <property name="margin_start">12</property>
+        <property name="margin_end">12</property>
+        <property name="margin_top">12</property>
+        <property name="margin_bottom">12</property>
         <child>
           <object class="GtkLabel" id="name_label">
-            <property name="visible">True</property>
-            <property name="hexpand">True</property>
             <property name="halign">start</property>
             <property name="ellipsize">end</property>
           </object>
         </child>
         <child>
           <object class="GtkButton" id="remove_button">
-            <property name="visible">True</property>
+            <property name="hexpand">True</property>
+            <property name="halign">end</property>
             <property name="valign">center</property>
-            <style>
-              <class name="image-button"/>
-            </style>
-            <child>
-              <object class="GtkImage">
-                <property name="visible">True</property>
-                <property name="icon_name">list-remove-symbolic</property>
-              </object>
-            </child>
+            <property name="icon_name">list-remove-symbolic</property>
           </object>
         </child>
       </object>
diff --git a/data/ui/baobab-folder-display.ui b/data/ui/baobab-folder-display.ui
index a80b246..7e585c7 100644
--- a/data/ui/baobab-folder-display.ui
+++ b/data/ui/baobab-folder-display.ui
@@ -3,8 +3,6 @@
 <interface>
   <requires lib="gtk+" version="3.22"/>
   <template class="BaobabFolderDisplay" parent="GtkTreeView">
-    <property name="visible">True</property>
-    <property name="can_focus">True</property>
     <property name="activate_on_single_click">True</property>
     <child internal-child="selection">
       <object class="GtkTreeSelection" id="treeview_selection">
diff --git a/data/ui/baobab-location-list.ui b/data/ui/baobab-location-list.ui
index ec3713d..8669c67 100644
--- a/data/ui/baobab-location-list.ui
+++ b/data/ui/baobab-location-list.ui
@@ -2,18 +2,18 @@
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
   <template class="BaobabLocationList" parent="GtkBox">
-    <property name="visible">True</property>
     <property name="orientation">vertical</property>
     <property name="spacing">32</property>
-    <property name="margin">32</property>
+    <property name="margin_start">32</property>
+    <property name="margin_end">32</property>
+    <property name="margin_top">32</property>
+    <property name="margin_bottom">32</property>
     <child>
       <object class="GtkBox" id="local_box">
-        <property name="visible">True</property>
         <property name="orientation">vertical</property>
         <property name="spacing">6</property>
         <child>
           <object class="GtkLabel" id="local_label">
-            <property name="visible">True</property>
             <property name="halign">start</property>
             <property name="label" translatable="yes">This Computer</property>
             <style>
@@ -23,7 +23,6 @@
         </child>
         <child>
           <object class="GtkListBox" id="local_list_box">
-            <property name="visible">True</property>
             <property name="selection_mode">none</property>
             <style>
               <class name="view"/>
@@ -35,12 +34,10 @@
     </child>
     <child>
       <object class="GtkBox" id="remote_box">
-        <property name="visible">True</property>
         <property name="orientation">vertical</property>
         <property name="spacing">6</property>
         <child>
           <object class="GtkLabel" id="remote_label">
-            <property name="visible">True</property>
             <property name="halign">start</property>
             <property name="label" translatable="yes">Remote Locations</property>
             <style>
@@ -50,7 +47,6 @@
         </child>
         <child>
           <object class="GtkListBox" id="remote_list_box">
-            <property name="visible">True</property>
             <property name="selection_mode">none</property>
             <style>
               <class name="view"/>
diff --git a/data/ui/baobab-location-row.ui b/data/ui/baobab-location-row.ui
index 115cae2..e177da1 100644
--- a/data/ui/baobab-location-row.ui
+++ b/data/ui/baobab-location-row.ui
@@ -2,11 +2,8 @@
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
   <template class="BaobabLocationRow" parent="GtkListBoxRow">
-    <property name="visible">True</property>
     <child>
       <object class="GtkBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
         <property name="margin-top">6</property>
         <property name="margin-bottom">12</property>
         <property name="margin-start">12</property>
@@ -14,39 +11,32 @@
         <property name="spacing">12</property>
         <child>
           <object class="GtkGrid" id="grid">
-            <property name="visible">True</property>
             <property name="column_spacing">12</property>
             <child>
               <object class="GtkImage" id="image">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
                 <property name="pixel_size">64</property>
+                <layout>
+                  <property name="column">0</property>
+                  <property name="row">0</property>
+                  <property name="row_span">2</property>
+                </layout>
               </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">0</property>
-                <property name="height">2</property>
-              </packing>
             </child>
             <child>
               <object class="GtkLabel" id="name_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
                 <property name="halign">start</property>
                 <property name="valign">end</property>
                 <property name="hexpand">True</property>
                 <property name="use_markup">True</property>
                 <property name="ellipsize">end</property>
+                <layout>
+                  <property name="column">1</property>
+                  <property name="row">0</property>
+                </layout>
               </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">0</property>
-              </packing>
             </child>
             <child>
               <object class="GtkLabel" id="path_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
                 <property name="halign">start</property>
                 <property name="valign">start</property>
                 <property name="hexpand">True</property>
@@ -54,59 +44,53 @@
                 <style>
                   <class name="dim-label"/>
                 </style>
+                <layout>
+                  <property name="column">1</property>
+                  <property name="row">1</property>
+                </layout>
               </object>
-              <packing>
-                <property name="left_attach">1</property>
-                <property name="top_attach">1</property>
-              </packing>
             </child>
             <child>
               <object class="GtkLabel" id="available_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
                 <property name="halign">end</property>
                 <property name="valign">end</property>
+                <layout>
+                  <property name="column">2</property>
+                  <property name="row">0</property>
+                </layout>
               </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="top_attach">0</property>
-              </packing>
             </child>
             <child>
               <object class="GtkLabel" id="total_size_label">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
                 <property name="halign">end</property>
                 <property name="valign">start</property>
                 <style>
                   <class name="dim-label"/>
                 </style>
+                <layout>
+                  <property name="column">2</property>
+                  <property name="row">1</property>
+                </layout>
               </object>
-              <packing>
-                <property name="left_attach">2</property>
-                <property name="top_attach">1</property>
-              </packing>
             </child>
             <child>
               <object class="GtkLevelBar" id="usage_bar">
-                <property name="can_focus">False</property>
+                <property name="visible">False</property>
                 <property name="valign">start</property>
                 <property name="margin_top">6</property>
                 <property name="margin_bottom">6</property>
                 <property name="hexpand">True</property>
+                <layout>
+                  <property name="column">0</property>
+                  <property name="row">2</property>
+                  <property name="column_span">3</property>
+                </layout>
               </object>
-              <packing>
-                <property name="left_attach">0</property>
-                <property name="top_attach">2</property>
-                <property name="width">3</property>
-              </packing>
             </child>
           </object>
         </child>
         <child>
           <object class="GtkImage">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
             <property name="icon_name">go-next-symbolic</property>
             <property name="width_request">36</property>
             <style>
diff --git a/data/ui/baobab-main-window.ui b/data/ui/baobab-main-window.ui
index e1cd76a..355cbe0 100644
--- a/data/ui/baobab-main-window.ui
+++ b/data/ui/baobab-main-window.ui
@@ -31,142 +31,83 @@
       </item>
     </section>
   </menu>
-  <object class="GtkPopoverMenu" id="treeview_popover_menu">
-    <property name="can_focus">False</property>
-    <property name="relative-to">treeview</property>
-    <property name="position">bottom</property>
-  </object>
-  <template class="BaobabWindow" parent="HdyApplicationWindow">
+  <template class="BaobabWindow" parent="AdwApplicationWindow">
     <property name="title" translatable="yes">Disk Usage Analyzer</property>
     <property name="icon_name">baobab</property>
     <child>
       <object class="GtkBox" id="vbox">
       <property name="orientation">vertical</property>
-      <property name="visible">True</property>
       <child>
-        <object class="HdyHeaderBar" id="header_bar">
-          <property name="visible">True</property>
-          <property name="can_focus">False</property>
-          <property name="show_close_button">True</property>
-          <style>
-            <class name="titlebar"/>
-          </style>
+        <object class="AdwHeaderBar" id="header_bar">
           <child>
             <object class="GtkButton" id="back_button">
               <property name="valign">center</property>
-              <property name="can_focus">True</property>
               <property name="action_name">win.show-home-page</property>
+              <property name="icon_name">go-previous-symbolic</property>
               <property name="tooltip_text" translatable="yes">Go back to location list</property>
-              <style>
-                <class name="image-button"/>
-              </style>
-              <child>
-                <object class="GtkImage" id="back_button_image">
-                  <property name="visible">True</property>
-                  <property name="icon_name">go-previous-symbolic</property>
-                  <property name="icon_size">1</property>
-                </object>
-              </child>
             </object>
-            <packing>
-              <property name="pack_type">start</property>
-            </packing>
           </child>
-          <child>
-            <object class="GtkButton" id="reload_button">
-              <property name="valign">center</property>
-              <property name="can_focus">True</property>
-              <property name="action_name">win.reload</property>
-              <property name="tooltip_text" translatable="yes">Rescan current location</property>
-              <style>
-                <class name="image-button"/>
-              </style>
-              <child>
-                <object class="GtkImage" id="reload_button_image">
-                  <property name="visible">True</property>
-                  <property name="icon_size">1</property>
-                  <property name="icon_name">view-refresh-symbolic</property>
-                </object>
-              </child>
-            </object>
-            <packing>
-              <property name="pack_type">end</property>
-            </packing>
-          </child>
-          <child>
+          <child type="end">
             <object class="GtkMenuButton" id="menu_button">
               <property name="valign">center</property>
               <property name="menu_model">primarymenu</property>
-              <property name="action_name">win.show-primary-menu</property>
+              <property name="icon_name">open-menu-symbolic</property>
               <property name="direction">none</property>
-              <style>
-                <class name="image-button"/>
-              </style>
             </object>
-            <packing>
-              <property name="pack_type">end</property>
-            </packing>
+          </child>
+          <child type="end">
+            <object class="GtkButton" id="reload_button">
+              <property name="valign">center</property>
+              <property name="action_name">win.reload</property>
+              <property name="icon_name">view-refresh-symbolic</property>
+              <property name="tooltip_text" translatable="yes">Rescan current location</property>
+            </object>
           </child>
         </object>
       </child>
       <child>
         <object class="GtkGrid" id="window_contents">
-          <property name="visible">True</property>
           <property name="orientation">vertical</property>
           <child>
             <object class="GtkInfoBar" id="infobar">
               <property name="visible">False</property>
-              <child internal-child="content_area">
+              <child>
                 <object class="GtkBox" id="infobar_content_area">
-                  <property name="visible">True</property>
-                  <property name="can_focus">False</property>
-                  <property name="border_width">8</property>
+                  <property name="margin_start">8</property>
+                  <property name="margin_end">8</property>
+                  <property name="margin_top">8</property>
+                  <property name="margin_bottom">8</property>
                   <property name="orientation">vertical</property>
                   <property name="spacing">16</property>
                   <property name="hexpand">True</property>
                   <child>
                     <object class="GtkLabel" id="infobar_primary_label">
-                      <property name="visible">True</property>
-                      <property name="can_focus">True</property>
                       <property name="selectable">True</property>
                       <property name="use-markup">True</property>
                       <property name="halign">GTK_ALIGN_START</property>
                       <property name="wrap">True</property>
                     </object>
-                    <packing>
-                      <property name="expand">False</property>
-                      <property name="fill">True</property>
-                      <property name="position">0</property>
-                    </packing>
                   </child>
                   <child>
                     <object class="GtkLabel" id="infobar_secondary_label">
-                      <property name="visible">True</property>
-                      <property name="can_focus">True</property>
                       <property name="selectable">True</property>
                       <property name="use-markup">True</property>
                       <property name="halign">GTK_ALIGN_START</property>
                       <property name="wrap">True</property>
                     </object>
-                    <packing>
-                      <property name="expand">False</property>
-                      <property name="fill">True</property>
-                      <property name="position">1</property>
-                    </packing>
                   </child>
                 </object>
               </child>
-              <child internal-child="action_area">
-                <object class="GtkButtonBox" id="infobar_action_area">
-                  <property name="visible">True</property>
-                  <property name="can_focus">False</property>
-                  <property name="border_width">5</property>
+              <child type="action">
+                <object class="GtkBox" id="infobar_action_area">
+                  <property name="margin_start">5</property>
+                  <property name="margin_end">5</property>
+                  <property name="margin_top">5</property>
+                  <property name="margin_bottom">5</property>
                   <property name="orientation">vertical</property>
                   <property name="spacing">6</property>
-                  <property name="layout_style">end</property>
                   <child>
                     <object class="GtkButton" id="infobar_close_button">
-                      <property name="visible">True</property>
                       <property name="label" translatable="yes">Close</property>
                     </object>
                   </child>
@@ -176,17 +117,12 @@
           </child>
           <child>
             <object class="GtkStack" id="main_stack">
-              <property name="visible">True</property>
-              <property name="can_focus">False</property>
               <property name="transition_type">slide-left-right</property>
               <child>
                 <object class="GtkGrid" id="home_page">
-                  <property name="can_focus">False</property>
-                  <property name="visible">True</property>
                   <property name="orientation">vertical</property>
                   <child>
                     <object class="GtkScrolledWindow" id="location_scrolled_window">
-                      <property name="visible">True</property>
                       <property name="vexpand">True</property>
                       <property name="hexpand">True</property>
                       <property name="hscrollbar-policy">never</property>
@@ -202,40 +138,34 @@
               </child>
               <child>
                 <object class="GtkGrid" id="result_page">
-                  <property name="visible">True</property>
-                  <property name="can_focus">False</property>
                   <property name="column_homogeneous">True</property>
                   <child>
-                    <object class="GtkFrame" id="folder_display_frame">
-                      <property name="visible">true</property>
-                      <child>
-                        <object class="BaobabFolderDisplay" id="folder_display"/>
-                      </child>
+                    <object class="BaobabFolderDisplay" id="folder_display">
+                      <layout>
+                        <property name="row">0</property>
+                        <property name="column">0</property>
+                        <property name="column_span">1</property>
+                        <property name="row_span">1</property>
+                      </layout>
                     </object>
-                    <packing>
-                      <property name="left_attach">0</property>
-                      <property name="top_attach">0</property>
-                      <property name="width">1</property>
-                      <property name="height">1</property>
-                    </packing>
                   </child>
                   <child>
                     <object class="GtkScrolledWindow" id="scrolled_window">
-                      <property name="visible">True</property>
-                      <property name="can_focus">True</property>
-                      <property name="shadow_type">in</property>
                       <property name="hexpand">True</property>
                       <property name="vexpand">True</property>
                       <property name="hscrollbar-policy">never</property>
                       <child>
                         <object class="GtkTreeView" id="treeview">
-                          <property name="visible">True</property>
-                          <property name="can_focus">True</property>
                           <property name="headers_visible">false</property>
                           <property name="activate_on_single_click">True</property>
                           <child internal-child="selection">
                             <object class="GtkTreeSelection" id="treeview_selection1"/>
                           </child>
+                          <child>
+                            <object class="GtkPopoverMenu" id="treeview_popover_menu">
+                              <property name="position">bottom</property>
+                            </object>
+                          </child>
                           <child>
                             <object class="GtkTreeViewColumn" id="folder_column">
                               <property name="title" translatable="yes">Folder</property>
@@ -243,13 +173,12 @@
                               <property name="reorderable">True</property>
                               <property name="sort_column_id">0</property>
                               <child>
-                                <object class="BaobabCellRendererProgress" id="usage_column_bar_renderer">
+                                <object class="GtkCellRendererProgress" id="usage_column_bar_renderer">
                                   <property name="xpad">4</property>
                                   <property name="ypad">4</property>
                                 </object>
                                 <attributes>
                                   <attribute name="value">1</attribute>
-                                  <attribute name="state">6</attribute>
                                 </attributes>
                               </child>
                               <child>
@@ -311,113 +240,153 @@
                               </child>
                             </object>
                           </child>
+                          <child>
+                            <object class="GtkGestureClick" id="treeview_right_click_gesture">
+                              <property name="button">3</property>
+                            </object>
+                          </child>
+                          <child>
+                            <object class="GtkShortcutController">
+                              <child>
+                                <object class="GtkShortcut">
+                                  <property name="trigger">Menu</property>
+                                  <property name="action">action(win.show-treeview-popover)</property>
+                                </object>
+                              </child>
+                              <child>
+                                <object class="GtkShortcut">
+                                  <property name="trigger">Right</property>
+                                  <property name="action">action(win.treeview-expand-row)</property>
+                                </object>
+                              </child>
+                              <child>
+                                <object class="GtkShortcut">
+                                  <property name="trigger">Left</property>
+                                  <property name="action">action(win.treeview-collapse-row)</property>
+                                </object>
+                              </child>
+                              <child>
+                                <object class="GtkShortcut">
+                                  <property name="trigger">&lt;Alt&gt;Up</property>
+                                  <property name="action">action(win.treeview-go-up)</property>
+                                </object>
+                              </child>
+                            </object>
+                          </child>
                         </object>
                       </child>
+                      <layout>
+                        <property name="column">0</property>
+                        <property name="row">1</property>
+                        <property name="column_span">1</property>
+                        <property name="row_span">1</property>
+                      </layout>
                     </object>
-                    <packing>
-                      <property name="left_attach">0</property>
-                      <property name="top_attach">1</property>
-                      <property name="width">1</property>
-                      <property name="height">1</property>
-                    </packing>
                   </child>
                   <child>
                     <object class="GtkGrid" id="chart_grid">
-                      <property name="visible">True</property>
-                      <property name="can_focus">False</property>
                       <property name="hexpand">True</property>
                       <property name="vexpand">True</property>
+                      <property name="css_classes">chart-grid</property>
                       <child>
                         <object class="GtkStack" id="spinner_stack">
-                          <property name="visible">True</property>
                           <child>
                             <object class="GtkStack" id="chart_stack">
-                              <property name="visible">True</property>
-                              <property name="can_focus">True</property>
                               <property name="transition_type">crossfade</property>
                               <child>
-                                <object class="BaobabRingschart" id="rings_chart">
-                                  <property name="visible">True</property>
-                                  <property name="hexpand">True</property>
-                                  <property name="vexpand">True</property>
-                                </object>
-                                <packing>
+                                <object class="GtkStackPage">
                                   <property name="name">rings</property>
                                   <property name="title" translatable="yes">Rings Chart</property>
                                   <property name="icon_name">view-ringschart-symbolic</property>
-                                </packing>
+                                  <property name="child">
+                                    <object class="BaobabRingschart" id="rings_chart">
+                                      <property name="hexpand">True</property>
+                                      <property name="vexpand">True</property>
+                                    </object>
+                                  </property>
+                                </object>
                               </child>
                               <child>
-                                <object class="BaobabTreemap" id="treemap_chart">
-                                  <property name="visible">True</property>
-                                  <property name="hexpand">True</property>
-                                  <property name="vexpand">True</property>
-                                </object>
-                                <packing>
+                                <object class="GtkStackPage">
                                   <property name="name">treemap</property>
                                   <property name="title" translatable="yes">Treemap Chart</property>
                                   <property name="icon_name">view-treemap-symbolic</property>
-                                </packing>
+                                  <property name="child">
+                                    <object class="BaobabTreemap" id="treemap_chart">
+                                      <property name="hexpand">True</property>
+                                      <property name="vexpand">True</property>
+                                    </object>
+                                  </property>
+                                </object>
                               </child>
                             </object>
                           </child>
                           <child>
                             <object class="GtkSpinner" id="spinner">
-                              <property name="visible">True</property>
-                              <property name="can_focus">False</property>
                               <property name="width_request">128</property>
                               <property name="height_request">128</property>
                               <property name="halign">GTK_ALIGN_CENTER</property>
                               <property name="valign">GTK_ALIGN_CENTER</property>
                             </object>
                           </child>
+                          <layout>
+                            <property name="column">0</property>
+                            <property name="row">0</property>
+                            <property name="column_span">1</property>
+                            <property name="row_span">1</property>
+                          </layout>
                         </object>
-                        <packing>
-                          <property name="left_attach">0</property>
-                          <property name="top_attach">0</property>
-                          <property name="width">1</property>
-                          <property name="height">1</property>
-                        </packing>
                       </child>
                       <child>
                         <object class="GtkActionBar" id="chart_action_bar">
-                        <property name="visible">True</property>
                           <child type="center">
                             <object class="GtkStackSwitcher" id="chart_stack_switcher">
-                              <property name="visible">True</property>
                               <property name="stack">chart_stack</property>
                             </object>
                           </child>
+                          <layout>
+                            <property name="column">0</property>
+                            <property name="row">1</property>
+                            <property name="column_span">1</property>
+                            <property name="row_span">1</property>
+                          </layout>
                         </object>
-                        <packing>
-                          <property name="left_attach">0</property>
-                          <property name="top_attach">1</property>
-                          <property name="width">1</property>
-                          <property name="height">1</property>
-                        </packing>
                       </child>
+                      <layout>
+                        <property name="column">1</property>
+                        <property name="row">0</property>
+                        <property name="column_span">1</property>
+                        <property name="row_span">2</property>
+                      </layout>
                     </object>
-                    <packing>
-                      <property name="left_attach">1</property>
-                      <property name="top_attach">0</property>
-                      <property name="width">1</property>
-                      <property name="height">2</property>
-                    </packing>
                   </child>
                 </object>
               </child>
+              <style>
+                <class name="contents"/>
+              </style>
             </object>
           </child>
         </object>
-        <packing>
-          <property name="pack_type">end</property>
-        </packing>
       </child>
     </object>
   </child>
+    <child>
+      <object class="GtkEventControllerFocus" id="focus_controller"/>
+    </child>
+    <child>
+      <object class="GtkDropTarget" id="drop_target">
+        <property name="actions">copy</property>
+      </object>
+    </child>
+    <child>
+      <object class="GtkGestureClick" id="back_gesture">
+        <!-- The back mouse button -->
+        <property name="button">8</property>
+      </object>
+    </child>
   </template>
   <object class="BaobabPathbar" id="pathbar">
-    <property name="visible">True</property>
     <property name="valign">center</property>
     <property name="width_request">700</property>
     <style>
diff --git a/data/ui/baobab-pathbutton.ui b/data/ui/baobab-pathbutton.ui
index 90cf5f7..25eea39 100644
--- a/data/ui/baobab-pathbutton.ui
+++ b/data/ui/baobab-pathbutton.ui
@@ -2,10 +2,8 @@
 <interface>
   <!-- interface-requires gtk+ 3.0 -->
   <template class="BaobabPathButton" parent="GtkButton">
-    <property name="visible">True</property>
     <child>
       <object class="GtkBox" id="box">
-        <property name="visible">True</property>
         <child>
           <object class="GtkImage" id="icon">
             <property name="margin-end">8</property>
@@ -13,7 +11,6 @@
         </child>
         <child>
           <object class="GtkLabel" id="label">
-            <property name="visible">True</property>
             <property name="ellipsize">middle</property>
             <property name="max_width_chars">15</property>
           </object>
diff --git a/data/ui/baobab-preferences-dialog.ui b/data/ui/baobab-preferences-dialog.ui
index 4e683a9..e43eecd 100644
--- a/data/ui/baobab-preferences-dialog.ui
+++ b/data/ui/baobab-preferences-dialog.ui
@@ -2,23 +2,16 @@
 <!-- Generated with glade 3.22.0 -->
 <interface>
   <requires lib="gtk+" version="3.22"/>
-  <template class="BaobabPreferencesDialog" parent="HdyPreferencesWindow">
-    <property name="can_focus">False</property>
-    <property name="type_hint">dialog</property>
+  <template class="BaobabPreferencesDialog" parent="AdwPreferencesWindow">
     <property name="title" translatable="yes">Preferences</property>
     <property name="search_enabled">False</property>
     <child>
-      <object class="HdyPreferencesPage">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
+      <object class="AdwPreferencesPage">
         <child>
-          <object class="HdyPreferencesGroup">
-            <property name="visible">True</property>
+          <object class="AdwPreferencesGroup">
             <property name="title" translatable="yes">Locations to Ignore</property>
             <child>
               <object class="GtkListBox" id="excluded_list_box">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
                 <property name="selection_mode">none</property>
                 <style>
                   <class name="content"/>
diff --git a/meson.build b/meson.build
index 4602e03..c481a66 100644
--- a/meson.build
+++ b/meson.build
@@ -12,8 +12,8 @@ python = import('python')
 glib = dependency('glib-2.0', version: '>=2.44')
 gio = dependency('gio-2.0', version: '>=2.44')
 gobject = dependency('gobject-2.0', version: '>=2.44')
-gtk = dependency('gtk+-3.0', version: '>=3.24.1')
-libhandy = dependency('libhandy-1', version: '>=1.0.0')
+gtk = dependency('gtk4', version: '>=4.4.0')
+libhandy = dependency('libadwaita-1', version: '>=1.0.0')
 
 cc = meson.get_compiler('c')
 math = cc.find_library('m', required: false)
diff --git a/src/baobab-application.vala b/src/baobab-application.vala
index 9db69fe..eed5846 100644
--- a/src/baobab-application.vala
+++ b/src/baobab-application.vala
@@ -54,11 +54,6 @@ namespace Baobab {
         void ensure_window () {
             if (window == null) {
                 window = new Window (this);
-
-                window.focus_in_event.connect (() => {
-                    withdraw_notification ("scan-completed");
-                    return false;
-                });
             }
         }
 
@@ -80,13 +75,12 @@ namespace Baobab {
         protected override void startup () {
             base.startup ();
 
-            Hdy.init ();
-            Hdy.StyleManager.get_default ().color_scheme = PREFER_LIGHT;
+            Adw.init ();
 
             // Load custom CSS
             var css_provider = new Gtk.CssProvider ();
             css_provider.load_from_resource ("/org/gnome/baobab/baobab.css");
-            Gtk.StyleContext.add_provider_for_screen (Gdk.Screen.get_default (), css_provider, 
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+            Gtk.StyleContext.add_provider_for_display (Gdk.Display.get_default (), css_provider, 
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
 
             set_accels_for_action ("win.show-home-page", { "<Alt>Left" });
             set_accels_for_action ("win.show-primary-menu", { "F10" });
diff --git a/src/baobab-cellrenderers.vala b/src/baobab-cellrenderers.vala
index 23bae81..c7580bc 100644
--- a/src/baobab-cellrenderers.vala
+++ b/src/baobab-cellrenderers.vala
@@ -85,7 +85,7 @@ namespace Baobab {
             }
         }
 
-        protected override void render (Cairo.Context cr, Gtk.Widget widget, Gdk.Rectangle background_area, 
Gdk.Rectangle cell_area, Gtk.CellRendererState flags) {
+        protected override void snapshot (Gtk.Snapshot snp, Gtk.Widget widget, Gdk.Rectangle 
background_area, Gdk.Rectangle cell_area, Gtk.CellRendererState flags) {
             var context = widget.get_style_context ();
 
             context.save ();
@@ -101,7 +101,7 @@ namespace Baobab {
                 break;
             }
 
-            base.render (cr, widget, background_area, cell_area, flags);
+            base.snapshot (snp, widget, background_area, cell_area, flags);
 
             context.restore ();
         }
@@ -135,62 +135,4 @@ namespace Baobab {
             }
         }
     }
-
-    public class CellRendererProgress : Gtk.CellRendererProgress {
-        public Scanner.State state { set; get; }
-
-        public override void render (Cairo.Context cr, Gtk.Widget widget, Gdk.Rectangle background_area, 
Gdk.Rectangle cell_area, Gtk.CellRendererState flags) {
-            if (state == Scanner.State.ERROR) {
-                return;
-            }
-
-            int xpad;
-            int ypad;
-            get_padding (out xpad, out ypad);
-
-            var x = cell_area.x + xpad;
-            var y = cell_area.y + ypad;
-            var w = cell_area.width - xpad * 2;
-            var h = cell_area.height - ypad * 2;
-
-            var context = widget.get_style_context ();
-
-            context.save ();
-            context.add_class ("baobab-level-cell");
-
-            context.render_background (cr, x, y, w, h);
-            context.render_frame (cr, x, y, w, h);
-
-            var border = context.get_border (Gtk.StateFlags.NORMAL);
-            x += border.left;
-            y += border.top;
-            w -= border.left + border.right;
-            h -= border.top + border.bottom;
-
-            border = context.get_padding (Gtk.StateFlags.NORMAL);
-            x += border.left;
-            y += border.top;
-            w -= border.left + border.right;
-            h -= border.top + border.bottom;
-
-            var percent = value;
-            var perc_w = (w * percent) / 100;
-            var x_bar = x;
-            if (widget.get_direction () == Gtk.TextDirection.RTL) {
-                x_bar += w - perc_w;
-            }
-
-            context.add_class ("fill-block");
-
-            if (percent <= 33) {
-                context.add_class ("level-low");
-            } else if (percent > 66) {
-                context.add_class ("level-high");
-            }
-
-            context.render_background (cr, x_bar, y, perc_w, h);
-
-            context.restore ();
-        }
-    }
 }
diff --git a/src/baobab-chart.vala b/src/baobab-chart.vala
index b61ef2c..652d35e 100644
--- a/src/baobab-chart.vala
+++ b/src/baobab-chart.vala
@@ -59,10 +59,13 @@ namespace Baobab {
 
         bool model_changed;
 
-        Gtk.Popover context_menu = null;
+        Gtk.PopoverMenu context_menu = null;
 
         Gtk.EventControllerScroll scroll_controller;
         Gtk.EventControllerMotion motion_controller;
+        Gtk.GestureClick primary_click_gesture;
+        Gtk.GestureClick secondary_click_gesture;
+        Gtk.GestureClick middle_click_gesture;
 
         List<ChartItem> items;
 
@@ -109,7 +112,7 @@ namespace Baobab {
                 model_ = value;
                 model_changed = true;
 
-                root = null;
+                tree_root = null;
 
                 connect_model_signals (model_);
 
@@ -121,7 +124,7 @@ namespace Baobab {
         }
 
         Gtk.TreeRowReference? root_;
-        public Gtk.TreePath? root {
+        public Gtk.TreePath? tree_root {
             set {
                 if (model == null) {
                     return;
@@ -161,10 +164,10 @@ namespace Baobab {
                 }
 
                 if (highlighted_item_ != null) {
-                    get_window ().invalidate_rect (highlighted_item_.rect, true);
+                    queue_draw ();
                 }
                 if (value != null) {
-                    get_window ().invalidate_rect (value.rect, true);
+                    queue_draw ();
                 }
 
                 highlighted_item_ = value;
@@ -203,24 +206,55 @@ namespace Baobab {
         };
 
         construct {
-            add_events (Gdk.EventMask.EXPOSURE_MASK | Gdk.EventMask.ENTER_NOTIFY_MASK | 
Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK);
-
-            scroll_controller = new Gtk.EventControllerScroll (this, 
Gtk.EventControllerScrollFlags.BOTH_AXES);
+            scroll_controller = new Gtk.EventControllerScroll (Gtk.EventControllerScrollFlags.BOTH_AXES);
             scroll_controller.scroll.connect (scroll_cb);
+            add_controller (scroll_controller);
 
-            motion_controller = new Gtk.EventControllerMotion (this);
+            motion_controller = new Gtk.EventControllerMotion ();
             motion_controller.motion.connect (motion_cb);
             motion_controller.leave.connect (leave_cb);
+            add_controller (motion_controller);
+
+            primary_click_gesture = new Gtk.GestureClick ();
+            primary_click_gesture.button = Gdk.BUTTON_PRIMARY;
+            primary_click_gesture.pressed.connect ((_, x, y) => {
+                if (highlight_item_at_point (x, y)) {
+                    var path = model.get_path (highlighted_item.iter);
+                    if (tree_root.compare (path) == 0) {
+                        move_up_root ();
+                    } else {
+                        item_activated (highlighted_item.iter);
+                    }
+                }
+            });
+            add_controller (primary_click_gesture);
+
+            secondary_click_gesture = new Gtk.GestureClick ();
+            secondary_click_gesture.button = Gdk.BUTTON_SECONDARY;
+            secondary_click_gesture.pressed.connect ((_, x, y) => {
+                show_popover_at ((int) x, (int) y);
+            });
+            add_controller (secondary_click_gesture);
+
+            middle_click_gesture = new Gtk.GestureClick ();
+            middle_click_gesture.button = Gdk.BUTTON_MIDDLE;
+            middle_click_gesture.pressed.connect ((_, x, y) => {
+                move_up_root ();
+            });
+            add_controller (middle_click_gesture);
 
             action_group = new SimpleActionGroup ();
             action_group.add_action_entries (action_entries, this);
             insert_action_group ("chart", action_group);
 
             build_context_menu ();
+
+            set_draw_func (draw_func);
         }
 
-        public override void size_allocate (Gtk.Allocation allocation) {
-            base.size_allocate (allocation);
+        public override void size_allocate (int width, int height, int baseline) {
+            base.size_allocate (width, height, baseline);
+            context_menu.present ();
             foreach (ChartItem item in items) {
                 item.has_visible_children = false;
                 item.visible = false;
@@ -335,11 +369,7 @@ namespace Baobab {
             cr.save ();
 
             foreach (ChartItem item in items) {
-                Gdk.Rectangle clip;
-                if (Gdk.cairo_get_clip_rectangle (cr, out clip) &&
-                    item.visible &&
-                    clip.intersect (item.rect, null) &&
-                    (item.depth <= max_depth)) {
+                if (item.visible && (item.depth <= max_depth)) {
                     bool highlighted = (item == highlighted_item);
                     draw_item (cr, item, highlighted);
                 }
@@ -355,12 +385,12 @@ namespace Baobab {
                 return;
             }
 
-            var root_depth = root.get_depth ();
+            var root_depth = tree_root.get_depth ();
             var node_depth = path.get_depth ();
 
             if (((node_depth - root_depth) <= max_depth) &&
-                (root.is_ancestor (path) ||
-                 root.compare (path) == 0)) {
+                (tree_root.is_ancestor (path) ||
+                 tree_root.compare (path) == 0)) {
                 queue_draw ();
             }
         }
@@ -400,21 +430,19 @@ namespace Baobab {
             update_draw (path);
         }
 
-        public override bool draw (Cairo.Context cr) {
+        void draw_func (Gtk.DrawingArea da, Cairo.Context cr, int width, int height) {
             if (model != null) {
                 if (model_changed || items == null) {
-                    get_items (root);
+                    get_items (tree_root);
                 } else {
                     var current_path = model.get_path (items.data.iter);
-                    if (root.compare (current_path) != 0) {
-                        get_items (root);
+                    if (tree_root.compare (current_path) != 0) {
+                        get_items (tree_root);
                     }
                 }
 
                 draw_chart (cr);
             }
-
-            return false;
         }
 
         Gdk.RGBA interpolate_colors (Gdk.RGBA colora, Gdk.RGBA colorb, double percentage) {
@@ -423,13 +451,13 @@ namespace Baobab {
             double diff;
 
             diff = colora.red - colorb.red;
-            color.red = colora.red - diff * percentage;
-            diff = colora.green - colorb.green;
-            color.green = colora.green - diff * percentage;
-            diff = colora.blue - colorb.blue;
-            color.blue = colora.blue - diff * percentage;
+            color.red = (float) (colora.red - diff * percentage);
+            diff = (float) (colora.green - colorb.green);
+            color.green = (float) (colora.green - diff * percentage);
+            diff = (float) (colora.blue - colorb.blue);
+            color.blue = (float) (colora.blue - diff * percentage);
 
-            color.alpha = 1.0;
+            color.alpha = (float) 1.0;
 
             return color;
         }
@@ -439,7 +467,7 @@ namespace Baobab {
 
             var color = Gdk.RGBA ();
 
-            double intensity = 1 - (((depth - 1) * 0.3) / MAX_DEPTH);
+            float intensity = (float) (1 - (((depth - 1) * 0.3) / MAX_DEPTH));
 
             if (depth == 0) {
                 context.lookup_color ("level_color", out color);
@@ -463,7 +491,7 @@ namespace Baobab {
                 if (depth == 0) {
                     context.lookup_color ("level_color_hi", out color);
                 } else {
-                    double maximum = double.max (color.red, double.max (color.green, color.blue));
+                    float maximum = float.max (color.red, float.max (color.green, color.blue));
                     color.red /= maximum;
                     color.green /= maximum;
                     color.blue /= maximum;
@@ -473,70 +501,45 @@ namespace Baobab {
             return color;
         }
 
-        protected override bool button_press_event (Gdk.EventButton event) {
-            if (event.type == Gdk.EventType.BUTTON_PRESS) {
-                if (event.triggers_context_menu ()) {
-                    show_popup_menu (event);
-                    return true;
-                }
-
-                switch (event.button) {
-                case Gdk.BUTTON_PRIMARY:
-                    if (highlight_item_at_point (event.x, event.y)) {
-                        var path = model.get_path (highlighted_item.iter);
-                        if (root.compare (path) == 0) {
-                            move_up_root ();
-                        } else {
-                            item_activated (highlighted_item.iter);
-                        }
-                    }
-                    break;
-                case Gdk.BUTTON_MIDDLE:
-                    move_up_root ();
-                    break;
-                }
-
-                return true;
-            }
-
-            return false;
-        }
-
-        void scroll_cb (double dx, double dy) {
+        bool scroll_cb (double dx, double dy) {
             // Up or to the left
             if (dx > 0.0 || dy < 0.0) {
                 zoom_out ();
+                return true;
             // Down or to the right
             } else if (dx < 0.0 || dy > 0.0) {
                 zoom_in ();
+                return true;
             }
+
+            return false;
         }
 
         public void open_file () {
-            ((Window) get_toplevel ()).open_item (highlighted_item.iter);
+            ((Window) get_root ()).open_item (highlighted_item.iter);
         }
 
         public void copy_path () {
-            ((Window) get_toplevel ()).copy_path (highlighted_item.iter);
+            ((Window) get_root ()).copy_path (highlighted_item.iter);
         }
 
         public void trash_file () {
-            ((Window) get_toplevel ()).trash_file (highlighted_item.iter);
+            ((Window) get_root ()).trash_file (highlighted_item.iter);
         }
 
         protected bool can_move_up_root () {
             Gtk.TreeIter iter, parent_iter;
 
-            model.get_iter (out iter, root);
+            model.get_iter (out iter, tree_root);
             return model.iter_parent (out parent_iter, iter);
         }
 
         public void move_up_root () {
             Gtk.TreeIter iter, parent_iter;
 
-            model.get_iter (out iter, root);
+            model.get_iter (out iter, tree_root);
             if (model.iter_parent (out parent_iter, iter)) {
-                root = model.get_path (parent_iter);
+                tree_root = model.get_path (parent_iter);
                 item_activated (parent_iter);
             }
         }
@@ -555,11 +558,12 @@ namespace Baobab {
 
         void build_context_menu () {
             var menu_model = Application.get_default ().get_menu_by_id ("chartmenu");
-            context_menu = new Gtk.Popover.from_model (this, menu_model);
+            context_menu = new Gtk.PopoverMenu.from_model (menu_model);
+            context_menu.set_parent (this);
             context_menu.set_position (Gtk.PositionType.BOTTOM);
         }
 
-        void show_popup_menu (Gdk.EventButton? event) {
+        void show_popover_at (int x, int y) {
             var enable = highlighted_item != null;
             var action = action_group.lookup_action ("open-file") as SimpleAction;
             action.set_enabled (enable);
@@ -576,7 +580,7 @@ namespace Baobab {
             action = action_group.lookup_action ("zoom-out") as SimpleAction;
             action.set_enabled (can_zoom_out ());
 
-            Gdk.Rectangle rect = { (int) event.x, (int) event.y, 0, 0 };
+            Gdk.Rectangle rect = { x, y, 0, 0 };
             context_menu.set_pointing_to (rect);
             context_menu.popup ();
         }
diff --git a/src/baobab-location-list.vala b/src/baobab-location-list.vala
index 43b0ed4..731e329 100644
--- a/src/baobab-location-list.vala
+++ b/src/baobab-location-list.vala
@@ -250,7 +250,7 @@ namespace Baobab {
             }
 
             recent_items.sort ((a, b) => {
-                return (int)(b.get_modified () - a.get_modified ());
+                return (int)(b.get_modified ().difference (a.get_modified ()));
             });
 
             unowned List<Gtk.RecentInfo> last = recent_items.nth (MAX_RECENT_LOCATIONS - 1);
@@ -269,17 +269,22 @@ namespace Baobab {
         }
 
         public void update () {
-            local_list_box.foreach ((widget) => { widget.destroy (); });
-            remote_list_box.foreach ((widget) => { widget.destroy (); });
+            for (Gtk.Widget? child = local_list_box.get_first_child (); child != null; child = 
local_list_box.get_first_child ()) {
+                local_list_box.remove (child);
+            }
+
+            for (Gtk.Widget? child = remote_list_box.get_first_child (); child != null; child = 
remote_list_box.get_first_child ()) {
+                remote_list_box.remove (child);
+            }
 
             remote_box.visible = false;
 
             foreach (var location in locations) {
                 if (location.is_remote) {
-                    remote_list_box.add (new LocationRow (location));
+                    remote_list_box.append (new LocationRow (location));
                     remote_box.visible = true;
                 } else {
-                    local_list_box.add (new LocationRow (location));
+                    local_list_box.append (new LocationRow (location));
                 }
             }
         }
diff --git a/src/baobab-pathbar.vala b/src/baobab-pathbar.vala
index ad39f6c..cb9433a 100644
--- a/src/baobab-pathbar.vala
+++ b/src/baobab-pathbar.vala
@@ -71,13 +71,15 @@ namespace Baobab {
 
                 buttons.reverse ();
                 foreach (var button in buttons) {
-                    add (button);
+                    append (button);
                 }
             }
         }
 
         void clear () {
-            this.foreach ((widget) => { widget.destroy (); });
+            for (Gtk.Widget? child = get_first_child (); child != null; child = get_first_child ()) {
+                remove (child);
+            }
         }
 
         PathButton make_button (Gtk.TreePath path) {
diff --git a/src/baobab-preferences-dialog.vala b/src/baobab-preferences-dialog.vala
index 5a324e1..78b9a14 100644
--- a/src/baobab-preferences-dialog.vala
+++ b/src/baobab-preferences-dialog.vala
@@ -39,7 +39,7 @@ namespace Baobab {
     }
 
     [GtkTemplate (ui = "/org/gnome/baobab/ui/baobab-preferences-dialog.ui")]
-    public class PreferencesDialog : Hdy.PreferencesWindow {
+    public class PreferencesDialog : Adw.PreferencesWindow {
         [GtkChild]
         private unowned Gtk.ListBox excluded_list_box;
 
@@ -50,17 +50,14 @@ namespace Baobab {
 
             excluded_list_box.row_activated.connect (() => {
                 // The only activatable row is "Add location"
-                var file_chooser = new Gtk.FileChooserDialog (_("Select Location to Ignore"), this,
+                var file_chooser = new Gtk.FileChooserNative (_("Select Location to Ignore"), this,
                                                              Gtk.FileChooserAction.SELECT_FOLDER,
-                                                              _("_Cancel"), Gtk.ResponseType.CANCEL,
-                                                              _("_Open"), Gtk.ResponseType.OK);
+                                                             null, null);
 
-                file_chooser.local_only = false;
                 file_chooser.modal = true;
-                file_chooser.set_default_response (Gtk.ResponseType.OK);
 
                 file_chooser.response.connect ((response) => {
-                    if (response == Gtk.ResponseType.OK) {
+                    if (response == Gtk.ResponseType.ACCEPT) {
                         var uri = file_chooser.get_file ().get_uri ();
                         add_uri (uri);
                         populate ();
@@ -75,12 +72,14 @@ namespace Baobab {
         }
 
         void populate () {
-            excluded_list_box.foreach ((widget) => { widget.destroy (); });
+            for (Gtk.Widget? child = excluded_list_box.get_first_child (); child != null; child = 
excluded_list_box.get_first_child ()) {
+                excluded_list_box.remove (child);
+            }
 
             foreach (var uri in prefs_settings.get_strv ("excluded-uris")) {
                 var file = File.new_for_uri (uri);
                 var row = new ExcludedRow (file);
-                excluded_list_box.insert (row, -1);
+                excluded_list_box.append (row);
 
                 row.removed.connect (() => {
                     remove_uri (uri);
@@ -89,9 +88,11 @@ namespace Baobab {
             }
 
             var label = new Gtk.Label (_("Add Location…"));
-            label.margin = 12;
-            label.show ();
-            excluded_list_box.insert (label, -1);
+            label.margin_start = 12;
+            label.margin_end = 12;
+            label.margin_top = 12;
+            label.margin_bottom = 12;
+            excluded_list_box.append (label);
         }
 
         void add_uri (string uri) {
diff --git a/src/baobab-ringschart.vala b/src/baobab-ringschart.vala
index b1c5e39..f2aaa96 100644
--- a/src/baobab-ringschart.vala
+++ b/src/baobab-ringschart.vala
@@ -98,7 +98,6 @@ namespace Baobab {
             }
 
             var context = get_style_context ();
-            var context_state = context.get_state ();
             context.save ();
             context.add_class ("subfolder-tip");
 
@@ -111,7 +110,7 @@ namespace Baobab {
 
             Gdk.Rectangle last_rect = Gdk.Rectangle ();
 
-            var padding = context.get_padding (context_state);
+            var padding = context.get_padding ();
             var vpadding = padding.top + padding.bottom;
             var hpadding = padding.left + padding.right;
 
@@ -303,9 +302,7 @@ namespace Baobab {
             get_allocation (out allocation);
 
             var context = get_style_context ();
-            var context_state = context.get_state ();
-
-            var padding = context.get_padding (context_state);
+            var padding = context.get_padding ();
             var max_radius = int.min (allocation.width / 2, allocation.height / 2) - padding.left; // 
Assuming that padding is the same for all sides
             var thickness = max_radius / (max_depth + 1);
 
diff --git a/src/baobab-scanner.vala b/src/baobab-scanner.vala
index 998995e..1c61a26 100644
--- a/src/baobab-scanner.vala
+++ b/src/baobab-scanner.vala
@@ -419,7 +419,7 @@ namespace Baobab {
             hardlinks = new GenericSet<HardLink> (HardLink.hash, HardLink.equal);
 
             base.clear ();
-            set_sort_column_id (Gtk.SortColumn.UNSORTED, Gtk.SortType.DESCENDING);
+            set_sort_column_id (Gtk.TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, Gtk.SortType.DESCENDING);
 
             cancellable.reset ();
             scan_error = null;
diff --git a/src/baobab-window.vala b/src/baobab-window.vala
index 3126b20..a17a763 100644
--- a/src/baobab-window.vala
+++ b/src/baobab-window.vala
@@ -23,11 +23,17 @@
 namespace Baobab {
 
     [GtkTemplate (ui = "/org/gnome/baobab/ui/baobab-main-window.ui")]
-    public class Window : Hdy.ApplicationWindow {
+    public class Window : Adw.ApplicationWindow {
+        [GtkChild]
+        private unowned Gtk.EventControllerFocus focus_controller;
+        [GtkChild]
+        private unowned Gtk.DropTarget drop_target;
+        [GtkChild]
+        private unowned Gtk.GestureClick back_gesture;
         [GtkChild]
         private unowned Gtk.Box vbox;
         [GtkChild]
-        private unowned Hdy.HeaderBar header_bar;
+        private unowned Adw.HeaderBar header_bar;
         [GtkChild]
         private unowned Pathbar pathbar;
         [GtkChild]
@@ -65,6 +71,8 @@ namespace Baobab {
         [GtkChild]
         private unowned Gtk.TreeViewColumn time_modified_column;
         [GtkChild]
+        private unowned Gtk.GestureClick treeview_right_click_gesture;
+        [GtkChild]
         private unowned Gtk.Stack chart_stack;
         [GtkChild]
         private unowned Gtk.Stack spinner_stack;
@@ -78,6 +86,7 @@ namespace Baobab {
         private unowned Gtk.Spinner spinner;
 
         private Location? active_location = null;
+        private bool is_busy = false;
         private ulong scan_completed_handler = 0;
         private uint scanning_progress_id = 0;
 
@@ -92,6 +101,10 @@ namespace Baobab {
             { "show-preferences", on_show_preferences },
             { "help", on_help_activate },
             { "about", on_about_activate },
+            { "show-treeview-popover", on_show_treeview_popover },
+            { "treeview-expand-row", on_treeview_expand_row },
+            { "treeview-collapse-row", on_treeview_collapse_row },
+            { "treeview-go-up", go_up_treeview },
             { "treeview-open-folder", on_treeview_open_folder },
             { "treeview-copy", on_treeview_copy },
             { "treeview-trash", on_treeview_trash }
@@ -106,19 +119,11 @@ namespace Baobab {
             { "scan-folder", false },
         };
 
-        private enum DndTargets {
-            URI_LIST
-        }
-
-        private const Gtk.TargetEntry dnd_target_list[1] = {
-            {"text/uri-list", 0, DndTargets.URI_LIST}
-        };
-
         public Window (Application app) {
             Object (application: app);
 
             if (busy_cursor == null) {
-                busy_cursor = new Gdk.Cursor.from_name (get_display(), "wait");
+                busy_cursor = new Gdk.Cursor.from_name ("wait", null);
             }
 
             var ui_settings = new Settings ("org.gnome.baobab.ui");
@@ -134,7 +139,7 @@ namespace Baobab {
             GLib.MenuModel treeview_menu = (GLib.MenuModel) builder.get_object ("treeview_menu");
 
             setup_treeview ();
-            treeview_popover_menu.bind_model (treeview_menu, null);
+            treeview_popover_menu.set_menu_model (treeview_menu);
 
             infobar_close_button.clicked.connect (() => { clear_message (); });
 
@@ -147,8 +152,9 @@ namespace Baobab {
             folder_display.activated.connect (on_folder_display_activated);
 
             // Setup drag-n-drop
-            drag_data_received.connect (on_drag_data_received);
-            enable_drop ();
+            drop_target.set_gtypes ({typeof (Gdk.FileList)});
+            drop_target.on_drop.connect (on_drop);
+            drop_target.accept.connect (on_drop_target_accept);
 
             // Setup window geometry saving
             if (ui_settings.get_boolean ("is-maximized")) {
@@ -157,33 +163,31 @@ namespace Baobab {
 
             int width, height;
             ui_settings.get ("window-size", "(ii)", out width, out height);
-            resize (width, height);
+            set_default_size (width, height);
 
-            ui_settings.bind ("is-maximized", this, "is-maximized", GLib.SettingsBindFlags.SET);
+            ui_settings.bind ("is-maximized", this, "maximized", GLib.SettingsBindFlags.SET);
 
-            size_allocate.connect ((_) => {
-                if (!is_maximized) {
-                    get_size (out width, out height);
-                    ui_settings.set ("window-size", "(ii)", width, height);
+            close_request.connect (() => {
+                if (!maximized) {
+                    int win_width, win_height;
+                    get_default_size (out win_width, out win_height);
+                    ui_settings.set ("window-size", "(ii)", win_width, win_height);
                 }
-            });
-
-            destroy.connect (() => {
                 ui_settings.apply ();
+                return false;
             });
 
             set_ui_state (home_page, false);
 
-            button_press_event.connect ((event) => {
-                // mouse back button
-                if (event.button == 8) {
-                    lookup_action ("show-home-page").activate (null);
-                    return Gdk.EVENT_STOP;
-                }
-                return Gdk.EVENT_PROPAGATE;
+            back_gesture.pressed.connect ((n_press, x, y) => {
+                lookup_action ("show-home-page").activate (null);
             });
 
-            show ();
+            focus_controller.enter.connect (() => {
+                application.withdraw_notification ("scan-completed");
+            });
+
+            present ();
         }
 
         void on_show_primary_menu_activate (SimpleAction action) {
@@ -198,21 +202,20 @@ namespace Baobab {
         }
 
         void on_scan_folder_activate () {
-            var file_chooser = new Gtk.FileChooserDialog (_("Select Folder"), this,
+            var file_chooser = new Gtk.FileChooserNative (_("Select Folder"), this,
                                                           Gtk.FileChooserAction.SELECT_FOLDER,
-                                                          _("_Cancel"), Gtk.ResponseType.CANCEL,
-                                                          _("_Open"), Gtk.ResponseType.OK);
+                                                          null, null);
 
-            file_chooser.local_only = false;
             file_chooser.modal = true;
-            file_chooser.set_default_response (Gtk.ResponseType.OK);
 
-            var check_button = new Gtk.CheckButton.with_label (_("Recursively analyze mount points"));
-            file_chooser.extra_widget = check_button;
+            file_chooser.add_choice ("recurse",
+                                    _("Recursively analyze mount points"),
+                                    null, null);
 
             file_chooser.response.connect ((response) => {
-                if (response == Gtk.ResponseType.OK) {
-                    var flags = check_button.active ? ScanFlags.NONE : ScanFlags.EXCLUDE_MOUNTS;
+                if (response == Gtk.ResponseType.ACCEPT) {
+                    bool recurse = bool.parse (file_chooser.get_choice ("recurse"));
+                    var flags = recurse ? ScanFlags.NONE : ScanFlags.EXCLUDE_MOUNTS;
                     scan_directory (file_chooser.get_file (), flags);
                 }
                 file_chooser.destroy ();
@@ -259,15 +262,11 @@ namespace Baobab {
             var dialog = new PreferencesDialog ();
             dialog.modal = true;
             dialog.set_transient_for (this);
-            dialog.show ();
+            dialog.present ();
         }
 
         void on_help_activate () {
-            try {
-                Gtk.show_uri (get_screen (), "help:baobab", Gtk.get_current_event_time ());
-            } catch (Error e) {
-                message (_("Failed to show help"), e.message, Gtk.MessageType.WARNING);
-            }
+            Gtk.show_uri (this, "help:baobab", Gdk.CURRENT_TIME);
         }
 
         void on_about_activate () {
@@ -322,35 +321,26 @@ namespace Baobab {
             }
         }
 
-        void on_drag_data_received (Gtk.Widget widget, Gdk.DragContext context, int x, int y,
-                                    Gtk.SelectionData selection_data, uint target_type, uint time) {
-            File dir = null;
+        bool on_drop_target_accept (Gtk.DropTarget target, Gdk.Drop drop) {
+            return !is_busy;
+        }
 
-            if ((selection_data != null) && (selection_data.get_length () >= 0) && (target_type == 
DndTargets.URI_LIST)) {
-                var uris = GLib.Uri.list_extract_uris ((string) selection_data.get_data ());
-                if (uris != null && uris.length == 1) {
-                    dir = File.new_for_uri (uris[0]);
+        bool on_drop (Gtk.DropTarget target, Value value, double x, double y) {
+            if (value.type () == typeof (Gdk.FileList)) {
+                unowned var files = (SList<File>) value.get_boxed ();
+                File dir = null;
+                if (files != null && files.length () == 1) {
+                    dir = files.nth (0).data;
                 }
-            }
 
-            if (dir != null) {
-                // finish drop before scanning, since the it can time out
-                Gtk.drag_finish (context, true, false, time);
-                scan_directory (dir);
-            } else {
-                Gtk.drag_finish (context, false, false, time);
-            }
-        }
+                if (dir != null) {
+                    scan_directory (dir);
+                }
 
-        void enable_drop () {
-            Gtk.drag_dest_set (this,
-                               Gtk.DestDefaults.DROP | Gtk.DestDefaults.MOTION | Gtk.DestDefaults.HIGHLIGHT,
-                               dnd_target_list,
-                               Gdk.DragAction.COPY);
-        }
+                return true;
+            }
 
-        void disable_drop () {
-            Gtk.drag_dest_unset (this);
+            return false;
         }
 
         bool show_treeview_popover (Gtk.PopoverMenu popover, int x, int y) {
@@ -371,9 +361,8 @@ namespace Baobab {
 
         public void copy_path (Gtk.TreeIter iter) {
             var parse_name = active_location.scanner.get_file (iter).get_parse_name ();
-            var clipboard = Gtk.Clipboard.get (Gdk.SELECTION_CLIPBOARD);
-            clipboard.set_text (parse_name, -1);
-            clipboard.store ();
+            var clipboard = get_primary_clipboard ();
+            clipboard.set_text (parse_name);
         }
 
         public void trash_file (Gtk.TreeIter iter) {
@@ -422,6 +411,30 @@ namespace Baobab {
             return sort.convert_child_path_to_path (filter_path);
         }
 
+        void on_show_treeview_popover () {
+            show_treeview_popover (treeview_popover_menu,
+                                   treeview.get_allocated_width () / 2,
+                                   treeview.get_allocated_height () / 2);
+        }
+
+        void on_treeview_expand_row () {
+            Gtk.TreeIter iter;
+            if (treeview.get_selection ().get_selected (null, out iter)) {
+                Gtk.TreePath path = treeview.model.get_path (iter);
+                treeview.expand_row (path, false);
+            }
+        }
+
+        void on_treeview_collapse_row () {
+            Gtk.TreeIter iter;
+            if (treeview.get_selection ().get_selected (null, out iter)) {
+                Gtk.TreePath path = treeview.model.get_path (iter);
+                if (!treeview.collapse_row (path) && path.up ()) {
+                    treeview.set_cursor(path, null, false);
+                }
+            }
+        }
+
         void on_treeview_open_folder () {
             Gtk.TreeIter iter;
             if (get_selected_iter (out iter)) {
@@ -444,54 +457,12 @@ namespace Baobab {
         }
 
         void setup_treeview () {
-            treeview.button_press_event.connect ((event) => {
-                if (event.triggers_context_menu ()) {
-                    Gtk.TreePath path;
-                    if (treeview.get_path_at_pos ((int)event.x, (int)event.y, out path, null, null, null)) {
-                        treeview.get_selection ().select_path (path);
-                        return show_treeview_popover (treeview_popover_menu,  (int) event.x, (int) event.y);
-                    }
+            treeview_right_click_gesture.pressed.connect ((n_press, x, y) => {
+                Gtk.TreePath path;
+                if (treeview.get_path_at_pos ((int) x, (int) y, out path, null, null, null)) {
+                    treeview.get_selection ().select_path (path);
+                    show_treeview_popover (treeview_popover_menu,  (int) x, (int) y);
                 }
-
-                return false;
-            });
-
-            treeview.key_press_event.connect ((event) => {
-                Gtk.TreeIter iter;
-                if (treeview.get_selection ().get_selected (null, out iter)) {
-                    Gtk.TreePath path = treeview.model.get_path (iter);
-                    if (event.keyval == Gdk.Key.Right) {
-                        if (treeview.expand_row (path, false)) {
-                            return true;
-                        }
-                    } else if (event.keyval == Gdk.Key.Left) {
-                        if (treeview.collapse_row (path)) {
-                            return true;
-                        } else if (path.up ()) {
-                            treeview.set_cursor(path, null, false);
-                            return true;
-                        }
-                    } else if (event.keyval == Gdk.Key.space) {
-                        if (treeview.expand_row (path, false)) {
-                            return true;
-                        } else if (treeview.collapse_row (path)) {
-                            return true;
-                        }
-                    } else if (event.keyval == Gdk.Key.Up && event.state == Gdk.ModifierType.MOD1_MASK) {
-                        go_up_treeview ();
-                        return true;
-                    }
-                }
-
-                return false;
-            });
-
-            treeview.popup_menu.connect (() => {
-                Gtk.Allocation allocation;
-                treeview.get_allocated_size (out allocation, null);
-                return show_treeview_popover (treeview_popover_menu,
-                                              allocation.width / 2,
-                                              allocation.height / 2);
             });
 
             treeview.row_activated.connect ((wrapper_path, column) => {
@@ -532,8 +503,8 @@ namespace Baobab {
                 return;
             }
 
-            rings_chart.root = path;
-            treemap_chart.root = path;
+            rings_chart.tree_root = path;
+            treemap_chart.tree_root = path;
             folder_display.path = path;
             pathbar.path = path;
 
@@ -558,27 +529,23 @@ namespace Baobab {
         }
 
         void set_busy (bool busy) {
-            Gdk.Cursor? cursor = null;
+            Gdk.Cursor? new_cursor = null;
+            is_busy = busy;
 
             if (busy) {
-                cursor = busy_cursor;
-                disable_drop ();
+                new_cursor = busy_cursor;
                 chart_stack_switcher.sensitive = false;
                 spinner_stack.visible_child = spinner;
                 spinner.start ();
                 pathbar.sensitive = false;
             } else {
-                enable_drop ();
                 spinner.stop ();
                 spinner_stack.visible_child = chart_stack;
                 chart_stack_switcher.sensitive = true;
                 pathbar.sensitive = true;
             }
 
-            var window = get_window ();
-            if (window != null) {
-                window.cursor = cursor;
-            }
+            this.cursor = new_cursor;
 
             foreach (ActionState action_state in actions_while_scanning) {
                 var action = lookup_action (action_state.name) as SimpleAction;
@@ -593,17 +560,17 @@ namespace Baobab {
 
             set_busy (busy);
 
-            header_bar.custom_title = null;
+            header_bar.title_widget = null;
             if (child == home_page) {
                 var action = lookup_action ("reload") as SimpleAction;
                 action.set_enabled (false);
-                header_bar.title = _("Devices & Locations");
+                this.title = _("Devices & Locations");
             } else {
                 var action = lookup_action ("reload") as SimpleAction;
                 action.set_enabled (true);
-                header_bar.title = active_location.name;
+                this.title = active_location.name;
                 if (child == result_page) {
-                    header_bar.custom_title = pathbar;
+                    header_bar.title_widget = pathbar;
                 }
             }
 


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