[simple-scan] app-window: Make preferences modal



commit 4c58594801835b8e83681edd8c9376b1fc32634c
Author: Christopher Davis <brainblasted disroot org>
Date:   Fri Feb 12 14:16:12 2021 +0000

    app-window: Make preferences modal
    
    Matches how we handle preference dialogs across GNOME

 .gitlab-ci.yml                |   6 +-
 data/ui/app-window.ui         | 398 +++++++++++++---------------
 data/ui/preferences-dialog.ui | 601 ++++++++++++------------------------------
 meson.build                   |  27 ++
 src/app-window.vala           |  40 +--
 src/meson.build               |   2 +-
 src/preferences-dialog.vala   |   4 +-
 src/simple-scan.vala          |   2 +
 subprojects/libhandy.wrap     |   4 +
 9 files changed, 398 insertions(+), 686 deletions(-)
---
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e0325b8a..f3d2a883 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,7 +13,7 @@ build-ubuntu:
   image: ubuntu:rolling
   before_script:
     - apt-get update
-    - DEBIAN_FRONTEND=noninteractive apt-get install -q -y --no-install-recommends meson valac gcc gettext 
itstool libgtk-3-dev libgusb-dev libcolord-dev libpackagekit-glib2-dev libwebp-dev libsane-dev
+    - DEBIAN_FRONTEND=noninteractive apt-get install -q -y --no-install-recommends meson valac gcc gettext 
itstool gobject-introspection libfribidi-dev libgirepository1.0-dev libgtk-3-dev libgusb-dev libcolord-dev 
libpackagekit-glib2-dev libwebp-dev libsane-dev git ca-certificates
   script:
     - meson _build
     - ninja -C _build install
@@ -21,7 +21,7 @@ build-ubuntu:
 build-fedora:
   image: fedora:latest
   before_script:
-    - dnf install -y meson vala gettext itstool gtk3-devel libgusb-devel colord-devel PackageKit-glib-devel 
libwebp-devel sane-backends-devel
+    - dnf install -y meson vala gettext itstool fribidi-devel gtk3-devel gobject-introspection-devel 
libgusb-devel colord-devel PackageKit-glib-devel libwebp-devel sane-backends-devel git
   script:
     - meson _build
     - ninja -C _build install
@@ -29,7 +29,7 @@ build-fedora:
 build-arch:
   image: archlinux/base:latest
   before_script:
-    - pacman -Syu --noconfirm meson vala gettext itstool gtk3 libgusb colord libwebp sane
+    - pacman -Syu --noconfirm meson vala gettext itstool fribidi gtk3 gobject-introspection libgusb colord 
libwebp sane git
   script:
     - meson _build
     - ninja -C _build install
diff --git a/data/ui/app-window.ui b/data/ui/app-window.ui
index 540c6bcb..5fd0a0a5 100644
--- a/data/ui/app-window.ui
+++ b/data/ui/app-window.ui
@@ -491,308 +491,267 @@
       </object>
     </child>
   </object>
-  <template class="AppWindow" parent="GtkApplicationWindow">
+  <template class="AppWindow" parent="HdyApplicationWindow">
     <property name="width_request">320</property>
     <property name="height_request">480</property>
     <property name="can_focus">False</property>
     <property name="title" translatable="yes" comments="Title of scan window">Document Scanner</property>
     <property name="icon_name">org.gnome.SimpleScan</property>
     <signal name="delete-event" handler="window_delete_event_cb" swapped="no"/>
-    <child type="titlebar">
-      <object class="GtkHeaderBar" id="header_bar">
+    <child>
+      <object class="GtkBox">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
-        <property name="vexpand">True</property>
-        <property name="show_close_button">True</property>
+        <property name="orientation">vertical</property>
         <child>
-          <object class="GtkBox" id="open_box">
+          <object class="HdyHeaderBar" id="header_bar">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="valign">center</property>
+            <property name="show_close_button">True</property>
             <child>
-              <object class="GtkButton" id="stop_button">
+              <object class="GtkBox" id="open_box">
+                <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="receives_default">False</property>
-                <property name="tooltip_text" translatable="yes" comments="Tooltip for stop button">Stop the 
current scan</property>
-                <property name="use_underline">True</property>
-                <signal name="clicked" handler="stop_scan_button_clicked_cb" swapped="no"/>
+                <property name="valign">center</property>
                 <child>
-                  <object class="GtkBox">
+                  <object class="GtkButton" id="stop_button">
+                    <property name="can_focus">False</property>
+                    <property name="receives_default">False</property>
+                    <property name="tooltip_text" translatable="yes" comments="Tooltip for stop button">Stop 
the current scan</property>
+                    <property name="use_underline">True</property>
+                    <signal name="clicked" handler="stop_scan_button_clicked_cb" swapped="no"/>
+                    <child>
+                      <object class="GtkBox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkSpinner" id="stop_button_spinner">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="active">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">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="label" translatable="yes">S_top</property>
+                            <property name="use_underline">True</property>
+                            <property name="width_chars">6</property>
+                            <property name="xalign">0.33</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
+                      </object>
+                    </child>
+                    <style>
+                      <class name="text-button"/>
+                      <class name="destructive-action"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="scan_button">
                     <property name="visible">True</property>
+                    <property name="sensitive">False</property>
                     <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
+                    <property name="receives_default">False</property>
+                    <property name="tooltip_text" translatable="yes" comments="Tooltip for scan toolbar 
button">Scan a single page from the scanner</property>
+                    <property name="use_underline">True</property>
+                    <signal name="clicked" handler="scan_button_clicked_cb" swapped="no"/>
                     <child>
-                      <object class="GtkSpinner" id="stop_button_spinner">
+                      <object class="GtkBox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="active">True</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkImage" id="scan_options_image">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">scanner-symbolic</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="margin_right">1</property>
+                            <property name="label" translatable="yes">_Scan</property>
+                            <property name="use_underline">True</property>
+                            <property name="width_chars">6</property>
+                            <property name="xalign">0.33</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
                       </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
                     </child>
+                    <style>
+                      <class name="text-button"/>
+                      <class name="suggested-action"/>
+                    </style>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="receives_default">False</property>
+                    <property name="popover">scan_options_popover</property>
                     <child>
-                      <object class="GtkLabel">
+                      <object class="GtkBox">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="label" translatable="yes">S_top</property>
-                        <property name="use_underline">True</property>
-                        <property name="width_chars">6</property>
-                        <property name="xalign">0.33</property>
+                        <property name="spacing">6</property>
+                        <child>
+                          <object class="GtkImage" id="scan_hint_image">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">x-office-document-symbolic</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkImage">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">pan-down-symbolic</property>
+                          </object>
+                          <packing>
+                            <property name="expand">False</property>
+                            <property name="fill">True</property>
+                            <property name="position">1</property>
+                          </packing>
+                        </child>
                       </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
                     </child>
                   </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
                 </child>
                 <style>
-                  <class name="text-button"/>
-                  <class name="destructive-action"/>
+                  <class name="linked"/>
                 </style>
               </object>
-              <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
             </child>
             <child>
-              <object class="GtkButton" id="scan_button">
+              <object class="GtkMenuButton" id="menu_button">
                 <property name="visible">True</property>
-                <property name="sensitive">False</property>
                 <property name="can_focus">False</property>
                 <property name="receives_default">False</property>
-                <property name="tooltip_text" translatable="yes" comments="Tooltip for scan toolbar 
button">Scan a single page from the scanner</property>
                 <property name="use_underline">True</property>
-                <signal name="clicked" handler="scan_button_clicked_cb" swapped="no"/>
+                <accelerator key="F10" signal="activate"/>
                 <child>
-                  <object class="GtkBox">
+                  <object class="GtkImage">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkImage" id="scan_options_image">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="icon_name">scanner-symbolic</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="margin_right">1</property>
-                        <property name="label" translatable="yes">_Scan</property>
-                        <property name="use_underline">True</property>
-                        <property name="width_chars">6</property>
-                        <property name="xalign">0.33</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
+                    <property name="icon_name">open-menu-symbolic</property>
+                    <property name="icon_size">1</property>
                   </object>
                 </child>
                 <style>
-                  <class name="text-button"/>
-                  <class name="suggested-action"/>
+                  <class name="image-button"/>
                 </style>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
+                <property name="pack_type">end</property>
                 <property name="position">1</property>
               </packing>
             </child>
             <child>
-              <object class="GtkMenuButton">
+              <object class="GtkButton" id="save_button">
                 <property name="visible">True</property>
+                <property name="sensitive">False</property>
                 <property name="can_focus">False</property>
                 <property name="receives_default">False</property>
-                <property name="popover">scan_options_popover</property>
+                <property name="tooltip_text" translatable="yes" comments="Tooltip for save toolbar 
button">Save document to a file</property>
+                <property name="use_underline">True</property>
+                <signal name="clicked" handler="save_file_button_clicked_cb" swapped="no"/>
                 <child>
-                  <object class="GtkBox">
+                  <object class="GtkImage" id="save_image">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkImage" id="scan_hint_image">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="icon_name">x-office-document-symbolic</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkImage">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="icon_name">pan-down-symbolic</property>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
+                    <property name="icon_name">document-save-symbolic</property>
+                    <property name="icon_size">1</property>
                   </object>
                 </child>
+                <style>
+                  <class name="image-button"/>
+                </style>
               </object>
               <packing>
-                <property name="expand">False</property>
-                <property name="fill">True</property>
+                <property name="pack_type">end</property>
                 <property name="position">2</property>
               </packing>
             </child>
             <style>
-              <class name="linked"/>
-            </style>
-          </object>
-        </child>
-        <child>
-          <object class="GtkMenuButton" id="menu_button">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="receives_default">False</property>
-            <property name="use_underline">True</property>
-            <accelerator key="F10" signal="activate"/>
-            <child>
-              <object class="GtkImage">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="icon_name">open-menu-symbolic</property>
-                <property name="icon_size">1</property>
-              </object>
-            </child>
-            <style>
-              <class name="image-button"/>
-            </style>
-          </object>
-          <packing>
-            <property name="pack_type">end</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="save_button">
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">False</property>
-            <property name="receives_default">False</property>
-            <property name="tooltip_text" translatable="yes" comments="Tooltip for save toolbar button">Save 
document to a file</property>
-            <property name="use_underline">True</property>
-            <signal name="clicked" handler="save_file_button_clicked_cb" swapped="no"/>
-            <child>
-              <object class="GtkImage" id="save_image">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="icon_name">document-save-symbolic</property>
-                <property name="icon_size">1</property>
-              </object>
-            </child>
-            <style>
-              <class name="image-button"/>
+              <class name="titlebar"/>
             </style>
           </object>
-          <packing>
-            <property name="pack_type">end</property>
-            <property name="position">2</property>
-          </packing>
         </child>
-        <style>
-          <class name="titlebar"/>
-        </style>
-      </object>
-    </child>
-    <child>
-      <object class="GtkBox">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
         <child>
           <object class="GtkStack" id="stack">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="vexpand">True</property>
             <child>
-              <object class="GtkAlignment">
+              <object class="HdyStatusPage" id="status_page">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="xscale">0</property>
-                <property name="yscale">0</property>
+                <property name="icon_name">org.gnome.SimpleScan-symbolic</property>
                 <child>
                   <object class="GtkBox">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
                     <property name="orientation">vertical</property>
-                    <property name="spacing">10</property>
-                    <child>
-                      <object class="GtkImage">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="has_focus">True</property>
-                        <property name="is_focus">True</property>
-                        <property name="can_default">True</property>
-                        <property name="has_default">True</property>
-                        <property name="opacity">0.5</property>
-                        <property name="pixel_size">120</property>
-                        <property name="icon_name">org.gnome.SimpleScan-symbolic</property>
-                        <property name="icon_size">6</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="status_primary_label">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                          <attribute name="scale" value="1.5"/>
-                        </attributes>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">1</property>
-                      </packing>
-                    </child>
+                    <property name="spacing">12</property>
                     <child>
                       <object class="GtkLabel" id="status_secondary_label">
-                        <property name="can_focus">False</property>
+                        <property name="visible">False</property>
+                        <property name="wrap">True</property>
+                        <property name="wrap-mode">word-char</property>
+                        <property name="justify">center</property>
+                        <property name="use-markup">True</property>
                         <property name="track_visited_links">False</property>
                         <signal name="activate-link" handler="status_label_activate_link_cb" swapped="no"/>
                         <style>
-                          <class name="dim-label"/>
+                          <class name="body"/>
+                          <class name="description"/>
                         </style>
                       </object>
-                      <packing>
-                        <property name="expand">False</property>
-                        <property name="fill">True</property>
-                        <property name="position">2</property>
-                      </packing>
                     </child>
                     <child>
                       <object class="GtkBox" id="device_buttons_box">
@@ -868,11 +827,6 @@
               </packing>
             </child>
           </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
         </child>
       </object>
     </child>
diff --git a/data/ui/preferences-dialog.ui b/data/ui/preferences-dialog.ui
index 8bd7999a..a54709c3 100644
--- a/data/ui/preferences-dialog.ui
+++ b/data/ui/preferences-dialog.ui
@@ -40,520 +40,243 @@
       <column type="gchararray"/>
     </columns>
   </object>
-  <template class="PreferencesDialog" parent="GtkDialog">
+  <template class="PreferencesDialog" parent="HdyPreferencesWindow">
     <property name="can_focus">False</property>
-    <property name="title" translatable="yes" comments="Title of preferences dialog">Preferences</property>
-    <property name="resizable">False</property>
     <property name="icon_name">org.gnome.SimpleScan</property>
-    <property name="type_hint">normal</property>
-    <child type="titlebar">
-      <placeholder/>
-    </child>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="dialog-vbox2">
+    <property name="search_enabled">False</property>
+    <child>
+      <object class="HdyPreferencesPage">
         <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">2</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox">
-            <property name="can_focus">False</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
         <child>
-          <object class="GtkNotebook">
+          <object class="HdyPreferencesGroup">
             <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="show_border">False</property>
+            <property name="title" translatable="yes" comments="Preferences Dialog: Section label for 
scanning settings">Scanning</property>
             <child>
-              <object class="GtkBox">
+              <object class="HdyActionRow">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="border_width">30</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">30</property>
+                <property name="title" translatable="yes" comments="Label beside scan side combo box">Scan 
_Sides</property>
+                <property name="use_underline">True</property>
+                <property name="activatable_widget">front_side_button</property>
                 <child>
-                  <object class="GtkGrid">
+                  <object class="GtkBox" id="scan_side_box">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="row_spacing">15</property>
-                    <property name="column_spacing">10</property>
-                    <child>
-                      <object class="GtkLabel" id="page_side_label">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Label beside scan side combo 
box">Scan _Sides</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">front_side_button</property>
-                        <property name="xalign">1</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                      </packing>
-                    </child>
+                    <property name="valign">center</property>
+                    <property name="homogeneous">True</property>
                     <child>
-                      <object class="GtkLabel" id="paper_size_label">
+                      <object class="GtkRadioButton" id="front_side_button">
+                        <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">Front</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Label beside page size combo 
box">_Page Size</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">paper_size_combo</property>
-                        <property name="xalign">1</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="active">True</property>
+                        <property name="draw_indicator">False</property>
                       </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">1</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkComboBox" id="paper_size_combo">
+                      <object class="GtkRadioButton" id="back_side_button">
+                        <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on the back side of a page">Back</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="hexpand">True</property>
-                        <property name="model">paper_size_model</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="draw_indicator">False</property>
+                        <property name="group">front_side_button</property>
                       </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">1</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkBox" id="scan_side_box">
+                      <object class="GtkRadioButton" id="both_side_button">
+                        <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on both sides of a page">Both</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="homogeneous">True</property>
-                        <child>
-                          <object class="GtkRadioButton" id="front_side_button">
-                            <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">Front</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>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="back_side_button">
-                            <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on the back side of a page">Back</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="group">front_side_button</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="both_side_button">
-                            <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on both sides of a page">Both</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="group">front_side_button</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <style>
-                          <class name="linked"/>
-                        </style>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="draw_indicator">False</property>
+                        <property name="group">front_side_button</property>
                       </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">0</property>
-                      </packing>
                     </child>
+                    <style>
+                      <class name="linked"/>
+                    </style>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
                 </child>
+              </object>
+            </child>
+            <child>
+              <object class="HdyActionRow">
+                <property name="visible">True</property>
+                <property name="title" translatable="yes" comments="Label beside page size combo box">_Page 
Size</property>
+                <property name="use_underline">True</property>
+                <property name="activatable_widget">paper_size_combo</property>
+                <child>
+                  <object class="GtkComboBox" id="paper_size_combo">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="valign">center</property>
+                    <property name="model">paper_size_model</property>
+                  </object>
+                </child>
+              </object>
+            </child>
+            <child>
+              <object class="HdyActionRow">
+                <property name="visible">True</property>
+                <property name="title" translatable="yes" comments="Label beside page delay scale">_Delay in 
Seconds</property>
+                <property name="subtitle" translatable="yes" comments="Provides context for the page delay 
scale">Interval to scan multiple pages</property>
+                <property name="use_underline">True</property>
+                <property name="activatable_widget">page_delay_0s_button</property>
                 <child>
-                  <object class="GtkGrid">
+                  <object class="GtkBox">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="row_spacing">15</property>
-                    <property name="column_spacing">10</property>
+                    <property name="valign">center</property>
+                    <property name="homogeneous">True</property>
+                    <child>
+                      <object class="GtkRadioButton" id="page_delay_0s_button">
+                        <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">0</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>
+                      </object>
+                    </child>
                     <child>
-                      <object class="GtkLabel" id="page_delay_label">
+                      <object class="GtkRadioButton" id="page_delay_3s_button">
+                        <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">3</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Label beside page delay 
scale">_Delay</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">page_delay_0s_button</property>
-                        <property name="xalign">1</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
+                        <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="group">page_delay_0s_button</property>
                       </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">1</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkLabel">
+                      <object class="GtkRadioButton" id="page_delay_6s_button">
+                        <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">6</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Preferences dialog: Label above 
settings for scanning multiple pages from a flatbed">Multiple pages from flatbed</property>
-                        <property name="xalign">0</property>
-                        <attributes>
-                          <attribute name="weight" value="bold"/>
-                        </attributes>
+                        <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="group">page_delay_0s_button</property>
                       </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                        <property name="width">3</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkBox">
+                      <object class="GtkRadioButton" id="page_delay_10s_button">
+                        <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">10</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="homogeneous">True</property>
-                        <child>
-                          <object class="GtkRadioButton" id="page_delay_0s_button">
-                            <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">0</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>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">0</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="page_delay_3s_button">
-                            <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">3</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="group">page_delay_0s_button</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">1</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="page_delay_6s_button">
-                            <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">6</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="group">page_delay_0s_button</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">2</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="page_delay_10s_button">
-                            <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">10</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="group">page_delay_0s_button</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">3</property>
-                          </packing>
-                        </child>
-                        <child>
-                          <object class="GtkRadioButton" id="page_delay_15s_button">
-                            <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">15</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="group">page_delay_0s_button</property>
-                          </object>
-                          <packing>
-                            <property name="expand">False</property>
-                            <property name="fill">True</property>
-                            <property name="position">4</property>
-                          </packing>
-                        </child>
-                        <style>
-                          <class name="linked"/>
-                        </style>
+                        <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="group">page_delay_0s_button</property>
                       </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">1</property>
-                      </packing>
                     </child>
                     <child>
-                      <object class="GtkLabel">
+                      <object class="GtkRadioButton" id="page_delay_15s_button">
+                        <property name="label" translatable="yes" comments="Preferences Dialog: Toggle 
button to select scanning on front side of a page">15</property>
                         <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Label after page delay radio 
buttons">Seconds</property>
-                        <property name="use_underline">True</property>
-                        <property name="xalign">1</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
+                        <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="group">page_delay_0s_button</property>
                       </object>
-                      <packing>
-                        <property name="left_attach">2</property>
-                        <property name="top_attach">1</property>
-                      </packing>
                     </child>
+                    <style>
+                      <class name="linked"/>
+                    </style>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="tab_expand">True</property>
-              </packing>
             </child>
-            <child type="tab">
-              <object class="GtkLabel">
+          </object>
+        </child>
+        <child>
+          <object class="HdyPreferencesGroup">
+            <property name="visible">True</property>
+            <property name="title" translatable="yes" comments="Preferences Dialog: Section label for 
quality settings">Quality</property>
+            <child>
+              <object class="HdyActionRow">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="label" translatable="yes" comments="Preferences Dialog: Tab label for 
scanning settings">_Scanning</property>
+                <property name="title" translatable="yes" comments="Label beside scan resolution combo 
box">_Text Resolution</property>
                 <property name="use_underline">True</property>
+                <property name="activatable_widget">text_dpi_combo</property>
+                <child>
+                  <object class="GtkComboBox" id="text_dpi_combo">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="valign">center</property>
+                    <property name="model">text_dpi_model</property>
+                  </object>
+                </child>
               </object>
-              <packing>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
             <child>
-              <object class="GtkBox">
+              <object class="HdyActionRow">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="border_width">30</property>
-                <property name="orientation">vertical</property>
-                <property name="spacing">30</property>
+                <property name="title" translatable="yes" comments="Label beside scan resolution combo 
box">_Image Resolution</property>
+                <property name="use_underline">True</property>
+                <property name="activatable_widget">photo_dpi_combo</property>
                 <child>
-                  <object class="GtkGrid">
+                  <object class="GtkComboBox" id="photo_dpi_combo">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="row_spacing">14</property>
-                    <property name="column_spacing">10</property>
-                    <child>
-                      <object class="GtkLabel" id="text_dpi_label">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Label beside scan resolution 
combo box">_Text Resolution</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">text_dpi_combo</property>
-                        <property name="xalign">1</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="photo_dpi_label">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Label beside scan resolution 
combo box">_Image Resolution</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">photo_dpi_combo</property>
-                        <property name="xalign">1</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="text_dpi_combo">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="hexpand">True</property>
-                        <property name="model">text_dpi_model</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkComboBox" id="photo_dpi_combo">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="hexpand">True</property>
-                        <property name="model">photo_dpi_model</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">1</property>
-                      </packing>
-                    </child>
+                    <property name="valign">center</property>
+                    <property name="model">photo_dpi_model</property>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">0</property>
-                  </packing>
                 </child>
+              </object>
+            </child>
+            <child>
+              <object class="HdyActionRow">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="title" translatable="yes" comments="Label beside brightness 
scale">_Brightness</property>
+                <property name="use_underline">True</property>
+                <property name="activatable_widget">brightness_scale</property>
                 <child>
-                  <object class="GtkGrid">
+                  <object class="GtkScale" id="brightness_scale">
                     <property name="visible">True</property>
-                    <property name="can_focus">False</property>
-                    <property name="row_spacing">15</property>
-                    <property name="column_spacing">10</property>
-                    <child>
-                      <object class="GtkLabel" id="brightness_label">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Label beside brightness 
scale">_Brightness</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">brightness_scale</property>
-                        <property name="xalign">1</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkLabel" id="contrast_label">
-                        <property name="visible">True</property>
-                        <property name="can_focus">False</property>
-                        <property name="label" translatable="yes" comments="Label beside contrast 
scale">_Contrast</property>
-                        <property name="use_underline">True</property>
-                        <property name="mnemonic_widget">contrast_scale</property>
-                        <property name="xalign">1</property>
-                        <style>
-                          <class name="dim-label"/>
-                        </style>
-                      </object>
-                      <packing>
-                        <property name="left_attach">0</property>
-                        <property name="top_attach">1</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkScale" id="brightness_scale">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="adjustment">brightness_adjustment</property>
-                        <property name="draw_value">False</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">0</property>
-                      </packing>
-                    </child>
-                    <child>
-                      <object class="GtkScale" id="contrast_scale">
-                        <property name="visible">True</property>
-                        <property name="can_focus">True</property>
-                        <property name="hexpand">True</property>
-                        <property name="adjustment">contrast_adjustment</property>
-                        <property name="draw_value">False</property>
-                      </object>
-                      <packing>
-                        <property name="left_attach">1</property>
-                        <property name="top_attach">1</property>
-                      </packing>
-                    </child>
+                    <property name="can_focus">True</property>
+                    <property name="valign">center</property>
+                    <property name="hexpand">True</property>
+                    <property name="adjustment">brightness_adjustment</property>
+                    <property name="draw_value">False</property>
                   </object>
-                  <packing>
-                    <property name="expand">False</property>
-                    <property name="fill">True</property>
-                    <property name="position">1</property>
-                  </packing>
                 </child>
               </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="tab_expand">True</property>
-              </packing>
             </child>
-            <child type="tab">
-              <object class="GtkLabel">
+            <child>
+              <object class="HdyActionRow">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="label" translatable="yes" comments="Preferences Dialog: Tab for quality 
settings">_Quality</property>
+                <property name="title" translatable="yes" comments="Label beside contrast 
scale">_Contrast</property>
                 <property name="use_underline">True</property>
+                <property name="activatable_widget">contrast_scale</property>
+                <child>
+                  <object class="GtkScale" id="contrast_scale">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="valign">center</property>
+                    <property name="hexpand">True</property>
+                    <property name="adjustment">contrast_adjustment</property>
+                    <property name="draw_value">False</property>
+                  </object>
+                </child>
               </object>
-              <packing>
-                <property name="position">1</property>
-                <property name="tab_fill">False</property>
-              </packing>
             </child>
           </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
         </child>
       </object>
     </child>
   </template>
-  <object class="GtkSizeGroup" id="label_size_group">
+  <object class="GtkSizeGroup" id="scale_size_group">
+    <property name="mode">GTK_SIZE_GROUP_HORIZONTAL</property>
     <widgets>
-      <widget name="page_side_label"/>
-      <widget name="paper_size_label"/>
-      <widget name="page_delay_label"/>
-      <widget name="text_dpi_label"/>
-      <widget name="photo_dpi_label"/>
-      <widget name="brightness_label"/>
-      <widget name="contrast_label"/>
+      <widget name="brightness_scale"/>
+      <widget name="contrast_scale"/>
     </widgets>
   </object>
 </interface>
diff --git a/meson.build b/meson.build
index 2024075f..b7dd0b77 100644
--- a/meson.build
+++ b/meson.build
@@ -7,6 +7,12 @@ project ('simple-scan', ['vala', 'c'],
          ],
          meson_version: '>= 0.37.1')
 
+# FIXME Disable --disable-since-check after libhandy 1.2 is released
+add_project_arguments (
+  '--disable-since-check',
+  language: 'vala'
+)
+
 gnome = import ('gnome')
 i18n = import ('i18n')
 
@@ -23,6 +29,7 @@ glib_dep = dependency ('glib-2.0', version: '>= 2.38')
 gtk_dep = dependency ('gtk+-3.0', version: '>=3.22')
 gmodule_dep = dependency ('gmodule-export-2.0')
 gthread_dep = dependency ('gthread-2.0')
+libhandy_dep = dependency ('libhandy-1', version: '>= 1.1.90', required: false)
 zlib_dep = dependency ('zlib')
 cairo_dep = dependency ('cairo')
 gdk_pixbuf_dep = dependency ('gdk-pixbuf-2.0')
@@ -35,6 +42,26 @@ sane_dep = dependency ('sane-backends')
 msgfmt = find_program  ('msgfmt')
 itstool = find_program  ('itstool')
 
+libhandy_subproj = libhandy_dep
+if not libhandy_dep.found()
+  libhandy_subproj = subproject(
+    'libhandy',
+    default_options: [
+      'examples=false',
+      'glade_catalog=disabled',
+      'tests=false',
+    ]
+  )
+
+  # When using libhandy as subproject, make sure we get the VAPI file
+  libhandy_dep = declare_dependency(
+    dependencies: [
+      libhandy_subproj.get_variable('libhandy_dep'),
+      libhandy_subproj.get_variable('libhandy_vapi'),
+    ]
+  )
+endif
+
 subdir ('po')
 subdir ('data')
 subdir ('help')
diff --git a/src/app-window.vala b/src/app-window.vala
index 3e362871..e718a249 100644
--- a/src/app-window.vala
+++ b/src/app-window.vala
@@ -14,7 +14,7 @@ private const int DEFAULT_TEXT_DPI = 150;
 private const int DEFAULT_PHOTO_DPI = 300;
 
 [GtkTemplate (ui = "/org/gnome/SimpleScan/ui/app-window.ui")]
-public class AppWindow : Gtk.ApplicationWindow
+public class AppWindow : Hdy.ApplicationWindow
 {
     private const GLib.ActionEntry[] action_entries =
     {
@@ -48,13 +48,15 @@ public class AppWindow : Gtk.ApplicationWindow
     private bool user_selected_device;
 
     [GtkChild]
-    private Gtk.HeaderBar header_bar;
+    private Hdy.HeaderBar header_bar;
     [GtkChild]
     private Gtk.Menu page_menu;
     [GtkChild]
     private Gtk.Stack stack;
     [GtkChild]
-    private Gtk.Label status_primary_label;
+    private Hdy.StatusPage status_page;
+    [GtkChild]
+    private Gtk.Label status_secondary_label;
     [GtkChild]
     private Gtk.ListStore device_model;
     [GtkChild]
@@ -62,8 +64,6 @@ public class AppWindow : Gtk.ApplicationWindow
     [GtkChild]
     private Gtk.ComboBox device_combo;
     [GtkChild]
-    private Gtk.Label status_secondary_label;
-    [GtkChild]
     private Gtk.Box main_vbox;
     [GtkChild]
     private Gtk.RadioMenuItem custom_crop_menuitem;
@@ -251,16 +251,16 @@ public class AppWindow : Gtk.ApplicationWindow
         scan_button.sensitive = false;
         if (!have_devices)
         {
-            status_primary_label.set_text (/* Label shown when searching for scanners */
-                                           _("Searching for Scanners…"));
+            status_page.set_title (/* Label shown when searching for scanners */
+                                   _("Searching for Scanners…"));
             status_secondary_label.visible = false;
             device_buttons_box.visible = false;
         }
         else if (get_selected_device () != null)
         {
             scan_button.sensitive = true;
-            status_primary_label.set_text (/* Label shown when detected a scanner */
-                                           _("Ready to Scan"));
+            status_page.set_title (/* Label shown when detected a scanner */
+                                   _("Ready to Scan"));
             status_secondary_label.set_text (get_selected_device_label ());
             status_secondary_label.visible = false;
             device_buttons_box.visible = true;
@@ -269,8 +269,8 @@ public class AppWindow : Gtk.ApplicationWindow
         }
         else if (this.missing_driver != null)
         {
-            status_primary_label.set_text (/* Warning displayed when no drivers are installed but a 
compatible scanner is detected */
-                                           _("Additional software needed"));
+            status_page.set_title (/* Warning displayed when no drivers are installed but a compatible 
scanner is detected */
+                                   _("Additional Software Needed"));
             /* Instructions to install driver software */
             status_secondary_label.set_markup (_("You need to <a href=\"install-firmware\">install driver 
software</a> for your scanner."));
             status_secondary_label.visible = true;
@@ -279,9 +279,9 @@ public class AppWindow : Gtk.ApplicationWindow
         else
         {
             /* Warning displayed when no scanners are detected */
-            status_primary_label.set_text (_("No scanners detected"));
+            status_page.set_title (_("No Scanners Detected"));
             /* Hint to user on why there are no scanners detected */
-            status_secondary_label.set_text (_("Please check your scanner is connected and powered on"));
+            status_secondary_label.set_text (_("Please check your scanner is connected and powered on."));
             status_secondary_label.visible = true;
             device_buttons_box.visible = true;
             device_buttons_box.sensitive = true;
@@ -832,8 +832,8 @@ public class AppWindow : Gtk.ApplicationWindow
 
     private void scan (ScanOptions options)
     {
-        status_primary_label.set_text (/* Label shown when scan started */
-                                       _("Contacting scanner…"));
+        status_page.set_title (/* Label shown when scan started */
+                               _("Contacting Scanner…"));
         device_buttons_box.visible = true;
         device_buttons_box.sensitive = false;
         start_scan (get_selected_device (), options);
@@ -1845,8 +1845,12 @@ public class AppWindow : Gtk.ApplicationWindow
     private void load ()
     {
         preferences_dialog = new PreferencesDialog (settings);
-        preferences_dialog.delete_event.connect (() => { return true; });
-        preferences_dialog.response.connect (() => { preferences_dialog.visible = false; });
+        preferences_dialog.delete_event.connect (() => {
+            preferences_dialog.visible = false;
+            return true;
+        });
+        preferences_dialog.transient_for = this;
+        preferences_dialog.modal = true;
 
         Gtk.Window.set_default_icon_name ("org.gnome.SimpleScan");
 
@@ -1883,9 +1887,9 @@ public class AppWindow : Gtk.ApplicationWindow
         section.append (_("Email"), "app.email");
         section.append (_("Print"), "app.print");
         section.append (C_("menu", "Reorder Pages"), "app.reorder");
-        section.append (_("Preferences"), "app.preferences");
         section = new Menu ();
         gear_menu.append_section (null, section);
+        section.append (_("Preferences"), "app.preferences");
         section.append (_("Keyboard Shortcuts"), "win.show-help-overlay");
         section.append (_("Help"), "app.help");
         section.append (_("About Document Scanner"), "app.about");
diff --git a/src/meson.build b/src/meson.build
index a2c5adea..3f699ebc 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,5 +1,5 @@
 vala_args = [ '--pkg=posix', '--vapidir=' + meson.current_source_dir () ]
-dependencies = [ glib_dep, gtk_dep, zlib_dep, cairo_dep, gdk_pixbuf_dep, gusb_dep, sane_dep ]
+dependencies = [ glib_dep, gtk_dep, libhandy_dep, zlib_dep, cairo_dep, gdk_pixbuf_dep, gusb_dep, sane_dep ]
 if colord_dep.found ()
     vala_args += [ '-D', 'HAVE_COLORD' ]
     dependencies += colord_dep
diff --git a/src/preferences-dialog.vala b/src/preferences-dialog.vala
index ee3d031b..374fe7c3 100644
--- a/src/preferences-dialog.vala
+++ b/src/preferences-dialog.vala
@@ -11,7 +11,7 @@
  */
 
 [GtkTemplate (ui = "/org/gnome/SimpleScan/ui/preferences-dialog.ui")]
-private class PreferencesDialog : Gtk.Dialog
+private class PreferencesDialog : Hdy.PreferencesWindow
 {
     private Settings settings;
 
@@ -54,8 +54,6 @@ private class PreferencesDialog : Gtk.Dialog
 
     public PreferencesDialog (Settings settings)
     {
-        Object (use_header_bar: 1);
-
         this.settings = settings;
 
         Gtk.TreeIter iter;
diff --git a/src/simple-scan.vala b/src/simple-scan.vala
index 84d8a8c1..c15a5418 100644
--- a/src/simple-scan.vala
+++ b/src/simple-scan.vala
@@ -50,6 +50,8 @@ public class SimpleScan : Gtk.Application
     {
         base.startup ();
 
+        Hdy.init ();
+
         app = new AppWindow ();
         book = app.book;
         app.start_scan.connect (scan_cb);
diff --git a/subprojects/libhandy.wrap b/subprojects/libhandy.wrap
new file mode 100644
index 00000000..a3806c8d
--- /dev/null
+++ b/subprojects/libhandy.wrap
@@ -0,0 +1,4 @@
+[wrap-git]
+directory=libhandy
+url=https://gitlab.gnome.org/GNOME/libhandy.git
+revision=origin/master


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