[gnome-weather/wip/ewlsh/gtk4] Initial implementation of location entry.
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-weather/wip/ewlsh/gtk4] Initial implementation of location entry.
- Date: Tue, 5 Jan 2021 21:37:49 +0000 (UTC)
commit 077628da3ef6de860e4fb4657e462b3dd57efbd1
Author: Evan Welsh <contact evanwelsh com>
Date: Tue Jan 5 13:37:43 2021 -0800
Initial implementation of location entry.
data/day-entry.ui | 101 +++++---
data/hour-entry.ui | 8 -
data/places-popover.ui | 29 ++-
data/weather-widget.ui | 2 +-
data/window.ui | 9 +-
src/app/city.js | 8 +
src/app/entry.js | 394 +++++++++++++++++++++++++++++
src/app/main.js | 38 ++-
src/app/window.js | 10 +-
src/app/world.js | 25 +-
src/org.gnome.Weather.src.gresource.xml.in | 1 +
11 files changed, 543 insertions(+), 82 deletions(-)
---
diff --git a/data/day-entry.ui b/data/day-entry.ui
index e1ab7cf..393c488 100644
--- a/data/day-entry.ui
+++ b/data/day-entry.ui
@@ -247,53 +247,72 @@
<template class="Gjs_DayEntry" parent="GtkBox">
<property name="width_request">100</property>
<property name="height_request">200</property>
- <property name="hexpand">1</property>
- <property name="vexpand">1</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="margin_top">18</property>
+ <property name="margin_bottom">18</property>
<property name="orientation">vertical</property>
<property name="spacing">18</property>
<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="valign">start</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="maxTemperatureLabel">
- <property name="margin_top">8</property>
- <property name="label">18°</property>
- </object>
- </child>
- <child>
- <object class="GtkLabel" id="minTemperatureLabel">
- <property name="margin_top">8</property>
- <property name="label">9°</property>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="nameLabel">
+ <property name="label">Tues</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="dateLabel">
+ <property name="label">7 June</property>
+ <style>
+ <class name="small-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="valign">start</property>
+ <property name="vexpand">1</property>
+ <property name="pixel_size">32</property>
+ <property name="icon_name">weather-showers-symbolic</property>
+ </object>
+ </child>
</object>
</child>
<child>
- <object class="GtkMenuButton">
- <property name="halign">center</property>
- <property name="icon_name">view-more-symbolic</property>
- <property name="valign">center</property>
- <property name="popover">more_menu</property>
- <style>
- <class name="image-button"/>
- <class name="circular"/>
- <class name="flat"/>
- </style>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="maxTemperatureLabel">
+ <property name="label">18°</property>
+ <style>
+ <class name="forecast-temperature-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="minTemperatureLabel">
+ <property name="label">9°</property>
+ <style>
+ <class name="forecast-low-temperature-label"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuButton">
+ <property name="halign">center</property>
+ <property name="icon_name">view-more-symbolic</property>
+ <property name="valign">center</property>
+ <property name="popover">more_menu</property>
+ <style>
+ <class name="image-button"/>
+ <class name="circular"/>
+ <class name="flat"/>
+ </style>
+ </object>
+ </child>
</object>
</child>
</template>
diff --git a/data/hour-entry.ui b/data/hour-entry.ui
index 0c27049..436c336 100644
--- a/data/hour-entry.ui
+++ b/data/hour-entry.ui
@@ -5,8 +5,6 @@
<template class="Gjs_HourEntry" parent="GtkBox">
<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>
@@ -15,15 +13,11 @@
<property name="margin_bottom">18</property>
<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="pixel_size">32</property>
@@ -32,8 +26,6 @@
</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="label">13°</property>
<style>
diff --git a/data/places-popover.ui b/data/places-popover.ui
index ed5adfb..d07db18 100644
--- a/data/places-popover.ui
+++ b/data/places-popover.ui
@@ -9,11 +9,8 @@
<property name="margin-top">12</property>
<property name="margin-bottom">12</property>
<child>
- <object class="GtkEntry" id="location-entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
+ <object class="Gjs_LocationSearchEntry" id="location-entry">
<property name="width-request">300</property>
- <property name="activates_default">True</property>
<layout>
<property name="column">0</property>
<property name="row">0</property>
@@ -88,7 +85,7 @@
<property name="vhomogeneous">0</property>
<property name="hhomogeneous">0</property>
<child>
- <object class="GtkGrid" id="search-grid">
+ <object class="GtkGrid" id="empty-search-grid">
<property name="name">search-city-grid</property>
<property name="orientation">vertical</property>
<property name="margin_top">25</property>
@@ -126,6 +123,28 @@
</child>
</object>
</child>
+ <child>
+ <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>
+ </child>
<child>
<object class="GtkGrid" id="locations-grid">
<property name="name">locations-grid</property>
diff --git a/data/weather-widget.ui b/data/weather-widget.ui
index 69a79ff..88d3db5 100644
--- a/data/weather-widget.ui
+++ b/data/weather-widget.ui
@@ -181,7 +181,7 @@
<child>
<object class="GtkLabel" id="attributionLabel">
<property name="name">attribution-label</property>
- <property name="use_markup">1</property>
+ <property name="use_markup">True</property>
<property name="wrap">1</property>
<property name="xalign">0</property>
<layout>
diff --git a/data/window.ui b/data/window.ui
index cb72882..6494fed 100644
--- a/data/window.ui
+++ b/data/window.ui
@@ -5,8 +5,6 @@
<property name="orientation">vertical</property>
<child>
<object class="HdyHeaderBar" id="header-bar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
<property name="vexpand">False</property>
<property name="centering_policy">strict</property>
<child>
@@ -21,7 +19,6 @@
</child>
<child type="title">
<object class="HdyViewSwitcherTitle" id="switcher-title">
- <property name="visible">True</property>
<property name="title" translatable="yes">Weather</property>
</object>
</child>
@@ -89,10 +86,7 @@
</object>
</child>
<child>
- <object class="GtkEntry" id="initial-grid-location-entry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="activates_default">True</property>
+ <object class="Gjs_LocationSearchEntry" id="initial-grid-location-entry">
<layout>
<property name="column">0</property>
<property name="row">3</property>
@@ -111,7 +105,6 @@
</child>
<child>
<object class="HdyViewSwitcherBar" id="switcher-bar">
- <property name="visible">True</property>
<property name="reveal" bind-source="switcher-title" bind-property="title-visible"
bind-flags="sync-create"/>
</object>
</child>
diff --git a/src/app/city.js b/src/app/city.js
index d15dcc7..676ec39 100644
--- a/src/app/city.js
+++ b/src/app/city.js
@@ -116,6 +116,10 @@ var WeatherWidget = GObject.registerClass({
this.connect('destroy', () => this._onDestroy());
}
+ _cleanup() {
+ this._worldView._cleanup();
+ }
+
_onDestroy() {
if (this._updatedTimeTimeoutId) {
GLib.Source.remove(this._updatedTimeTimeoutId);
@@ -291,6 +295,10 @@ var WeatherView = GObject.registerClass({
this._desktopSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
}
+ _cleanup() {
+ this._infoPage._cleanup();
+ }
+
get info() {
return this._info;
}
diff --git a/src/app/entry.js b/src/app/entry.js
new file mode 100644
index 0000000..c6a45ac
--- /dev/null
+++ b/src/app/entry.js
@@ -0,0 +1,394 @@
+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;
+}
+
+/** @typedef {import("@gi-types/gio").ListModel} ListModel */
+
+const LocationListModel = GObject.registerClass(
+ {
+ Implements: [Gio.ListModel]
+ },
+ class LocationListModel extends GObject.Object {
+ /** @type {Array<typeof LocationItem.prototype>} */
+ _list = [];
+ _show_named_timezones = false;
+
+ /**
+ * @param {*} klass
+ */
+ _initClass(klass) {
+ const lm = new Gtk.BinLayout();
+ klass.set_layout_manager(lm);
+ klass.set_css_name('entry');
+ }
+
+ _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.get_children();
+ /** @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;
+ }
+ }
+);
+
+var LocationSearchEntry = GObject.registerClass(
+ {
+ Properties: {
+ 'location': GObject.ParamSpec.boxed("location", "location", "location",
GObject.ParamFlags.READWRITE, GWeather.Location.$gtype)
+ }
+ },
+ class LocationSearchEntry extends Gtk.Widget {
+ constructor() {
+ super();
+
+ /** @type {import("@gi-types/gtk").SearchEntry} */
+ this._entry;
+ }
+
+ 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, position) => {
+ const model = selection.get_model();
+ const item = model.get_item(position);
+ 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();
+
+ 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._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);
+ });
+
+ this._model.fill();
+ }
+
+ _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/main.js b/src/app/main.js
index da03caf..83c23ba 100644
--- a/src/app/main.js
+++ b/src/app/main.js
@@ -20,13 +20,15 @@ pkg.initFormat();
pkg.initGettext();
window.ngettext = imports.gettext.ngettext;
-pkg.require({ 'Gdk': '4.0',
- 'Gio': '2.0',
- 'GLib': '2.0',
- 'GObject': '2.0',
- 'Gtk': '4.0',
- 'Handy': '4',
- 'GWeather': '4.0' });
+pkg.require({
+ 'Gdk': '4.0',
+ 'Gio': '2.0',
+ 'GLib': '2.0',
+ 'GObject': '2.0',
+ 'Gtk': '4.0',
+ 'Handy': '4',
+ 'GWeather': '4.0'
+});
const ByteArray = imports.byteArray;
const Handy = imports.gi.Handy;
@@ -42,6 +44,9 @@ const Window = imports.app.window;
const World = imports.shared.world;
const CurrentLocationController = imports.app.currentLocationController;
+// ensure the type before we call to GtkBuilder
+imports.app.entry;
+
const ShellIntegrationInterface = ByteArray.toString(
Gio.resources_lookup_data('/org/gnome/shell/ShellWeatherIntegration.xml', 0).get_data());
@@ -55,9 +60,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) ';
@@ -90,8 +96,6 @@ const Application = GObject.registerClass(
vfunc_startup() {
super.vfunc_startup();
Handy.init();
- // ensure the type before we call to GtkBuilder
- Gtk.Entry;
Util.loadStyleSheet('/org/gnome/Weather/application.css');
@@ -266,5 +270,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._cleanup();
+ }
+ });
+
+ application.run(argv);
}
diff --git a/src/app/window.js b/src/app/window.js
index a33cb4b..8ab2826 100644
--- a/src/app/window.js
+++ b/src/app/window.js
@@ -122,6 +122,11 @@ var MainWindow = GObject.registerClass(
this._showingDefault = false;
}
+ _cleanup() {
+ this._cityView._cleanup();
+ this._searchEntry._cleanup();
+ }
+
update() {
this._cityView.update();
}
@@ -191,8 +196,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;
}
}
diff --git a/src/app/world.js b/src/app/world.js
index 216a69a..7da0b43 100644
--- a/src/app/world.js
+++ b/src/app/world.js
@@ -42,7 +42,9 @@ var WorldContentView = GObject.registerClass(
let grid = builder.get_object('popover-grid');
this.set_child(grid);
- this._searchGrid = builder.get_object('search-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;
@@ -60,11 +62,20 @@ 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');
@@ -121,6 +132,12 @@ 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();
}
diff --git a/src/org.gnome.Weather.src.gresource.xml.in b/src/org.gnome.Weather.src.gresource.xml.in
index 17b7432..7d547c7 100644
--- a/src/org.gnome.Weather.src.gresource.xml.in
+++ b/src/org.gnome.Weather.src.gresource.xml.in
@@ -5,6 +5,7 @@
<file>app/currentLocationController.js</file>
<file>app/hourlyForecast.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>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]