[gnome-weather/wip/ewlsh/gtk4: 133/133] WIP: Porting to GTK4
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-weather/wip/ewlsh/gtk4: 133/133] WIP: Porting to GTK4
- Date: Sun, 14 Nov 2021 21:03:32 +0000 (UTC)
commit fdcbca3443081cfd54d0ae8a6fdb7c88f3273ad2
Author: Evan Welsh <contact evanwelsh com>
Date: Sun Nov 14 12:34:09 2021 -0800
WIP: Porting to GTK4
data/application.css | 4 -
data/city.ui | 59 ++--
data/day-entry.ui | 313 ++++++++------------
data/hour-entry.ui | 32 +--
data/org.gnome.Weather.data.gresource.xml | 1 -
data/places-popover.ui | 305 +++++++++-----------
data/primary-menu.ui | 2 +
data/weather-widget.ui | 447 ++++++++++++-----------------
data/window.ui | 134 ++++-----
meson.build | 8 +-
org.gnome.Weather.json | 21 +-
src/app/city.js | 133 +++++----
src/app/dailyForecast.js | 74 +++--
src/app/entry.js | 396 +++++++++++++++++++++++++
src/app/hourlyForecast.js | 39 ++-
src/app/main.js | 56 ++--
src/app/thermometer.js | 129 +++++----
src/app/window.js | 72 ++---
src/app/world.js | 141 +++++----
src/misc/util.js | 14 +-
src/org.gnome.Weather.src.gresource.xml.in | 1 +
src/service/main.js | 2 +-
22 files changed, 1324 insertions(+), 1059 deletions(-)
---
diff --git a/data/application.css b/data/application.css
index da39c9e..12dde99 100644
--- a/data/application.css
+++ b/data/application.css
@@ -83,7 +83,6 @@ viewswitchertitle viewswitcher {
button.osd.circular {
border-radius: 9999px;
- -gtk-outline-radius: 9999px;
min-width: 24px;
min-height: 24px;
}
@@ -92,9 +91,6 @@ button.osd.circular > image {
padding: 12px;
}
-.day-popover {
- background-color: @theme_base_color;
-}
.small-label {
font-size: 9pt;
diff --git a/data/city.ui b/data/city.ui
index 8d6c66b..5bc7e55 100644
--- a/data/city.ui
+++ b/data/city.ui
@@ -1,44 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.1 -->
<interface>
- <requires lib="gtk+" version="3.0"/>
- <template class="Gjs_WeatherView" parent="GtkStack">
- <property name="transition_type">crossfade</property>
- <child internal-child="accessible">
- <object class="AtkObject" id="weather-view-accessible">
- <property name="accessible-name" translatable="yes">City view</property>
- </object>
- </child>
+ <requires lib="gtk" version="4.0"/>
+ <template class="Gjs_WeatherView">
<child>
- <object class="GtkBox" id="loading-box">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="valign">center</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkSpinner" id="spinner">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="height_request">128</property>
- <property name="width_request">128</property>
- <property name="margin_bottom">18</property>
- <property name="active">True</property>
- </object>
- </child>
+ <object class="GtkStack" id="stack">
<child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label" translatable="yes">Loading…</property>
- <style>
- <class name="large-title"/>
- </style>
+ <object class="GtkStackPage">
+ <property name="name">loading</property>
+ <property name="child">
+ <object class="GtkGrid" id="loading-grid">
+ <property name="orientation">vertical</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <child>
+ <object class="GtkSpinner" id="spinner">
+ <property name="height_request">128</property>
+ <property name="width_request">128</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Loading…</property>
+ </object>
+ </child>
+ </object>
+ </property>
</object>
</child>
</object>
- <packing>
- <property name="name">loading</property>
- </packing>
</child>
</template>
-</interface>
+</interface>
\ No newline at end of file
diff --git a/data/day-entry.ui b/data/day-entry.ui
index d6648be..ccda671 100644
--- a/data/day-entry.ui
+++ b/data/day-entry.ui
@@ -1,356 +1,279 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.0 -->
<interface>
- <requires lib="gtk+" version="3.20"/>
+ <requires lib="gtk" version="4.0"/>
<object class="GtkPopoverMenu" id="more_menu">
- <property name="can_focus">False</property>
<style>
<class name="day-popover"/>
</style>
- <child>
+ <property name="child">
<object class="GtkGrid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="row_spacing">8</property>
<property name="column_spacing">16</property>
- <property name="row_homogeneous">True</property>
+
<property name="margin_top">16</property>
<property name="margin_bottom">16</property>
<property name="margin_start">16</property>
<property name="margin_end">16</property>
<child>
<object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Night</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
<style>
<class name="small-label"/>
</style>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
</child>
<child>
<object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Morning</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
<style>
<class name="small-label"/>
</style>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
- </packing>
</child>
<child>
<object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Afternoon</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
<style>
<class name="small-label"/>
</style>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">3</property>
- </packing>
</child>
<child>
<object class="GtkLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="halign">end</property>
<property name="label" translatable="yes">Evening</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
<style>
<class name="small-label"/>
</style>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">4</property>
- </packing>
</child>
<child>
<object class="GtkImage" id="nightImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">weather-showers-symbolic</property>
+ <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="GtkImage" id="morningImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">weather-showers-symbolic</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
- </packing>
</child>
<child>
<object class="GtkImage" id="afternoonImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">weather-showers-symbolic</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">3</property>
- </packing>
</child>
<child>
<object class="GtkImage" id="eveningImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">weather-showers-symbolic</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">4</property>
- </packing>
</child>
<child>
<object class="GtkGrid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="vexpand">True</property>
<property name="row_spacing">8</property>
- <property name="row_homogeneous">True</property>
- <property name="column_homogeneous">True</property>
+ <property name="row_homogeneous">1</property>
+ <property name="column_homogeneous">1</property>
<child>
<object class="GtkLabel" id="nightTemperatureLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">16°</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
</child>
<child>
<object class="GtkLabel" id="morningTemperatureLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">16°</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">2</property>
- </packing>
</child>
<child>
<object class="GtkLabel" id="afternoonTemperatureLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">16°</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">3</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">3</property>
- </packing>
</child>
<child>
<object class="GtkLabel" id="eveningTemperatureLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">16°</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">4</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">4</property>
- </packing>
</child>
<child>
<object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">temperature-symbolic</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
</child>
<child>
<object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">weather-showers-scattered-symbolic</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="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">weather-windy</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="nightHumidity">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">2.1 mm</property>
+ <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="morningHumidity">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">2.1 mm</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">2</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">2</property>
- </packing>
</child>
<child>
<object class="GtkLabel" id="afternoonHumidity">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">2.1 mm</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">3</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">3</property>
- </packing>
</child>
<child>
<object class="GtkLabel" id="eveningHumidity">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">2.1 mm</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">4</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">4</property>
- </packing>
</child>
<child>
<object class="GtkLabel" id="nightWind">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">5 m/s</property>
+ <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="GtkLabel" id="morningWind">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">5 m/s</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">2</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">2</property>
- </packing>
</child>
<child>
<object class="GtkLabel" id="afternoonWind">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">5 m/s</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">3</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">3</property>
- </packing>
</child>
<child>
<object class="GtkLabel" id="eveningWind">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">5 m/s</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">4</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">4</property>
- </packing>
</child>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ <property name="row-span">5</property>
+ </layout>
</object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- <property name="height">5</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
</child>
</object>
- </child>
+ </property>
</object>
- <template class="Gjs_DayEntry" parent="GtkBox">
+ <template class="Gjs_DayEntry">
<property name="width_request">100</property>
<property name="height_request">200</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="margin_top">18</property>
<property name="margin_bottom">18</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">18</property>
<child>
- <object class="GtkBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkLabel" id="nameLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label">Tues</property>
- </object>
- </child>
- <child>
- <object class="GtkLabel" id="dateLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label">7 June</property>
- <style>
- <class name="small-label"/>
- </style>
- </object>
- </child>
+ <object class="GtkLabel" id="nameLabel">
+ <property name="margin_top">8</property>
+ <property name="label">Tues</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dateLabel">
+ <property name="margin_top">8</property>
+ <property name="label">7 June</property>
</object>
</child>
<child>
<object class="GtkImage" id="image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="valign">start</property>
<property name="pixel_size">32</property>
<property name="icon_name">weather-showers-symbolic</property>
@@ -358,24 +281,19 @@
</child>
<child>
<object class="Gjs_Thermometer" id="thermometer">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
+
<property name="vexpand">True</property>
<property name="hexpand">True</property>
</object>
</child>
<child>
<object class="GtkMenuButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
<property name="halign">center</property>
+ <property name="icon_name">view-more-symbolic</property>
<property name="valign">center</property>
<property name="popover">more_menu</property>
<child>
<object class="GtkImage">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">view-more-symbolic</property>
</object>
</child>
@@ -386,5 +304,6 @@
</style>
</object>
</child>
+
</template>
</interface>
diff --git a/data/hour-entry.ui b/data/hour-entry.ui
index 0c27049..be5d9d3 100644
--- a/data/hour-entry.ui
+++ b/data/hour-entry.ui
@@ -1,40 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.0 -->
<interface>
- <requires lib="gtk+" version="3.20"/>
- <template class="Gjs_HourEntry" parent="GtkBox">
+ <requires lib="gtk" version="4.0"/>
+ <template class="Gjs_HourEntry">
<property name="width_request">75</property>
<property name="height_request">200</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">18</property>
+ <property name="hexpand">1</property>
+ <property name="vexpand">1</property>
+
<property name="margin_top">18</property>
<property name="margin_bottom">18</property>
+ <layout>
+ <property name="orientation">vertical</property>
+ <property name="spacing">18</property>
+ </layout>
<child>
<object class="GtkLabel" id="timeLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="label">Now</property>
</object>
</child>
<child>
<object class="GtkImage" id="image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="valign">start</property>
- <property name="vexpand">True</property>
+
+ <property name="valign">1</property>
+ <property name="vexpand">1</property>
<property name="pixel_size">32</property>
<property name="icon_name">weather-showers-symbolic</property>
</object>
</child>
<child>
<object class="GtkLabel" id="temperatureLabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="valign">end</property>
+
+ <property name="valign">2</property>
<property name="label">13°</property>
<style>
<class name="forecast-temperature-label"/>
diff --git a/data/org.gnome.Weather.data.gresource.xml b/data/org.gnome.Weather.data.gresource.xml
index eb357d3..22f274b 100644
--- a/data/org.gnome.Weather.data.gresource.xml
+++ b/data/org.gnome.Weather.data.gresource.xml
@@ -3,7 +3,6 @@
<gresource prefix="/org/gnome/Weather">
<file preprocess="xml-stripblanks">city.ui</file>
<file preprocess="xml-stripblanks">places-popover.ui</file>
- <file preprocess="xml-stripblanks">primary-menu.ui</file>
<file preprocess="xml-stripblanks">weather-widget.ui</file>
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">hour-entry.ui</file>
diff --git a/data/places-popover.ui b/data/places-popover.ui
index c96d16f..0d44f4a 100644
--- a/data/places-popover.ui
+++ b/data/places-popover.ui
@@ -1,228 +1,199 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.1 -->
<interface>
- <requires lib="gtk+" version="3.0"/>
+ <requires lib="gtk" version="4.0"/>
<object class="GtkGrid" id="popover-grid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="row_spacing">10</property>
- <property name="margin">12</property>
- <property name="vexpand">False</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="GWeatherLocationEntry" id="location-entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
+ <object class="Gjs_LocationSearchEntry" id="location-entry">
+ <property name="focusable">1</property>
<property name="width-request">300</property>
- <property name="activates_default">True</property>
+ <!-- <property name="activates_default">1</property> -->
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</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="GtkStack" id="auto-location-stack">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="vexpand">False</property>
- <property name="homogeneous">False</property>
+ <property name="vhomogeneous">0</property>
+ <property name="hhomogeneous">0</property>
<property name="transition_type">crossfade</property>
<child>
- <object class="GtkGrid" id="auto-location-grid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">horizontal</property>
- <property name="column_homogeneous">True</property>
- <property name="margin_top">6</property>
- <property name="margin_bottom">6</property>
- <property name="vexpand">False</property>
- <child>
- <object class="GtkLabel" id="auto-location-label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="label" translatable="yes">Automatic Location</property>
- <property name="halign">start</property>
- <property name="vexpand">False</property>
- <attributes>
- <attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
- </attributes>
- <style>
- <class name="dim-label"/>
- </style>
- </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="GtkSwitch" id="auto-location-switch">
- <property name="visible">True</property>
- <property name="halign">end</property>
- <property name="vexpand">False</property>
+ <object class="GtkStackPage">
+ <property name="name">auto-location-switch-grid</property>
+ <property name="child">
+ <object class="GtkGrid" id="auto-location-grid">
+ <property name="column_homogeneous">1</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <child>
+ <object class="GtkLabel" id="auto-location-label">
+ <property name="label" translatable="yes">Automatic Location</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="PANGO_WEIGHT_BOLD"></attribute>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSwitch" id="auto-location-switch">
+ <property name="halign">end</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
+ </property>
</object>
- <packing>
- <property name="name">auto-location-switch-grid</property>
- </packing>
</child>
<child>
- <object class="GtkLabel" id="locating-label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="label" translatable="yes">Locating…</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="vexpand">False</property>
- </object>
- <packing>
+ <object class="GtkStackPage">
<property name="name">locating-label</property>
- </packing>
+ <property name="child">
+ <object class="GtkLabel" id="locating-label">
+ <property name="label" translatable="yes">Locating…</property>
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ </object>
+ </property>
+ </object>
</child>
- </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>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
</child>
<child>
<object class="GtkStack" id="popover-stack">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="vexpand">False</property>
- <property name="homogeneous">False</property>
+ <property name="vhomogeneous">0</property>
+ <property name="hhomogeneous">0</property>
<child>
- <object class="GtkGrid" id="search-grid">
- <property name="visible">True</property>
+ <object class="GtkGrid" id="empty-search-grid">
<property name="name">search-city-grid</property>
- <property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="margin_top">25</property>
<property name="margin_bottom">25</property>
<property name="halign">center</property>
<property name="valign">center</property>
- <property name="row_homogeneous">True</property>
- <property name="vexpand">False</property>
+ <property name="row_homogeneous">1</property>
+
+
<child>
<object class="GtkImage" id="search-image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">edit-find-symbolic</property>
- <property name="icon_size">6</property>
- <property name="use_fallback">True</property>
+ <property name="icon_size">2</property>
+ <property name="use_fallback">1</property>
<property name="halign">center</property>
<property name="valign">center</property>
- <property name="vexpand">False</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</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="GtkLabel" id="search-label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
<property name="label" translatable="yes">Search for a city</property>
<property name="halign">center</property>
<property name="valign">center</property>
- <property name="vexpand">False</property>
<style>
<class name="dim-label"/>
</style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">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>
- </object>
- <packing>
- <property name="name">search-grid</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="locations-grid">
- <property name="visible">True</property>
- <property name="name">locations-grid</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="row_spacing">10</property>
- <property name="vexpand">False</property>
<child>
- <object class="GtkLabel" id="recently-viewed-label">
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="label" translatable="yes">Viewed Recently</property>
- <property name="halign">start</property>
- <property name="vexpand">False</property>
- <attributes>
- <attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
- </attributes>
- <style>
- <class name="dim-label"/>
- </style>
+ <object class="GtkGrid" id="search-grid">
+ <property name="name">search-grid</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">10</property>
+ <child>
+ <object class="GtkScrolledWindow" id="city-search-scroll">
+ <child>
+ <object class="GtkListView" id="city-search-results">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="hexpand">True</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
</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="GtkFrame" id="locations-frame">
- <property name="name">locations-frame</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
+ <object class="GtkGrid" id="locations-grid">
+ <property name="name">locations-grid</property>
+ <property name="orientation">vertical</property>
+ <property name="row_spacing">10</property>
+ <child>
+ <object class="GtkLabel" id="recently-viewed-label">
+ <property name="label" translatable="yes">Viewed Recently</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="PANGO_WEIGHT_BOLD"></attribute>
+ </attributes>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
<child>
- <object class="GtkListBox" id="locations-list-box">
- <property name="name">locations-list-box</property>
- <property name="visible">True</property>
- <property name="can-focus">False</property>
- <property name="hexpand">True</property>
- <property name="vexpand">False</property>
- <property name="selection-mode">none</property>
+ <object class="GtkFrame" id="locations-frame">
+ <property name="name">locations-frame</property>
+ <property name="child">
+ <object class="GtkListBox" id="locations-list-box">
+ <property name="name">locations-list-box</property>
+ <property name="hexpand">1</property>
+ <property name="selection-mode">none</property>
+ </object>
+ </property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
</object>
</child>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">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>
</object>
- <packing>
- <property name="name">locations-grid</property>
- </packing>
</child>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
</object>
- <packing>
- <property name="left-attach">0</property>
- <property name="top-attach">2</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
</child>
</object>
</interface>
diff --git a/data/primary-menu.ui b/data/primary-menu.ui
index c6d55f0..67f0b35 100644
--- a/data/primary-menu.ui
+++ b/data/primary-menu.ui
@@ -1,4 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
+ <requires lib="gtk" version="4.0"/>
<menu id="primary-menu">
<submenu>
<attribute translatable="yes" name="label">_Temperature Unit</attribute>
diff --git a/data/weather-widget.ui b/data/weather-widget.ui
index a2d7753..2acc50f 100644
--- a/data/weather-widget.ui
+++ b/data/weather-widget.ui
@@ -1,307 +1,230 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.0 -->
<interface>
- <requires lib="gtk+" version="3.0"/>
- <template class="Gjs_WeatherWidget" parent="GtkFrame">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
+ <requires lib="gtk" version="4.0"/>
+ <template class="Gjs_WeatherWidget">
+
+
<child>
- <object class="GtkFrame" id="contentFrame">
- <property name="name">weather-page-content-view</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
+ <object class="AdwClamp" id="clamp">
+ <property name="maximum_size">1010</property>
+ <property name="tightening_threshold">600</property>
<child>
- <object class="HdyClamp">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="maximum_size">1010</property>
- <property name="tightening_threshold">600</property>
+ <object class="GtkBox" id="outerBox">
+ <property name="orientation">vertical</property>
+ <property name="margin-start">18</property>
+ <property name="margin-end">18</property>
+ <property name="margin-top">18</property>
+ <property name="margin-bottom">18</property>
+ <!-- <property name="spacing">18</property> -->
<child>
- <object class="GtkBox" id="outerBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="margin">18</property>
- <property name="spacing">18</property>
+ <object class="GtkGrid">
+ <property name="name">conditions-grid</property>
+ <property name="column_spacing">10</property>
<child>
- <object class="GtkGrid" id="inner-grid">
- <property name="name">conditions-grid</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="column_spacing">10</property>
- <child>
- <object class="GtkImage" id="conditionsImage">
- <property name="name">conditions-image</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">center</property>
- <property name="pixel_size">84</property>
- <style>
- <class name="icon-dropshadow"/>
- </style>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="height">2</property>
- </packing>
- </child>
+ <object class="GtkImage" id="conditionsImage">
+ <!-- <property name="name">conditions-image</property> -->
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="pixel_size">84</property>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="row-span">2</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton" id="placesButton">
+ <property name="receives_default">1</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
<child>
- <object class="GtkMenuButton" id="placesButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="focus_on_click">False</property>
- <property name="receives_default">True</property>
- <property name="halign">start</property>
- <property name="valign">start</property>
+ <object class="GtkBox" id="placesBox">
+ <property name="spacing">12</property>
<child>
- <object class="GtkBox" id="placesBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkLabel" id="placesLabel">
- <property name="name">places-label</property>
- <property name="wrap">True</property>
- <property name="wrap-mode">word-char</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Places</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkImage" id="placesImage">
- <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 class="GtkLabel" id="placesLabel">
+ <property name="name">places-label</property>
+ <property name="wrap">1</property>
+ <property name="wrap-mode">word-char</property>
+ <property name="label" translatable="yes">Places</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage">
+ <property name="icon_name">pan-down-symbolic</property>
</object>
</child>
- <style>
- <class name="text-button"/>
- <class name="flat"/>
- </style>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
</child>
+ <style>
+ <class name="text-button"/>
+ <class name="flat"/>
+ </style>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox" id="temperatureBox">
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="spacing">8</property> -->
+ <property name="baseline_position">bottom</property>
<child>
- <object class="GtkBox" id="temperatureBox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
+ <object class="GtkLabel" id="temperatureLabel">
+ <property name="name">temperature-label</property>
<property name="halign">start</property>
- <property name="valign">start</property>
- <property name="spacing">8</property>
- <property name="baseline_position">bottom</property>
- <child>
- <object class="GtkLabel" id="temperatureLabel">
- <property name="name">temperature-label</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">baseline</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="apparentLabel">
- <property name="name">apparent-label</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
- <property name="valign">baseline</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="valign">baseline</property>
</object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- </packing>
</child>
- <child internal-child="accessible">
- <object class="AtkObject" id="inner-grid-atkobject">
- <property name="AtkObject::accessible-name" translatable="yes">Current
conditions</property>
+ <child>
+ <object class="GtkLabel" id="apparentLabel">
+ <property name="name">apparent-label</property>
+ <property name="halign">start</property>
+ <property name="valign">baseline</property>
</object>
</child>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
</object>
</child>
- <child>
- <object class="GtkOverlay" id="forecast-overlay">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkFrame" id="forecastFrame">
+ </object>
+ </child>
+ <child>
+ <object class="GtkOverlay">
+ <property name="child">
+ <!-- <object class="GtkFrame" id="forecastFrame">
<property name="name">forecast-frame</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="shadow-type">GTK_SHADOW_IN</property>
- <child>
- <object class="GtkStack" id="forecastStack">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="transition_type">crossfade</property>
- <child>
- <object class="GtkScrolledWindow" id="forecast-hourly">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="vscrollbar_policy">never</property>
- <property name="min_content_width">308</property>
- <child>
- <object class="GtkViewport" id="forecast-hourly-viewport">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hscroll_policy">natural</property>
- <property name="vscroll_policy">natural</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="name">hourly</property>
- <property name="title" translatable="yes">Hourly</property>
- <property name="icon-name">preferences-system-time-symbolic</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="forecast-daily">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="vscrollbar_policy">never</property>
- <property name="min_content_width">308</property>
- <child>
- <object class="GtkViewport" id="forecast-daily-viewport">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hscroll_policy">natural</property>
- <property name="vscroll_policy">natural</property>
- </object>
- </child>
+ <property name="child"> -->
+ <object class="AdwViewStack" id="forecastStack">
+ <!-- <property name="transition_type">crossfade</property> -->
+ <child>
+ <object class="AdwViewStackPage">
+ <property name="name">hourly</property>
+ <property name="title" translatable="yes">Hourly</property>
+ <property name="icon-name">preferences-system-time-symbolic</property>
+ <property name="child">
+ <object class="GtkScrolledWindow" id="forecastHourly">
+ <property name="focusable">1</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="min_content_width">308</property>
+ <property name="child">
+ <object class="GtkViewport" id="forecastHourlyViewport">
+ <property name="hscroll_policy">natural</property>
+ <property name="vscroll_policy">natural</property>
</object>
- <packing>
- <property name="name">daily</property>
- <property name="title" translatable="yes">Daily</property>
- <property name="icon-name">x-office-calendar-symbolic</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="index">-1</property>
- </packing>
- </child>
- <child type="overlay">
- <object class="GtkButton" id="rightButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="halign">end</property>
- <property name="valign">center</property>
- <property name="margin_end">28</property>
- <child>
- <object class="GtkImage" id="right-image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">go-next-symbolic</property>
+ </property>
</object>
- </child>
- <style>
- <class name="osd"/>
- <class name="circular"/>
- </style>
+ </property>
</object>
</child>
- <child type="overlay">
- <object class="GtkButton" id="leftButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="halign">start</property>
- <property name="valign">center</property>
- <property name="margin_start">28</property>
- <child>
- <object class="GtkImage" id="left-image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="icon_name">go-previous-symbolic</property>
- <property name="icon_size">1</property>
+ <child>
+ <object class="AdwViewStackPage">
+ <property name="name">daily</property>
+ <property name="title" translatable="yes">Daily</property>
+ <property name="icon-name">x-office-calendar-symbolic</property>
+ <property name="child">
+ <object class="GtkScrolledWindow" id="forecastDaily">
+ <property name="focusable">1</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="min_content_width">308</property>
+ <property name="child">
+ <object class="GtkViewport" id="forecastDailyViewport">
+ <property name="hscroll_policy">natural</property>
+ <property name="vscroll_policy">natural</property>
+ </object>
+ </property>
</object>
- </child>
- <style>
- <class name="osd"/>
- <class name="circular"/>
- </style>
+ </property>
</object>
- <packing>
- <property name="index">1</property>
- </packing>
</child>
</object>
- </child>
- <child>
- <object class="GtkGrid">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="row_spacing">8</property>
+ <!-- </property>
+ </object> -->
+ </property>
+ <child type="overlay">
+ <object class="GtkButton" id="rightButton">
+ <property name="focusable">1</property>
+ <property name="receives_default">1</property>
+ <property name="halign">end</property>
+ <property name="valign">center</property>
+ <property name="margin_end">28</property>
<child>
- <object class="GtkLabel" id="updatedTimeLabel">
- <property name="name">updated-time-label</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="halign">start</property>
+ <object class="GtkImage" id="right-image">
+ <property name="icon_name">go-next-symbolic</property>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
</child>
+ <style>
+ <class name="osd"/>
+ <class name="circular"/>
+ </style>
+ </object>
+ </child>
+ <child type="overlay">
+ <object class="GtkButton" id="leftButton">
+ <property name="focusable">1</property>
+ <property name="receives_default">1</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="margin_start">28</property>
<child>
- <object class="GtkLabel" id="attributionLabel">
- <property name="name">attribution-label</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_markup">True</property>
- <property name="wrap">True</property>
- <property name="track_visited_links">False</property>
- <property name="xalign">0</property>
+ <object class="GtkImage" id="left-image">
+ <property name="icon_name">go-previous-symbolic</property>
+ <property name="icon_size">1</property>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- </packing>
</child>
+ <style>
+ <class name="osd"/>
+ <class name="circular"/>
+ </style>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid">
+ <property name="row_spacing">8</property>
+ <child>
+ <object class="GtkLabel" id="updatedTimeLabel">
+ <property name="name">updated-time-label</property>
+ <property name="halign">start</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="attributionLabel">
+ <property name="name">attribution-label</property>
+ <property name="use_markup">1</property>
+ <property name="wrap">1</property>
+ <!-- <property name="track_visited_links">False</property> -->
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
</object>
</child>
</object>
</child>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ </layout>
</object>
</child>
</object>
</child>
+
+
</template>
</interface>
diff --git a/data/window.ui b/data/window.ui
index b16a804..a46ec83 100644
--- a/data/window.ui
+++ b/data/window.ui
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.22.0 -->
<interface>
- <requires lib="gtk+" version="3.10"/>
+ <requires lib="gtk" version="4.0"/>
<menu id="primary-menu">
<submenu>
<attribute translatable="yes" name="label">_Temperature Unit</attribute>
@@ -23,133 +22,118 @@
</item>
</section>
</menu>
- <template class="Gjs_MainWindow" parent="HdyApplicationWindow">
- <property name="visible">True</property>
+ <template class="Gjs_MainWindow">
+
<property name="default_width">760</property>
<property name="default_height">520</property>
<child>
<object class="GtkBox">
- <property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
- <object class="HdyHeaderBar" id="header">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="vexpand">False</property>
- <property name="show_close_button">True</property>
- <property name="centering_policy">strict</property>
+ <object class="AdwHeaderBar" id="header">
+ <!-- <property name="show_close_button">True</property> -->
+ <!-- <property name="centering_policy">strict</property> -->
<child>
<object class="GtkRevealer" id="refreshRevealer">
- <property name="visible">True</property>
<property name="transition_type">crossfade</property>
- <child>
+ <property name="child">
<object class="GtkButton" id="refresh">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
+ <property name="focusable">1</property>
<property name="valign">center</property>
<property name="tooltip-text" translatable="yes">Refresh</property>
<property name="action_name">win.refresh</property>
<child>
<object class="GtkImage" id="refresh-button-image">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="icon_name">view-refresh-symbolic</property>
</object>
</child>
</object>
- </child>
+ </property>
</object>
</child>
<child type="title">
<object class="GtkStack" id="titleStack">
- <property name="visible">True</property>
<property name="visible-child-name" bind-source="stack" bind-property="visible-child-name"
bind-flags="bidirectional|sync-create"/>
<property name="transition_type">crossfade</property>
<child>
- <object class="GtkLabel">
- <property name="visible">True</property>
- <property name="ellipsize">end</property>
- <property name="halign">center</property>
- <property name="wrap">False</property>
- <property name="single-line-mode">True</property>
- <property name="width-chars">5</property>
- <property name="label" translatable="yes">Select Location</property>
- <style>
- <class name="title"/>
- </style>
- </object>
- <packing>
+ <object class="GtkStackPage">
<property name="name">search</property>
- </packing>
+ <property name="child">
+ <object class="GtkLabel">
+ <property name="ellipsize">end</property>
+ <property name="halign">center</property>
+ <property name="single-line-mode">1</property>
+ <property name="width-chars">5</property>
+ <property name="label" translatable="yes">Select Location</property>
+ <style>
+ <class name="title"/>
+ </style>
+ </object>
+ </property>
+ </object>
</child>
<child>
- <object class="HdyViewSwitcherTitle" id="forecastStackSwitcher">
- <property name="visible">True</property>
- <property name="title" translatable="yes">Weather</property>
- </object>
- <packing>
+ <object class="GtkStackPage">
<property name="name">city</property>
- </packing>
+ <property name="child">
+ <object class="AdwViewSwitcherTitle" id="forecastStackSwitcher">
+
+ <property name="title" translatable="yes">Weather</property>
+ </object>
+ </property>
+ </object>
</child>
</object>
</child>
<child>
- <object class="GtkMenuButton" id="primary-menu-button">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
+ <object class="GtkMenuButton">
+ <property name="focusable">1</property>
<property name="valign">center</property>
<property name="menu_model">primary-menu</property>
<child>
- <object class="GtkImage" id="primary-menu-img">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
+ <object class="GtkImage">
<property name="icon_name">open-menu-symbolic</property>
</object>
</child>
</object>
- <packing>
- <property name="pack_type">end</property>
- </packing>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="stack">
- <property name="can_focus">False</property>
+
<property name="transition_type">crossfade</property>
<child>
- <object class="HdyStatusPage" id="searchView">
- <property name="visible">True</property>
- <property name="icon_name">mark-location-symbolic</property>
- <property name="title" translatable="yes">Welcome to Weather!</property>
- <property name="description" translatable="yes">To get started, select a location.</property>
- <child>
- <object class="GWeatherLocationEntry" id="searchEntry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="activates_default">True</property>
- <property name="hexpand">False</property>
- <property name="halign">center</property>
- <property name="width-request">246</property>
- <property name="placeholder_text" translatable="yes">Search for a city or
country</property>
+ <object class="GtkStackPage">
+ <property name="name">search</property>
+ <property name="child">
+ <object class="AdwStatusPage" id="searchView">
+
+ <property name="icon_name">mark-location-symbolic</property>
+ <property name="title" translatable="yes">Welcome to Weather!</property>
+ <property name="description" translatable="yes">To get started, select a
location.</property>
+ <child>
+ <object class="Gjs_LocationSearchEntry" id="searchEntry">
+ <!-- <property name="hexpand">False</property>
+ <property name="halign">center</property>
+ <property name="width-request">246</property> -->
+ <!-- <property name="placeholder_text" translatable="yes">Search for a city or
country</property> -->
+ </object>
+ </child>
+ <style>
+ <class name="search-view"/>
+ </style>
</object>
- </child>
- <style>
- <class name="search-view"/>
- </style>
+ </property>
</object>
- <packing>
- <property name="name">search</property>
- </packing>
</child>
+
</object>
</child>
<child>
- <object class="HdyViewSwitcherBar" id="forecastStackSwitcherBar">
- <property name="visible">True</property>
- <property name="reveal" bind-source="forecastStackSwitcher" bind-property="title-visible"
bind-flags="sync-create" />
+ <object class="AdwViewSwitcherBar" id="forecastStackSwitcherBar">
+
+ <property name="reveal" bind-source="forecastStackSwitcher" bind-property="title-visible"
bind-flags="sync-create"/>
</object>
</child>
</object>
diff --git a/meson.build b/meson.build
index dc0f1b8..5c08bab 100644
--- a/meson.build
+++ b/meson.build
@@ -9,11 +9,11 @@ gnome = import('gnome')
dependency('glib-2.0')
dependency('gobject-introspection-1.0', version: '>=1.35.9')
-dependency('gtk+-3.0', version :'>=3.20')
-dependency('gjs-1.0', version: '>= 1.50.0')
+dependency('gtk4', version :'>=4.0')
+dependency('gjs-1.0', version: '>= 1.71.0')
dependency('geoclue-2.0', version: '>= 0.12.99')
-dependency('gweather-3.0', version: '>= 40.0')
-dependency('libhandy-1', version: '>= 1.1.90')
+dependency('libadwaita-1')
+dependency('gweather4', version: '>= 3.90.0')
# Profiles
if get_option('profile') == 'development'
diff --git a/org.gnome.Weather.json b/org.gnome.Weather.json
index 36b18fe..e8ced94 100644
--- a/org.gnome.Weather.json
+++ b/org.gnome.Weather.json
@@ -54,32 +54,21 @@
{
"type" : "git",
"url" : "https://gitlab.gnome.org/GNOME/libgweather.git",
- "tag" : "40.0"
+ "branch" : "main"
}
]
},
{
- "name" : "gnome-desktop",
+ "name" : "libadwaita",
"buildsystem" : "meson",
"config-opts" : [
- "-Ddebug_tools=false",
- "-Dudev=disabled",
- "-Ddesktop_docs=false"
+ "-Denable_vala=false",
+ "-Dgtk_doc=false"
],
"sources" : [
{
"type" : "git",
- "url" : "https://gitlab.gnome.org/GNOME/gnome-desktop.git"
- }
- ]
- },
- {
- "name" : "libhandy",
- "buildsystem" : "meson",
- "sources" : [
- {
- "type" : "git",
- "url" : "https://gitlab.gnome.org/GNOME/libhandy.git"
+ "url" : "https://gitlab.gnome.org/GNOME/libadwaita.git"
}
]
},
diff --git a/src/app/city.js b/src/app/city.js
index cf669c8..946f218 100644
--- a/src/app/city.js
+++ b/src/app/city.js
@@ -18,7 +18,6 @@
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
-const Gnome = imports.gi.GnomeDesktop;
const GObject = imports.gi.GObject;
const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;
@@ -37,45 +36,38 @@ const UPDATED_TIME_TIMEOUT = 60; //s
var WeatherWidget = GObject.registerClass({
Template: 'resource:///org/gnome/Weather/weather-widget.ui',
- InternalChildren: ['contentFrame', 'outerBox',
- 'conditionsImage', 'placesButton', 'placesLabel',
- 'temperatureLabel', 'apparentLabel',
- 'forecastFrame', 'forecastStack',
- 'leftButton', 'rightButton',
- 'forecast-hourly', 'forecast-hourly-viewport',
- 'forecast-daily', 'forecast-daily-viewport',
- 'updatedTimeLabel', 'attributionLabel'],
-}, class WeatherWidget extends Gtk.Frame {
-
- _init(application, window, params) {
- super._init(Object.assign({
- shadow_type: Gtk.ShadowType.NONE,
+ InternalChildren: ['clamp',
+ 'conditionsImage', 'placesButton',
+ 'temperatureLabel', 'apparentLabel',
+ 'forecastStack',
+ 'leftButton', 'rightButton',
+ 'forecastHourly', 'forecastHourlyViewport',
+ 'forecastDaily', 'forecastDailyViewport',
+ 'updatedTimeLabel', 'attributionLabel'],
+}, class WeatherWidget extends Gtk.Widget {
+ _init(application, window) {
+ super._init({
name: 'weather-page'
- }, params));
+ });
this._info = null;
this._worldView = new WorldView.WorldContentView(application, window);
this._placesButton.set_popover(this._worldView);
- this._forecasts = { };
-
- for (let t of ['hourly', 'daily']) {
- let box;
- if (t == 'hourly') {
- box = new HourlyForecast.HourlyForecastBox();
- } else {
- box = new DailyForecast.DailyForecastBox();
- }
-
- this._forecasts[t] = box;
- this['_forecast_' + t + '_viewport'].add(box);
+ this._forecasts = {
+ hourly: new HourlyForecast.HourlyForecastBox(),
+ daily: new DailyForecast.DailyForecastBox(),
+ };
+ this._forecastHourlyViewport.set_child(this._forecasts.hourly);
+ this._forecastDailyViewport.set_child(this._forecasts.daily);
- let fsw = this['_forecast_' + t];
- let hscrollbar = fsw.get_hscrollbar();
+ for (const scrollWindow of [this._forecastHourly, this._forecastDaily]) {
+ let hscrollbar = scrollWindow.get_hscrollbar();
hscrollbar.set_opacity(0.0);
hscrollbar.hide();
- let hadjustment = fsw.get_hadjustment();
+
+ let hadjustment = scrollWindow.get_hadjustment();
hadjustment.connect('changed', () => this._syncLeftRightButtons());
hadjustment.connect('value-changed', () => this._syncLeftRightButtons());
}
@@ -111,29 +103,29 @@ var WeatherWidget = GObject.registerClass({
this._beginScrollAnimation(target);
});
- this._forecastFrame.connect('draw', (frame, cr) => {
- const width = frame.get_allocated_width();
- const height = frame.get_allocated_height();
+ // this._forecastFrame.connect('draw', (frame, cr) => {
+ // const width = frame.get_allocated_width();
+ // const height = frame.get_allocated_height();
- const borderRadius = 8;
+ // const borderRadius = 8;
- const arc0 = 0.0;
- const arc1 = Math.PI * 0.5
- const arc2 = Math.PI;
- const arc3 = Math.PI * 1.5
+ // const arc0 = 0.0;
+ // const arc1 = Math.PI * 0.5
+ // const arc2 = Math.PI;
+ // const arc3 = Math.PI * 1.5
- cr.newSubPath();
- cr.arc(width - borderRadius, borderRadius, borderRadius, arc3, arc0);
- cr.arc(width - borderRadius, height - borderRadius, borderRadius, arc0, arc1);
- cr.arc(borderRadius, height - borderRadius, borderRadius, arc1, arc2);
- cr.arc(borderRadius, borderRadius, borderRadius, arc2, arc3);
- cr.closePath();
+ // cr.newSubPath();
+ // cr.arc(width - borderRadius, borderRadius, borderRadius, arc3, arc0);
+ // cr.arc(width - borderRadius, height - borderRadius, borderRadius, arc0, arc1);
+ // cr.arc(borderRadius, height - borderRadius, borderRadius, arc1, arc2);
+ // cr.arc(borderRadius, borderRadius, borderRadius, arc2, arc3);
+ // cr.closePath();
- cr.clip();
- cr.fill();
+ // cr.clip();
+ // cr.fill();
- return false;
- });
+ // return false;
+ // });
this._updatedTime = null;
this._updatedTimeTimeoutId = 0;
@@ -141,6 +133,15 @@ var WeatherWidget = GObject.registerClass({
this.connect('destroy', () => this._onDestroy());
}
+ // vfunc_measure(orientation, for_size) {
+ // return this._box.measure(orientation, for_size);
+ // }
+
+ _cleanup() {
+ // this._contentGrid.unparent();
+ this._worldView._cleanup();
+ }
+
_onDestroy() {
if (this._updatedTimeTimeoutId) {
GLib.Source.remove(this._updatedTimeTimeoutId);
@@ -153,10 +154,10 @@ var WeatherWidget = GObject.registerClass({
if ((hadjustment.get_upper() - hadjustment.get_lower()) == hadjustment.page_size) {
this._leftButton.hide();
this._rightButton.hide();
- } else if (hadjustment.value == hadjustment.get_lower()){
+ } else if (hadjustment.value == hadjustment.get_lower()) {
this._leftButton.hide();
this._rightButton.show();
- } else if (hadjustment.value >= (hadjustment.get_upper() - hadjustment.page_size)){
+ } else if (hadjustment.value >= (hadjustment.get_upper() - hadjustment.page_size)) {
this._leftButton.show();
this._rightButton.hide();
} else {
@@ -183,7 +184,7 @@ var WeatherWidget = GObject.registerClass({
if (now < end) {
t = (now - start) / SCROLLING_ANIMATION_TIME;
- t = Util.easeOutCubic (t);
+ t = Util.easeOutCubic(t);
hadjustment.value = value + t * (target - value);
return true;
} else {
@@ -220,13 +221,13 @@ var WeatherWidget = GObject.registerClass({
country = country.get_parent();
if (country)
- this._placesLabel.set_text(city.get_name() + ', ' + country.get_name());
+ this._placesButton.set_label(city.get_name() + ', ' + country.get_name());
else
- this._placesLabel.set_text(city.get_name());
+ this._placesButton.set_label(city.get_name());
this._worldView.refilter();
- this._conditionsImage.iconName = info.get_icon_name() + '-large';
+ this._conditionsImage.iconName = `${info.get_icon_name()}-large`;
const [, tempValue] = info.get_value_temp(GWeather.TemperatureUnit.DEFAULT);
this._temperatureLabel.label = '%d°'.format(Math.round(tempValue));
@@ -295,26 +296,32 @@ var WeatherWidget = GObject.registerClass({
}
});
+WeatherWidget.set_layout_manager_type(Gtk.BoxLayout);
+
+
var WeatherView = GObject.registerClass({
Template: 'resource:///org/gnome/Weather/city.ui',
- InternalChildren: ['spinner']
-}, class WeatherView extends Gtk.Stack {
+
+ InternalChildren: ['spinner', 'stack']
+}, class WeatherView extends Gtk.Widget {
_init(application, window, params) {
super._init(params);
this._infoPage = new WeatherWidget(application, window);
- this.add_named(this._infoPage, 'info');
+ this._stack.add_named(this._infoPage, 'info');
this._info = null;
this._updateId = 0;
this.connect('destroy', () => this._onDestroy());
- this._wallClock = new Gnome.WallClock();
- this._clockHandlerId = 0;
-
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
+
+ }
+
+ _cleanup() {
+ this._infoPage._cleanup();
}
get info() {
@@ -348,7 +355,7 @@ var WeatherView = GObject.registerClass({
}
update() {
- this.visible_child_name = 'loading';
+ this._stack.visible_child_name = 'loading';
this._spinner.start();
this._infoPage.clear();
@@ -359,10 +366,12 @@ var WeatherView = GObject.registerClass({
this._infoPage.clear();
this._infoPage.update(info);
this._spinner.stop();
- this.visible_child_name = 'info';
+ this._stack.visible_child_name = 'info';
}
getInfoPage() {
return this._infoPage;
}
});
+
+WeatherView.set_layout_manager_type(Gtk.BinLayout);
\ No newline at end of file
diff --git a/src/app/dailyForecast.js b/src/app/dailyForecast.js
index e3c71e8..3ac5ad9 100644
--- a/src/app/dailyForecast.js
+++ b/src/app/dailyForecast.js
@@ -20,6 +20,7 @@ const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
+const Gdk = imports.gi.Gdk;
const GWeather = imports.gi.GWeather;
const Thermometer = imports.app.thermometer;
@@ -28,14 +29,14 @@ const Util = imports.misc.util;
var DailyForecastBox = GObject.registerClass(class DailyForecastBox extends Gtk.Box {
- _init(params) {
- super._init(Object.assign({
+ _init() {
+ super._init({
orientation: Gtk.Orientation.HORIZONTAL,
spacing: 0,
name: 'daily-forecast-box',
- }, params));
+ });
- this.get_accessible().accessible_name = _('Daily Forecast');
+ this.update_property([Gtk.AccessibleProperty.LABEL], [_('Daily Forecast')]);
}
// get infos for the correct day
@@ -60,8 +61,8 @@ var DailyForecastBox = GObject.registerClass(class DailyForecastBox extends Gtk.
let weekInfos = [];
while (i < infos.length) {
- let dayInfos = {day: day, infos: []};
- for ( ; i < infos.length; i++) {
+ let dayInfos = { day: day, infos: [] };
+ for (; i < infos.length; i++) {
let info = infos[i];
let datetime = Util.getDateTime(info);
@@ -100,14 +101,16 @@ var DailyForecastBox = GObject.registerClass(class DailyForecastBox extends Gtk.
this._addSeparator();
}
} else {
- let label = new Gtk.Label({ label: _('Forecast not available'),
- use_markup: true,
- visible: true });
- this.pack_start(label, true, false, 0);
+ let label = new Gtk.Label({
+ label: _('Forecast not available'),
+ use_markup: true,
+ visible: true
+ });
+ this.prepend(label);
}
}
- _addDayEntry({day, infos}, weekHighestTemp, weekLowestTemp) {
+ _addDayEntry({ day, infos }, weekHighestTemp, weekLowestTemp) {
let maxInfo;
let maxTemp = -Infinity;
@@ -189,12 +192,12 @@ var DailyForecastBox = GObject.registerClass(class DailyForecastBox extends Gtk.
let dateFormat = _('%b %e');
dayEntry.dateLabel.label = day.format(dateFormat);
- dayEntry.image.iconName = dayInfo.get_icon_name() + '-small';
+ dayEntry.image.iconName = `${dayInfo.get_icon_name()}-small`;
const adjustment = Gtk.Adjustment.new(minTemp,
- weekLowestTemp, weekHighestTemp,
- 0, 0,
- maxTemp - minTemp);
+ weekLowestTemp, weekHighestTemp,
+ 0, 0,
+ maxTemp - minTemp);
dayEntry.thermometer.adjustment = adjustment;
dayEntry.nightTemperatureLabel.label = Util.getTempString(nightInfo);
@@ -217,19 +220,21 @@ var DailyForecastBox = GObject.registerClass(class DailyForecastBox extends Gtk.
dayEntry.eveningHumidity.label = eveningInfo.get_humidity();
this._setWindInfo(eveningInfo, dayEntry.eveningWind);
- this.pack_start(dayEntry, false, false, 0);
+ this.prepend(dayEntry);
}
_addSeparator() {
- let separator = new Gtk.Separator({ orientation: Gtk.Orientation.VERTICAL,
- visible: true});
- this.pack_start(separator, false, false, 0);
+ let separator = new Gtk.Separator({
+ orientation: Gtk.Orientation.VERTICAL,
+ visible: true
+ });
+ this.prepend(separator);
}
_setWindInfo(info, label) {
let [ok, speed, direction] = info.get_value_wind(GWeather.SpeedUnit.DEFAULT);
if (ok) {
- label.label = speed.toFixed(1).toString() + ' ' +
GWeather.speed_unit_to_string(GWeather.SpeedUnit.DEFAULT);
+ label.label = `${speed.toFixed(1).toString()}
${GWeather.speed_unit_to_string(GWeather.SpeedUnit.DEFAULT)}`;
} else {
/* Fall back to get_wind() */
label.label = info.get_wind();
@@ -237,26 +242,30 @@ var DailyForecastBox = GObject.registerClass(class DailyForecastBox extends Gtk.
}
clear() {
- this.foreach(function(w) { w.destroy(); });
+ for (const w of Array.from(this)) {
+ this.remove(w);
+ }
}
});
var DayEntry = GObject.registerClass({
Template: 'resource:///org/gnome/Weather/day-entry.ui',
InternalChildren: ['nameLabel', 'dateLabel', 'image',
- 'thermometer',
- 'nightTemperatureLabel', 'nightImage',
- 'nightHumidity', 'nightWind',
- 'morningTemperatureLabel', 'morningImage',
- 'morningHumidity', 'morningWind',
- 'afternoonTemperatureLabel', 'afternoonImage',
- 'afternoonHumidity', 'afternoonWind',
- 'eveningTemperatureLabel', 'eveningImage',
- 'eveningHumidity', 'eveningWind'],
-}, class DayEntry extends Gtk.Box {
+ 'thermometer',
+ 'nightTemperatureLabel', 'nightImage',
+ 'nightHumidity', 'nightWind',
+ 'morningTemperatureLabel', 'morningImage',
+ 'morningHumidity', 'morningWind',
+ 'afternoonTemperatureLabel', 'afternoonImage',
+ 'afternoonHumidity', 'afternoonWind',
+ 'eveningTemperatureLabel', 'eveningImage',
+ 'eveningHumidity', 'eveningWind'],
+}, class DayEntry extends Gtk.Widget {
_init(params) {
super._init(params);
+
+ this.layoutManager.orientation = Gtk.Orientation.VERTICAL;
}
get nameLabel() {
@@ -339,3 +348,6 @@ var DayEntry = GObject.registerClass({
return this._eveningWind;
}
});
+
+DayEntry.set_layout_manager_type(Gtk.BoxLayout);
+
\ No newline at end of file
diff --git a/src/app/entry.js b/src/app/entry.js
new file mode 100644
index 0000000..822c8f2
--- /dev/null
+++ b/src/app/entry.js
@@ -0,0 +1,396 @@
+const { Gio, GLib, GWeather, GObject, Gtk, Gdk } = imports.gi;
+
+const LocationItem = GObject.registerClass(
+ {
+ Properties: {
+ 'display-name': GObject.ParamSpec.string("display-name", "Display name", "",
GObject.ParamFlags.READWRITE, ''),
+ 'location': GObject.ParamSpec.boxed("location", "Display name", "",
GObject.ParamFlags.READWRITE, GWeather.Location.$gtype),
+ 'local-compare-name': GObject.ParamSpec.string("local-compare-name", "Local compare name", "",
GObject.ParamFlags.READWRITE, ''),
+ 'english-compare-name': GObject.ParamSpec.string("english-compare-name", "English compare name",
"", GObject.ParamFlags.READWRITE, ''),
+ }
+ },
+ class LocationItem extends GObject.Object { }
+);
+
+/**
+ * @param {string} displayName
+ * @param {import("@gi-types/gweather").Location} location
+ * @param {string} localCompareName
+ * @param {string} englishCompareName
+ */
+function buildLocationItem(displayName, location, localCompareName, englishCompareName) {
+ const item = new LocationItem();
+ item.displayName = displayName;
+ item.location = location;
+ item.localCompareName = localCompareName;
+ item.englishCompareName = englishCompareName;
+ return item;
+}
+
+GWeather.Location.prototype[Symbol.iterator] = function* () {
+ let child = this.next_child(null);
+
+ while (child != null) {
+ yield child;
+ child = this.next_child(child);
+ }
+}
+
+/** @typedef {Gio.ListModel} ListModel */
+
+const LocationListModel = GObject.registerClass(
+ {
+ Implements: [Gio.ListModel]
+ },
+ class LocationListModel extends Gtk.Widget {
+
+
+ _init() {
+ super._init();
+
+ this._top = GWeather.Location.get_world();
+ this._show_named_timezones = false;
+
+ this._list = [];
+ }
+
+ // TODO
+ // Adapted from libgweather
+
+ /**
+ * @param {import("@gi-types/gweather").Location} loc
+ * @param {string | null} parent_display_name
+ * @param {string | null} parent_compare_local_name
+ * @param {string | null} parent_compare_english_name
+ * @param {boolean} show_named_timezones
+ */
+ _fill_location_list_model(
+ loc,
+ parent_display_name,
+ parent_compare_local_name,
+ parent_compare_english_name,
+ show_named_timezones
+ ) {
+ let children = [...loc];
+ /** @type {string | null} */
+ let display_name;
+ /** @type {string | null} */
+ let local_compare_name;
+ /** @type {string | null} */
+ let english_compare_name;
+
+ switch (loc.get_level()) {
+ case GWeather.LocationLevel.WORLD:
+ case GWeather.LocationLevel.REGION:
+ /* Ignore these levels of hierarchy; just recurse, passing on
+ * the names from the parent node.
+ */
+ children.forEach(child => {
+ this._fill_location_list_model(child,
+ parent_display_name,
+ parent_compare_local_name,
+ parent_compare_english_name,
+ show_named_timezones);
+ });
+ break;
+
+ case GWeather.LocationLevel.COUNTRY:
+ /* Recurse, initializing the names to the country name */
+ children.forEach(child => {
+ this._fill_location_list_model(child,
+ loc.get_name(),
+ loc.get_sort_name(),
+ loc.get_english_name(),
+ show_named_timezones);
+ });
+ break;
+
+ case GWeather.LocationLevel.ADM1:
+ /* Recurse, adding the ADM1 name to the country name */
+ /* Translators: this is the name of a location followed by a region, for example:
+ * 'London, United Kingdom'
+ * You shouldn't need to translate this string unless the language has a different comma.
+ */
+ display_name = _("%s, %s").format(loc.get_name(), parent_display_name);
+ local_compare_name = _("%s, %s").format(loc.get_sort_name(), parent_compare_local_name);
+ english_compare_name = _("%s, %s").format(loc.get_english_name(),
parent_compare_english_name);
+
+ children.forEach(child => {
+ this._fill_location_list_model(child,
+ display_name, local_compare_name, english_compare_name,
+ show_named_timezones);
+ });
+
+ break;
+
+ case GWeather.LocationLevel.CITY:
+ /* If there are multiple (<location>) children, we use the one
+ * closest to the city center.
+ *
+ * Locations are already sorted by increasing distance from
+ * the city.
+ */
+ case GWeather.LocationLevel.WEATHER_STATION:
+ /* <location> with no parent <city> */
+ /* Translators: this is the name of a location followed by a region, for example:
+ * 'London, United Kingdom'
+ * You shouldn't need to translate this string unless the language has a different comma.
+ */
+ display_name = _("%s, %s").format(
+ loc.get_name(), parent_display_name);
+ local_compare_name = _("%s, %s").format(
+ loc.get_sort_name(), parent_compare_local_name);
+ english_compare_name = _("%s, %s").format(
+ loc.get_english_name(), parent_compare_english_name);
+
+ this._list.push(buildLocationItem(display_name, loc, local_compare_name,
english_compare_name));
+ break;
+ case GWeather.LocationLevel.NAMED_TIMEZONE:
+ if (show_named_timezones) {
+ this._list.push(buildLocationItem(loc.get_name(), loc, loc.get_sort_name(),
loc.get_english_sort_name()));
+ }
+ break;
+
+ case GWeather.LocationLevel.DETACHED:
+ throw new Error('No detached locations!');
+ }
+ }
+
+ /**
+ * @this {ListModel & this}
+ */
+ fill() {
+ if (!this._top) {
+ throw new Error('Failed to load location data');
+ }
+
+ this._fill_location_list_model(this._top, null, null, null, this._show_named_timezones);
+ this.items_changed(0, 0, this._list.length);
+ }
+
+ vfunc_get_item_type() {
+ return LocationItem.$gtype;
+ }
+
+ vfunc_get_n_items() {
+ return this._list.length;
+ }
+
+ /**
+ * @param {number} n
+ */
+ vfunc_get_item(n) {
+ return this._list[n] ?? null;
+ }
+ }
+);
+LocationListModel.set_layout_manager_type(Gtk.BinLayout);
+LocationListModel.set_css_name('entry');
+
+var LocationSearchEntry = GObject.registerClass(
+ {
+ Properties: {
+ 'location': GObject.ParamSpec.boxed("location", "location", "location",
GObject.ParamFlags.READWRITE, GWeather.Location.$gtype)
+ }
+ },
+ class LocationSearchEntry extends Gtk.Widget {
+
+ set location(loc) {
+ this._location = loc;
+ }
+
+ get location() {
+ return this._location;
+ }
+
+ /**
+ * @param {import("@gi-types/gtk").Orientation} orientation
+ * @param {number} for_size
+ */
+ vfunc_measure(orientation, for_size) {
+ return this._entry.measure(orientation, for_size);
+ }
+
+ /**
+ * @param {number} width
+ * @param {number} height
+ * @param {number} baseline
+ */
+ vfunc_size_allocate(width, height, baseline) {
+ this._entry.size_allocate(new Gdk.Rectangle({
+ x: 0,
+ y: 0,
+ width,
+ height
+ }), baseline);
+
+ if (this._popup) {
+ this._popup.set_size_request(this.get_allocation().width, -1);
+ this._popup.queue_resize();
+ this._popup.present();
+ }
+ }
+
+ vfunc_grab_focus() {
+ return this._entry.grab_focus();
+ }
+
+ /**
+ * @param {import("@gi-types/gtk").ListView} listview
+ */
+ set_list_view(listview) {
+ if (this._listview) {
+ this._listview.set_factory(null);
+ this._listview.set_model(null);
+ this._listview.unparent();
+ }
+
+ this._listview = listview;
+ const factory = this._build_factory();
+ listview.set_factory(factory);
+ const selection = this._build_model();
+ listview.set_model(selection);
+ }
+
+ onSearch(cb) {
+ this.cb = cb;
+ }
+
+ ensure_list_view() {
+ if (!this._listview) {
+ this._popup = new Gtk.Popover();
+ this._popup.set_parent(this);
+ this._popup.set_autohide(false);
+ this._popup.set_has_arrow(false);
+
+ this._listview = new Gtk.ListView();
+ const selection = this._build_model();
+ this._listview.set_model(selection);
+ const factory = this._build_factory();
+ this._listview.set_factory(factory);
+ this._sw = new Gtk.ScrolledWindow();
+ this._sw.set_child(this._listview);
+ this._sw.set_hexpand(true);
+ this._popup.set_child(this._sw);
+ return this._listview;
+ }
+
+ return this._listview;
+ }
+
+ _build_model() {
+ let filter = new Gtk.StringFilter();
+ this._filter = filter;
+ const expr = Gtk.ClosureExpression.new(GObject.TYPE_STRING, (self) => {
+ return self.displayName ?? "";
+ }, []);
+ filter.set_expression(expr);
+
+ let filter_model = new Gtk.FilterListModel({
+ model: this._model,
+ filter: this._filter
+ });
+ let selection = new Gtk.SingleSelection({
+ model: filter_model
+ });
+ selection.set_selected(GLib.MAXUINT32)
+ selection.set_autoselect(false);
+ selection.connect('notify::selected', (selection) => {
+ const item = selection.get_selected_item();
+
+ if (item instanceof LocationItem) {
+ this._set_location(item.location);
+
+ if (this._popup) {
+ this._popup.popdown();
+ }
+ }
+ });
+ return selection;
+ }
+
+ _build_factory() {
+ let factory = new Gtk.SignalListItemFactory();
+ this._setupId = factory.connect("setup", (source, item) => {
+ const label = new Gtk.Label();
+ item.set_child(label);
+ });
+ this._bindId = factory.connect("bind", (source, listitem) => {
+ const label = listitem.get_child();
+ /** @type {typeof LocationItem.prototype} */
+ const item = listitem.get_item();
+
+ if (label instanceof Gtk.Label) {
+ label.set_label(item.display_name);
+ }
+ });
+
+ return factory;
+ }
+
+ _init() {
+ super._init();
+ try {
+ this._model = new LocationListModel();
+ this._location = null;
+
+ // Widgets
+ this._entry = new Gtk.SearchEntry();
+
+ this._entry.set_parent(this);
+ this._entry.set_hexpand(true);
+ this._popup = null;
+
+
+ this._entry.connect("search-changed", (source) => {
+ this.ensure_list_view();
+
+ const text = source.get_text();
+
+ if (text === null || text === '') {
+ this.cb?.(null);
+ this._filter?.set_search(null);
+ if (this._popup && this._popup.visible) {
+ this._popup.visible = false;
+ }
+ return;
+ }
+ if (this._popup && !this._popup.visible) {
+ this._popup.visible = true;
+ this._entry?.grab_focus();
+ }
+
+ this._filter?.set_search(text);
+ this.cb?.(text);
+ });
+
+ try {
+ this._model.fill();
+ } catch (error) {
+ console.error(error);
+ }
+ } catch (e) {
+ logError(e);
+ }
+ }
+
+ _cleanup() {
+ if (this._listview instanceof Gtk.ListView) {
+ this._listview.set_model(null);
+ }
+ }
+
+ get_location() {
+ if (this._location)
+ return this._location;
+ else
+ return null;
+ }
+
+ _set_location(location) {
+ this._location = location;
+ this.notify('location');
+ }
+ }
+);
+
diff --git a/src/app/hourlyForecast.js b/src/app/hourlyForecast.js
index 543753a..6ac9294 100644
--- a/src/app/hourlyForecast.js
+++ b/src/app/hourlyForecast.js
@@ -22,6 +22,7 @@ const GObject = imports.gi.GObject;
const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;
const GWeather = imports.gi.GWeather;
+const Graphene = imports.gi.Graphene;
const Util = imports.misc.util;
@@ -29,16 +30,14 @@ const Util = imports.misc.util;
const TWENTY_FOUR_HOURS = 24 * 3600 * 1000 * 1000;
var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gtk.Box {
-
- _init(params) {
- super._init(Object.assign({
+ _init() {
+ super._init({
orientation: Gtk.Orientation.HORIZONTAL,
spacing: 0,
name: 'hourly-forecast-box',
- }, params));
-
- this.get_accessible().accessible_name = _('Hourly Forecast');
-
+ });
+
+ this.update_property([Gtk.AccessibleProperty.LABEL], [_('Hourly Forecast')]);
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
this._hourlyInfo = [];
@@ -94,7 +93,7 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
let label = new Gtk.Label({ label: _('Forecast not available'),
use_markup: true,
visible: true });
- this.pack_start(label, true, false, 0);
+ this.prepend(label);
}
this._hourlyInfo = hourlyInfo;
@@ -128,7 +127,7 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
hourEntry.temperatureLabel.set_markup(label);
};
- this.pack_start(hourEntry, false, false, 0);
+ this.prepend(hourEntry);
this._hasForecastInfo = true;
}
@@ -136,18 +135,26 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
_addSeparator() {
let separator = new Gtk.Separator({ orientation: Gtk.Orientation.VERTICAL,
visible: true});
- this.pack_start(separator, false, false, 0);
+ this.prepend(separator);
}
clear() {
- this.foreach(function(w) { w.destroy(); });
+ for (const w of Array.from(this)) {
+ this.remove(w);
+ }
}
hasForecastInfo() {
return this._hasForecastInfo;
}
- vfunc_draw(cr) {
+ vfunc_snapshot(snapshot) {
+ const allocation = this.get_allocation();
+
+ const rect = new Graphene.Rect();
+ rect.init(0, 0, allocation.width, allocation.height);
+
+ let cr = snapshot.append_cairo(rect);
const temps = this._hourlyInfo.map(info => Util.getTemp(info));
const maxTemp = Math.max(...temps);
@@ -209,7 +216,7 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
cr.lineTo(0, height);
cr.fill();
- super.vfunc_draw(cr);
+ super.vfunc_snapshot(snapshot);
cr.$dispose();
return Gdk.EVENT_PROPAGATE;
@@ -218,11 +225,12 @@ var HourlyForecastBox = GObject.registerClass(class HourlyForecastBox extends Gt
var HourEntry = GObject.registerClass({
Template: 'resource:///org/gnome/Weather/hour-entry.ui',
+
InternalChildren: ['timeLabel', 'image', 'temperatureLabel'],
-}, class HourEntry extends Gtk.Box {
+}, class HourEntry extends Gtk.Widget {
_init(params) {
- super._init(params);
+ super._init({...params});
}
get timeLabel() {
@@ -237,3 +245,4 @@ var HourEntry = GObject.registerClass({
return this._temperatureLabel;
}
});
+HourEntry.set_layout_manager_type(Gtk.BoxLayout);
\ No newline at end of file
diff --git a/src/app/main.js b/src/app/main.js
index 3b554ee..83a4363 100644
--- a/src/app/main.js
+++ b/src/app/main.js
@@ -20,15 +20,18 @@ pkg.initFormat();
pkg.initGettext();
window.ngettext = imports.gettext.ngettext;
-pkg.require({ 'Gdk': '3.0',
- 'Gio': '2.0',
- 'GLib': '2.0',
- 'GObject': '2.0',
- 'Gtk': '3.0',
- 'GWeather': '3.0' });
+pkg.require({
+ 'Gdk': '4.0',
+ 'Gio': '2.0',
+ 'GLib': '2.0',
+ 'GObject': '2.0',
+ 'Gtk': '4.0',
+ 'Adw': '1',
+ 'GWeather': '4.0'
+});
const ByteArray = imports.byteArray;
-const Handy = imports.gi.Handy;
+const Adw = imports.gi.Adw;
const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
@@ -36,11 +39,15 @@ const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
const GWeather = imports.gi.GWeather;
+// ensure the type before we call to GtkBuilder
+imports.app.entry;
+
const Util = imports.misc.util;
const Window = imports.app.window;
const World = imports.shared.world;
const CurrentLocationController = imports.app.currentLocationController;
+
const ShellIntegrationInterface = ByteArray.toString(
Gio.resources_lookup_data('/org/gnome/shell/ShellWeatherIntegration.xml', 0).get_data());
@@ -54,9 +61,10 @@ const Application = GObject.registerClass(
class WeatherApplication extends Gtk.Application {
_init() {
- super._init({ application_id: pkg.name,
- flags: (Gio.ApplicationFlags.CAN_OVERRIDE_APP_ID | Gio.ApplicationFlags.FLAGS_NONE)
});
-
+ super._init({
+ application_id: pkg.name,
+ flags: (Gio.ApplicationFlags.CAN_OVERRIDE_APP_ID | Gio.ApplicationFlags.FLAGS_NONE)
+ });
let name_prefix = '';
if (pkg.name.endsWith('Devel')) {
name_prefix = '(Development) ';
@@ -88,19 +96,19 @@ const Application = GObject.registerClass(
vfunc_startup() {
super.vfunc_startup();
- Handy.init();
- // ensure the type before we call to GtkBuilder
- GWeather.LocationEntry;
+ Adw.init();
Util.loadStyleSheet('/org/gnome/Weather/application.css');
- Handy.StyleManager
- .get_default()
- .set_color_scheme(Handy.ColorScheme.PREFER_LIGHT);
+ // TODO
+ // Handy.StyleManager
+ // .get_default()
+ // .set_color_scheme(Handy.ColorScheme.PREFER_LIGHT);
this.world = GWeather.Location.get_world();
this.model = new World.WorldModel(this.world, true);
this.currentLocationController = new CurrentLocationController.CurrentLocationController(this.model);
+
this.model.load();
@@ -172,9 +180,9 @@ const Application = GObject.registerClass(
});
this.add_action(temperatureAction);
- this.add_accelerator("Escape", "win.selection-mode", new GLib.Variant('b', false));
- this.add_accelerator("<Primary>a", "win.select-all", null);
- this.add_accelerator("<Primary>q", "app.quit", null);
+ this.set_accels_for_action("win.selection-mode", ["Escape"]);
+ this.set_accels_for_action("win.select-all", ["<Primary>a"]);
+ this.set_accels_for_action("app.quit", ["<Primary>q"]);
}
vfunc_dbus_register(conn, path) {
@@ -270,5 +278,13 @@ let ShellIntegration = class ShellIntegration {
function main(argv) {
initEnvironment();
- return (new Application()).run(argv);
+ const application = new Application();
+
+ application.connect("window-removed", (_, window) => {
+ if (window instanceof Window.MainWindow) {
+ window.run_dispose();
+ }
+ });
+
+ application.run(argv);
}
diff --git a/src/app/thermometer.js b/src/app/thermometer.js
index 8356ea4..b81a97f 100644
--- a/src/app/thermometer.js
+++ b/src/app/thermometer.js
@@ -23,6 +23,7 @@ const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;
const Pango = imports.gi.Pango;
const Cairo = imports.cairo;
+const Graphene = imports.gi.Graphene;
const Thermometer = GObject.registerClass({
Properties: {
@@ -35,28 +36,21 @@ const Thermometer = GObject.registerClass({
),
},
CssName: 'thermometer',
-},class Thermometer extends Gtk.DrawingArea {
+}, class Thermometer extends Gtk.Widget {
- _init(params) {
+ _init({ adjustment, ...params }) {
super._init(params);
- const styleContext = this.get_style_context();
-
- const createStyleContext = (selector) => {
- const path = styleContext.get_path().copy();
+ this._drawing = new Gtk.DrawingArea();
+ this._drawing.set_parent(this);
- const pos = path.append_type(GObject.TYPE_NONE);
- path.iter_set_object_name(pos, selector);
-
- const context = Gtk.StyleContext.new();
- context.set_parent(styleContext);
- context.set_path(path);
+ this._adjustment = adjustment;
+ if (adjustment) {
- return context;
}
-
- this._highStyleContext = createStyleContext('high');
- this._lowStyleContext = createStyleContext('low');
+ this._highLayout = null;
+ this._lowLayout = null;
+ this._updatePangoLayouts();
this._radius = 12;
this._margin = 12;
@@ -72,35 +66,51 @@ const Thermometer = GObject.registerClass({
this._updatePangoLayouts(adjustment);
}
- vfunc_get_preferred_width() {
+ // vfunc_get_preferred_width() {
+ // const [highWidth] = this._highLayout.get_pixel_size();
+ // const [lowWidth] = this._lowLayout.get_pixel_size();
+
+ // const width = Math.max(this._radius, highWidth, lowWidth);
+ // return [width, width];
+ // }
+
+ // vfunc_get_preferred_height() {
+ // const [, highHeight] = this._highLayout.get_pixel_size();
+ // const [, lowHeight] = this._lowLayout.get_pixel_size();
+
+ // const height = highHeight + this._margin + lowHeight;
+ // return [height, height];
+ // }
+
+ vfunc_measure(orientation, for_size) {
const [highWidth] = this._highLayout.get_pixel_size();
const [lowWidth] = this._lowLayout.get_pixel_size();
- const width = Math.max(this._radius, highWidth, lowWidth);
- return [width, width];
- }
-
- vfunc_get_preferred_height() {
const [, highHeight] = this._highLayout.get_pixel_size();
const [, lowHeight] = this._lowLayout.get_pixel_size();
- const height = highHeight + this._maring + lowHeight;
- return [height, height];
+ const allocatedHeight = highHeight + this._margin + this.radius + lowHeight;
+
+ return [allocatedHeight, allocatedHeight + 100];
}
_updatePangoLayouts(adjustment) {
+ if (!adjustment) return;
+
const value = adjustment.get_value();
const pageSize = adjustment.get_page_size();
const highLabel = Math.round(value + pageSize) + "°";
- this._highLayout = this._createPangoLayout(this._highStyleContext, highLabel);
+ this._highLayout = this._createPangoLayout(highLabel);
const lowLabel = Math.round(value) + "°";
- this._lowLayout = this._createPangoLayout(this._lowStyleContext, lowLabel);
+ this._lowLayout = this._createPangoLayout(lowLabel);
+
+ this.queue_draw();
}
- _createPangoLayout(styleContext, text) {
- const context = this._createPangoContext(styleContext);
+ _createPangoLayout(text) {
+ const context = this.get_pango_context();
const layout = Pango.Layout.new(context);
layout.set_text(text, -1);
@@ -108,17 +118,35 @@ const Thermometer = GObject.registerClass({
return layout;
}
- _createPangoContext(styleContext) {
- const display = this.get_display();
- const context = Gdk.pango_context_get_for_display(display);
+ vfunc_snapshot(snapshot) {
+ if (!this._adjustment) {
+ super.vfunc_snapshot(snapshot);
+
+ return Gdk.EVENT_PROPAGATE;
+ }
- const font = styleContext.get_property('font', styleContext.get_state());
- context.set_font_description (font);
+ const allocation = this._drawing.get_allocation();
- return context;
- }
+ const rect = new Graphene.Rect();
+ rect.init(0, 0, allocation.width, allocation.height);
+
+ const highColor = new Gdk.RGBA();
+ highColor.parse("#c89009");
+ const lowColor = new Gdk.RGBA();
+ lowColor.parse("#2174d9");
+
+ // snapshot.append_linear_gradient(rect, 0, allocation.height - 12, [
+ // new Gsk.ColorStop({ offset: 0, color: highColor }),
+ // new Gsk.ColorStop({ offset: allocation.height / 2, color: lowColor }),
+ // ])
+
+ // const border = new Gsk.RoundedRect();
+ // border.init_from_rect(rect, 12);
+ // snapshot.push_rounded_clip(border)
- vfunc_draw(cr) {
+
+
+ let cr = snapshot.append_cairo(rect);
const lower = this._adjustment.get_lower();
const upper = this._adjustment.get_upper();
const value = this._adjustment.get_value();
@@ -127,8 +155,8 @@ const Thermometer = GObject.registerClass({
const width = this.get_allocated_width();
const height = this.get_allocated_height();
- const [highWidth, highHeight] = this._highLayout.get_pixel_size();
- const [lowWidth, lowHeight] = this._lowLayout.get_pixel_size();
+ const [, highHeight] = this._highLayout.get_pixel_size();
+ const [, lowHeight] = this._lowLayout.get_pixel_size();
const radius = this._radius;
const margin = this._margin;
@@ -142,7 +170,6 @@ const Thermometer = GObject.registerClass({
let highY = 0;
let lowY = height - lowHeight;
- cr.save();
if (maxScaleHeight > 0) {
this._renderScale(cr, width / 2 - radius, scaleY, radius, scaleHeight);
@@ -151,17 +178,14 @@ const Thermometer = GObject.registerClass({
lowY = scaleY + scaleHeight + radius + margin;
}
- Gtk.render_layout(this._highStyleContext, cr,
- width / 2 - highWidth / 2, highY,
- this._highLayout);
+ snapshot.append_layout(this._highLayout, highColor);
+ snapshot.append_layout(this._lowLayout, lowColor);
- Gtk.render_layout(this._lowStyleContext, cr,
- width / 2 - lowWidth / 2, lowY,
- this._lowLayout);
+ super.vfunc_snapshot(snapshot);
- cr.restore();
+ cr.$dispose();
- return false;
+ return Gdk.EVENT_PROPAGATE;
}
_renderScale(cr, x, y, radius, height) {
@@ -180,13 +204,16 @@ const Thermometer = GObject.registerClass({
const styleContext = this.get_style_context();
- const [, warmColor] = styleContext.lookup_color('thermometer_warm_color');
- pattern.addColorStopRGB(0.0, warmColor.red, warmColor.green, warmColor.blue);
- const [, coldColor] = styleContext.lookup_color('thermometer_cold_color');
- pattern.addColorStopRGB(1.0, coldColor.red, coldColor.green, coldColor.blue);
+ //const [, warmColor] = styleContext.lookup_color('thermometer_warm_color');
+ pattern.addColorStopRGB(0.0, 100, 0, 0);
+
+ //const [, coldColor] = styleContext.lookup_color('thermometer_cold_color');
+ pattern.addColorStopRGB(1.0, 0, 0, 100);
return pattern;
}
});
+
+Thermometer.set_layout_manager_type(Gtk.BoxLayout);
diff --git a/src/app/window.js b/src/app/window.js
index 22d0894..111899e 100644
--- a/src/app/window.js
+++ b/src/app/window.js
@@ -16,7 +16,7 @@
// with Gnome Weather; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-const Handy = imports.gi.Handy;
+const Adw = imports.gi.Adw;
const Gio = imports.gi.Gio;
const GObject = imports.gi.GObject;
const Gtk = imports.gi.Gtk;
@@ -36,16 +36,15 @@ const Page = {
var MainWindow = GObject.registerClass({
Template: 'resource:///org/gnome/Weather/window.ui',
InternalChildren: ['header', 'refreshRevealer', 'refresh', 'forecastStackSwitcher', 'stack',
- 'titleStack', 'searchView', 'searchEntry', 'forecastStackSwitcherBar']
-}, class MainWindow extends Handy.ApplicationWindow {
-
+ 'titleStack','searchEntry', 'searchView', 'forecastStackSwitcherBar']
+}, class MainWindow extends Adw.ApplicationWindow {
_init(params) {
super._init(params);
this._world = this.application.world;
this.currentInfo = null;
this._currentPage = Page.SEARCH;
- this._pageWidgets = [[],[]];
+ this._pageWidgets = [[], []];
let aboutAction = new Gio.SimpleAction({
enabled: true,
@@ -79,7 +78,7 @@ var MainWindow = GObject.registerClass({
this._pageWidgets[Page.CITY].push(this._refresh);
this._cityView = new City.WeatherView(this.application, this,
- { hexpand: true, vexpand: true });
+ { hexpand: true, vexpand: true });
this._stack.add_named(this._cityView, 'city');
this._forecastStackSwitcher.set_stack(this._cityView.getInfoPage().getForecastStack());
@@ -97,7 +96,12 @@ var MainWindow = GObject.registerClass({
}
this._showingDefault = false;
- this.show_all();
+ // this.show_all();
+ }
+
+ on_destroy() {
+ this._cityView._cleanup();
+ this._searchEntry._cleanup();
}
update() {
@@ -116,9 +120,7 @@ var MainWindow = GObject.registerClass({
this._pageWidgets[this._currentPage][i].hide();
for (let i = 0; i < this._pageWidgets[page].length; i++) {
- let widget = this._pageWidgets[page][i];
- if (!widget.no_show_all)
- this._pageWidgets[page][i].show();
+ this._pageWidgets[page][i].show();
}
this._currentPage = page;
@@ -164,8 +166,9 @@ var MainWindow = GObject.registerClass({
if (!this._cityView.info._isCurrentLocation)
return;
} else if (this._currentPage == Page.SEARCH) {
- if (this._searchEntry.text.length > 0)
- return;
+ // TODO
+ // if (this._searchEntry.text.length > 0)
+ // return;
}
}
@@ -179,14 +182,14 @@ var MainWindow = GObject.registerClass({
}
_showAbout() {
- let artists = [ 'Jakub Steiner <jimmac gmail com>',
- 'Pink Sherbet Photography (D. Sharon Pruitt)',
- 'Elliott Brown',
- 'Analogick',
- 'DBduo Photography (Daniel R. Blume)',
- 'davharuk',
- 'Tech Haven Ministries',
- 'Jim Pennucci' ];
+ let artists = ['Jakub Steiner <jimmac gmail com>',
+ 'Pink Sherbet Photography (D. Sharon Pruitt)',
+ 'Elliott Brown',
+ 'Analogick',
+ 'DBduo Photography (Daniel R. Blume)',
+ 'davharuk',
+ 'Tech Haven Ministries',
+ 'Jim Pennucci'];
let name_prefix = '';
if (pkg.name.endsWith('Devel')) {
@@ -197,19 +200,19 @@ var MainWindow = GObject.registerClass({
let attribution = this._cityView.info ? this._cityView.info.get_attribution() : '';
copyright += attribution ? '\n' + attribution : '';
let aboutDialog = new Gtk.AboutDialog(
- { artists: artists,
- authors: [ 'Giovanni Campagna <gcampagna src gnome org>' ],
- translator_credits: _("translator-credits"),
- program_name: name_prefix + _("Weather"),
- comments: _("A weather application"),
- license_type: Gtk.License.GPL_2_0,
- logo_icon_name: pkg.name,
- version: pkg.version,
- website: 'https://wiki.gnome.org/Apps/Weather',
- wrap_license: true,
- modal: true,
- transient_for: this,
- use_header_bar: true
+ {
+ artists: artists,
+ authors: ['Giovanni Campagna <gcampagna src gnome org>'],
+ translator_credits: _("translator-credits"),
+ program_name: name_prefix + _("Weather"),
+ comments: _("A weather application"),
+ license_type: Gtk.License.GPL_2_0,
+ logo_icon_name: pkg.name,
+ version: pkg.version,
+ website: 'https://wiki.gnome.org/Apps/Weather',
+ wrap_license: true,
+ modal: true,
+ transient_for: this
});
// HACK: we need to poke into gtkaboutdialog internals
@@ -221,9 +224,6 @@ var MainWindow = GObject.registerClass({
copyrightLabel.show();
aboutDialog.show();
- aboutDialog.connect('response', function() {
- aboutDialog.destroy();
- });
}
_close() {
diff --git a/src/app/world.js b/src/app/world.js
index 1815629..11d293d 100644
--- a/src/app/world.js
+++ b/src/app/world.js
@@ -26,22 +26,28 @@ const CurrentLocationController = imports.app.currentLocationController;
const Util = imports.misc.util;
-var WorldContentView = GObject.registerClass(
- class WorldContentView extends Gtk.Popover {
- _init(application, window, params) {
- super._init(Object.assign({
- hexpand: false,
- vexpand: false
- }, params));
+class _WorldContentView extends Gtk.Popover {
+ static [GObject.TypeName] = 'WorldContentView';
- this.get_accessible().accessible_name = _("World view");
+ _init(application, window, params = {}) {
+ super._init({
+ hexpand: false,
+ vexpand: false,
+ ...params,
+ });
+ this.update_property([Gtk.AccessibleProperty.LABEL], [_("World view")]);
let builder = new Gtk.Builder();
builder.add_from_resource('/org/gnome/Weather/places-popover.ui');
let grid = builder.get_object('popover-grid');
- this.add(grid);
+ this.set_child(grid);
+
+ this._searchResults = builder.get_object('city-search-results');
+ this._searchGrid = builder.get_object('empty-search-grid');
+ this._searchResultsGrid = builder.get_object('search-grid');
+ this._locationsGrid = builder.get_object('locations-grid');
this.model = application.model;
this._window = window;
@@ -58,18 +64,27 @@ var WorldContentView = GObject.registerClass(
}
});
- let locationEntry = builder.get_object('location-entry');
- locationEntry.connect('notify::location', (entry) => this._locationChanged(entry));
+ this._locationEntry = builder.get_object('location-entry');
+ this._locationEntry.set_list_view(this._searchResults);
+ // TODO: Signal-ify this
+ this._locationEntry.onSearch((term) => {
+ if (term) {
+ this._stackPopover.set_visible_child(this._searchResultsGrid);
+ } else {
+ this._syncStackPopover();
+ }
+ })
+ this._locationEntry.connect('notify::location', (entry) => this._locationChanged(entry));
this.connect('show', () => {
- locationEntry.grab_focus();
+ this._locationEntry.grab_focus();
});
let autoLocStack = builder.get_object('auto-location-stack');
let autoLocSwitch = builder.get_object('auto-location-switch');
this._currentLocationController = application.currentLocationController;
- if(this._currentLocationController.autoLocation == CurrentLocationController.AutoLocation.ENABLED) {
+ if (this._currentLocationController.autoLocation == CurrentLocationController.AutoLocation.ENABLED) {
autoLocStack.visible_child_name = 'locating-label';
} else {
autoLocStack.visible_child_name = 'auto-location-switch-grid';
@@ -119,15 +134,21 @@ var WorldContentView = GObject.registerClass(
this._onLocationAdded(this.model, list[i], list[i]._isCurrentLocation);
}
+ _cleanup() {
+ this._locationEntry._cleanup();
+
+ this._listbox.set_header_func(null);
+ }
+
refilter() {
this._listbox.invalidate_filter();
}
_syncStackPopover() {
if (this.model.length == 1)
- this._stackPopover.set_visible_child_name("search-grid");
+ this._stackPopover.set_visible_child(this._searchGrid);
else
- this._stackPopover.set_visible_child_name("locations-grid");
+ this._stackPopover.set_visible_child(this._locationsGrid);
}
_filterListbox(row) {
@@ -147,55 +168,71 @@ var WorldContentView = GObject.registerClass(
_onLocationAdded(model, info, isCurrentLocation) {
let location = info.location;
- let grid = new Gtk.Grid({ orientation: Gtk.Orientation.HORIZONTAL,
- column_spacing: 12,
- margin: 12,
- visible: true });
+ let grid = new Gtk.Grid({
+ orientation: Gtk.Orientation.HORIZONTAL,
+ column_spacing: 12,
+ margin_start: 12,
+ margin_end: 12,
+ margin_top: 12,
+ margin_bottom: 12,
+ visible: true
+ });
let name = location.get_city_name();
- let locationGrid = new Gtk.Grid({ orientation: Gtk.Orientation.HORIZONTAL,
- column_spacing: 12,
- halign: Gtk.Align.START,
- hexpand: true,
- visible: true });
- let locationLabel = new Gtk.Label({ label: name,
- use_markup: true,
- halign: Gtk.Align.START,
- visible: true });
+ let locationGrid = new Gtk.Grid({
+ orientation: Gtk.Orientation.HORIZONTAL,
+ column_spacing: 12,
+ halign: Gtk.Align.START,
+ hexpand: true,
+ visible: true
+ });
+ let locationLabel = new Gtk.Label({
+ label: name,
+ use_markup: true,
+ halign: Gtk.Align.START,
+ visible: true
+ });
locationGrid.attach(locationLabel, 0, 0, 1, 1);
grid.attach(locationGrid, 0, 0, 1, 1);
- let tempLabel = new Gtk.Label({ use_markup: true,
- halign: Gtk.Align.END,
- margin_start: 12,
- visible: true });
+ let tempLabel = new Gtk.Label({
+ use_markup: true,
+ halign: Gtk.Align.END,
+ margin_start: 12,
+ visible: true
+ });
grid.attach(tempLabel, 1, 0, 1, 1);
if (isCurrentLocation) {
- let image = new Gtk.Image({ icon_size: Gtk.IconSize.LARGE_TOOLBAR,
- icon_name: 'mark-location-symbolic',
- use_fallback: true,
- halign: Gtk.Align.START,
- visible: true });
+ let image = new Gtk.Image({
+ icon_size: Gtk.IconSize.LARGE,
+ icon_name: 'mark-location-symbolic',
+ use_fallback: true,
+ halign: Gtk.Align.START
+ });
locationGrid.attach(image, 1, 0, 1, 1);
}
- let image = new Gtk.Image({ icon_size: Gtk.IconSize.LARGE_TOOLBAR,
- use_fallback: true,
- halign: Gtk.Align.END,
- visible: true });
+ let image = new Gtk.Image({
+ icon_size: Gtk.IconSize.LARGE,
+ use_fallback: true,
+ halign: Gtk.Align.END
+ });
grid.attach(image, 2, 0, 1, 1);
let row = new Gtk.ListBoxRow({ visible: true });
- row.add(grid);
+ row.set_child(grid);
row._info = info;
row._isCurrentLocation = isCurrentLocation;
if (isCurrentLocation) {
if (this._currentLocationAdded) {
let row0 = this._listbox.get_row_at_index(0);
- if (row0)
- row0.destroy();
+ if (row0) {
+ // TODO: GTK4
+ delete row0._info;
+ this._listbox.remove(row0);
+ }
}
this._currentLocationAdded = true;
@@ -220,14 +257,10 @@ var WorldContentView = GObject.registerClass(
}
_onLocationRemoved(model, info) {
- let rows = this._listbox.get_children();
-
- for (let row of rows) {
- if (row._info == info) {
- row.destroy();
- break;
- }
- }
+ Array.from(this._listbox).forEach((row) => {
+ delete row._info;
+ this._listbox.remove(row);
+ });
if (info._updatedId) {
info.disconnect(info._updatedId);
@@ -238,4 +271,6 @@ var WorldContentView = GObject.registerClass(
this._syncStackPopover();
}
-});
+};
+
+var WorldContentView = GObject.registerClass(_WorldContentView);
diff --git a/src/misc/util.js b/src/misc/util.js
index bd00d83..e3ffadc 100644
--- a/src/misc/util.js
+++ b/src/misc/util.js
@@ -28,7 +28,7 @@ const Gdk = imports.gi.Gdk;
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
-const Handy = imports.gi.Handy;
+const Adw = imports.gi.Adw;
const System = imports.system;
const GWeather = imports.gi.GWeather;
@@ -47,7 +47,7 @@ function loadUI(resourcePath, objects) {
function loadStyleSheet(resource) {
let provider = new Gtk.CssProvider();
provider.load_from_file(Gio.File.new_for_uri('resource://' + resource));
- Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
+ Gtk.StyleContext.add_provider_for_display(Gdk.Display.get_default(),
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
}
@@ -89,14 +89,6 @@ function getSettings(schemaId, path) {
path: path });
}
-function loadIcon(iconName, size) {
- let theme = Gtk.IconTheme.get_default();
-
- return theme.load_icon(iconName,
- size,
- Gtk.IconLookupFlags.GENERIC_FALLBACK);
-}
-
function getWeatherConditions(info) {
let conditions = info.get_conditions();
if (conditions == '-') // Not significant
@@ -211,5 +203,5 @@ function getTempString(info) {
}
function isDarkTheme() {
- return Handy.StyleManager.get_default().dark;
+ return Adw.StyleManager.get_default().dark;
}
diff --git a/src/org.gnome.Weather.src.gresource.xml.in b/src/org.gnome.Weather.src.gresource.xml.in
index 9613401..220a28b 100644
--- a/src/org.gnome.Weather.src.gresource.xml.in
+++ b/src/org.gnome.Weather.src.gresource.xml.in
@@ -6,6 +6,7 @@
<file>app/hourlyForecast.js</file>
<file>app/thermometer.js</file>
<file>app/dailyForecast.js</file>
+ <file>app/entry.js</file>
<file>app/main.js</file>
<file>app/window.js</file>
<file>app/world.js</file>
diff --git a/src/service/main.js b/src/service/main.js
index 113bf93..b28e3d3 100644
--- a/src/service/main.js
+++ b/src/service/main.js
@@ -21,7 +21,7 @@ pkg.initFormat();
pkg.require({ 'Gio': '2.0',
'GLib': '2.0',
'GObject': '2.0',
- 'GWeather': '3.0' });
+ 'GWeather': '4.0' });
const Gio = imports.gi.Gio;
const GLib = imports.gi.GLib;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]