[gnome-weather/wip/ewlsh/gtk4] Start work on model updates, selection changes
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-weather/wip/ewlsh/gtk4] Start work on model updates, selection changes
- Date: Sun, 6 Feb 2022 03:07:36 +0000 (UTC)
commit b9ee873368df03323439beb0498c5638788f1d34
Author: Evan Welsh <contact evanwelsh com>
Date: Sat Feb 5 19:07:31 2022 -0800
Start work on model updates, selection changes
data/application.css | 29 +++-
data/org.gnome.Weather.gschema.xml | 8 -
data/places-popover.ui | 78 ++-------
src/app/city.js | 3 +-
src/app/currentLocationController.js | 35 +---
src/app/entry.js | 36 ++--
src/app/locationRow.js | 40 +++++
src/app/locationRow.ui | 40 +++++
src/app/shell.js | 7 +-
src/app/window.js | 51 ++----
src/app/world.js | 254 ++++++++---------------------
src/org.gnome.Weather.src.gresource.xml.in | 2 +
src/shared/world.js | 122 ++++++++------
tests/testutil.py | 3 -
14 files changed, 304 insertions(+), 404 deletions(-)
---
diff --git a/data/application.css b/data/application.css
index 5403e46..a2b63f7 100644
--- a/data/application.css
+++ b/data/application.css
@@ -40,8 +40,33 @@
font-weight: bold;
}
-#locations-list-box {
- border: 1px solid @borders;
+#locationEntry {
+ margin: 10px;
+}
+
+WeatherLocationRow {
+ padding: 10px;
+}
+
+WeatherLocationRow #label {
+ margin-bottom: 10px;
+ font-size: 11pt;
+}
+
+WeatherLocationRow #countryLabel {
+ font-size: 9pt;
+}
+
+.weather-popover contents {
+ padding: 0;
+}
+
+#currentIcon {
+ padding: 10px;
+}
+
+#locationIcon {
+ padding: 10px;
}
.forecast-frame {
diff --git a/data/org.gnome.Weather.gschema.xml b/data/org.gnome.Weather.gschema.xml
index f3c98f7..17b7d2d 100644
--- a/data/org.gnome.Weather.gschema.xml
+++ b/data/org.gnome.Weather.gschema.xml
@@ -9,13 +9,5 @@
GVariant returned by gweather_location_serialize().
</description>
</key>
- <key name="automatic-location" type="b">
- <default>true</default>
- <summary>Automatic location</summary>
- <description>
- The automatic location is the value of automatic-location switch which decides whether
- to fetch current location or not.
- </description>
- </key>
</schema>
</schemalist>
diff --git a/data/places-popover.ui b/data/places-popover.ui
index f1fffaa..589969b 100644
--- a/data/places-popover.ui
+++ b/data/places-popover.ui
@@ -2,14 +2,12 @@
<interface>
<requires lib="gtk" version="4.0"/>
<object class="GtkGrid" id="popover-grid">
+ <property name="name">popoverGrid</property>
+ <property name="hexpand">1</property>
<property name="orientation">vertical</property>
- <property name="row_spacing">10</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="Gjs_LocationSearchEntry" id="location-entry">
+ <property name="name">locationEntry</property>
<property name="focusable">1</property>
<property name="width-request">300</property>
<layout>
@@ -65,73 +63,21 @@
</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>
+ <object class="GtkScrolledWindow" id="search-list-scroll-window">
<child>
- <object class="GtkFrame">
- <property name="name">search-frame</property>
- <property name="child">
- <object class="GtkScrolledWindow" id="search-list-scroll-window">
- <child>
- <object class="GtkListView" id="search-list-view">
- <property name="name">search-list-view</property>
- <property name="hexpand">1</property>
- </object>
- </child>
- </object>
- </property>
- <layout>
- <property name="column">0</property>
- <property name="row">1</property>
- </layout>
+ <object class="GtkListView" id="search-list-view">
+ <property name="name">search-list-view</property>
+ <property name="hexpand">1</property>
</object>
</child>
</object>
</child>
<child>
- <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="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 class="GtkListBox" id="locations-list-box">
+ <property name="name">locations-list-box</property>
+ <property name="hexpand">1</property>
+ <property name="selection-mode">none</property>
+ <property name="show-separators">false</property>
</object>
</child>
diff --git a/src/app/city.js b/src/app/city.js
index 4478a85..8bcacb5 100644
--- a/src/app/city.js
+++ b/src/app/city.js
@@ -66,7 +66,7 @@ export const WeatherWidget = GObject.registerClass({
this._info = null;
- this._worldView = new WorldView.WorldContentView(application, window);
+ this._worldView = new WorldView.WorldContentView(application, window, {}, this);
this._placesButton.set_popover(this._worldView);
for (const adjustment of [this._forecastHourlyAdjustment, this._forecastDailyAdjustment]) {
@@ -207,6 +207,7 @@ export const WeatherWidget = GObject.registerClass({
this._conditionsImage.iconName = `${info.get_icon_name()}-large`;
const [, tempValue] = info.get_value_temp(GWeather.TemperatureUnit.DEFAULT);
+ console.log(tempValue);
this._temperatureLabel.label = '%d°'.format(Math.round(tempValue));
const [, apparentValue] = info.get_value_apparent(GWeather.TemperatureUnit.DEFAULT);
diff --git a/src/app/currentLocationController.js b/src/app/currentLocationController.js
index 8c891d6..fc66102 100644
--- a/src/app/currentLocationController.js
+++ b/src/app/currentLocationController.js
@@ -21,23 +21,14 @@ import GWeather from 'gi://GWeather';
import Geoclue from 'gi://Geoclue';
import * as Util from '../misc/util.js';
-
-/** @enum {number} */
-export const AutoLocation = {
- DISABLED: 0,
- ENABLED: 1,
- NOT_AVAILABLE: 2
-};
-
export class CurrentLocationController {
constructor(world) {
this._world = world;
this._processStarted = false;
this._settings = Util.getSettings('org.gnome.Weather');
- let autoLocation = this._settings.get_value('automatic-location').deep_unpack();
- this._syncAutoLocation(autoLocation);
- if (this.autoLocation == AutoLocation.ENABLED)
- this._startGeolocationService();
+
+ this.autoLocationAvailable = false;
+ this._startGeolocationService();
this.currentLocation = null;
}
@@ -53,7 +44,7 @@ export class CurrentLocationController {
_geoLocationFailed(e) {
log ("Failed to connect to GeoClue2 service: " + e.message);
- this.autoLocation = AutoLocation.NOT_AVAILABLE;
+ this.autoLocationAvailable = false;
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._world.currentLocationChanged(null);
});
@@ -72,6 +63,8 @@ export class CurrentLocationController {
client.distance_threshold = 100;
this._findLocation();
+
+ this.autoLocationAvailable = true;
}
_findLocation() {
@@ -94,22 +87,6 @@ export class CurrentLocationController {
this._world.currentLocationChanged(this.currentLocation);
}
- setAutoLocation(active) {
- this._settings.set_value('automatic-location', new GLib.Variant('b', active));
-
- if (this.autoLocation == AutoLocation.NOT_AVAILABLE)
- return;
- this._autoLocationChanged(active);
- this._syncAutoLocation(active);
- }
-
- _syncAutoLocation(autoLocation) {
- if (autoLocation)
- this.autoLocation = AutoLocation.ENABLED;
- else
- this.autoLocation = AutoLocation.DISABLED;
- }
-
_autoLocationChanged(active) {
if (active) {
if (!this._processStarted) {
diff --git a/src/app/entry.js b/src/app/entry.js
index 199b6e5..c5ee54d 100644
--- a/src/app/entry.js
+++ b/src/app/entry.js
@@ -5,7 +5,7 @@ import Gtk from 'gi://Gtk';
import GWeather from 'gi://GWeather';
import * as World from './world.js';
-
+import { LocationRow } from './locationRow.js';
GWeather.Location.prototype[Symbol.iterator] = function* () {
let child = this.next_child(null);
@@ -123,6 +123,7 @@ export const LocationSearchEntry = GObject.registerClass(
'location': GObject.ParamSpec.object("location", "location", "location",
GObject.ParamFlags.READWRITE, GWeather.Location.$gtype)
},
Signals: {
+ 'search-started': { param_types: [] },
'search-updated': { param_types: [GObject.String] },
}
},
@@ -139,25 +140,19 @@ export const LocationSearchEntry = GObject.registerClass(
this._entry.set_hexpand(true);
this._popup = null;
-
+ this.text = '';
this._entry.connect("search-changed", (source) => {
const text = source.get_text();
if (text === null || text === '') {
+ this.text = null;
this._filter?.setFilterString(text);
this.emit('search-updated', 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();
- }
-
+ if (!this.text) this.emit('search-started');
+ this.text = text;
this._filter?.setFilterString(text);
this.emit('search-updated', text);
});
@@ -174,6 +169,14 @@ export const LocationSearchEntry = GObject.registerClass(
});
}
+ get searchText() {
+ return this._entry.text;
+ }
+
+ set searchText(text) {
+ this._entry.text = text;
+ }
+
set location(loc) {
this._location = loc;
this.notify('location');
@@ -218,10 +221,6 @@ export const LocationSearchEntry = GObject.registerClass(
if (location instanceof GWeather.Location) {
this.location = location;
-
- if (this._popup) {
- this._popup.popdown();
- }
}
});
return selection;
@@ -231,17 +230,18 @@ export const LocationSearchEntry = GObject.registerClass(
let factory = new Gtk.SignalListItemFactory();
this._setupId = factory.connect("setup", (source, item) => {
- item.set_child(new World.LocationRow('--', false));
+ item.set_child(new LocationRow({ name: '', countryName: '' }));
});
this._bindId = factory.connect("bind", (source, listitem) => {
const row = listitem.get_child();
/** @type {GWeather.Location} */
const location = listitem.get_item();
- if (row instanceof World.LocationRow) {
+ if (row instanceof LocationRow) {
const parentName = location.get_parent().get_name();
const locationName = location.get_name();
- row.locationName = parentName ? [locationName, parentName].join(', ') : locationName;
+ row.name = locationName;
+ row.countryName = parentName ?? '';
}
});
diff --git a/src/app/locationRow.js b/src/app/locationRow.js
new file mode 100644
index 0000000..0fdf1c0
--- /dev/null
+++ b/src/app/locationRow.js
@@ -0,0 +1,40 @@
+import GObject from 'gi://GObject';
+import Gtk from 'gi://Gtk';
+import GLib from 'gi://GLib';
+
+// TODO: Finish converting into a proper GObject w/ properties
+export const LocationRow = GObject.registerClass({
+ CssName: 'WeatherLocationRow',
+ Template: GLib.Uri.resolve_relative(import.meta.url, './locationRow.ui', 0),
+ InternalChildren: ['label', 'countryLabel', 'locationIcon', 'currentIcon'],
+}, class LocationRow extends Gtk.Widget {
+ _init({ name, countryName, isSelected = false, isCurrentLocation = false }) {
+ super._init({});
+
+ Object.assign(this.layoutManager, {
+ orientation: Gtk.Orientation.HORIZONTAL,
+ });
+
+ this.name = name;
+ this.countryName = countryName ?? '';
+ this.isSelected = isSelected;
+ this.isCurrentLocation = isCurrentLocation;
+ }
+
+ set name(name) {
+ this._label.label = name;
+ }
+
+ set countryName(name) {
+ this._countryLabel.label = name;
+ }
+
+ set isCurrentLocation(is) {
+ this._locationIcon.visible = is;
+ }
+
+ set isSelected(is) {
+ this._currentIcon.visible = is;
+ }
+});
+LocationRow.set_layout_manager_type(Gtk.BoxLayout);
diff --git a/src/app/locationRow.ui b/src/app/locationRow.ui
new file mode 100644
index 0000000..b926a49
--- /dev/null
+++ b/src/app/locationRow.ui
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk" version="4.0"/>
+ <template class="Gjs_LocationRow">
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="name">label</property>
+ <property name="justify">left</property>
+ <property name="halign">start</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="countryLabel">
+ <property name="name">countryLabel</property>
+ <property name="justify">left</property>
+ <property name="halign">start</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="currentIcon">
+ <property name="name">currentIcon</property>
+ <property name="hexpand">1</property>
+ <property name="icon-name">emblem-ok-symbolic</property>
+ <property name="halign">start</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImage" id="locationIcon">
+ <property name="name">locationIcon</property>
+ <property name="icon-name">find-location-symbolic</property>
+ <property name="halign">end</property>
+ </object>
+ </child>
+ </template>
+</interface>
\ No newline at end of file
diff --git a/src/app/shell.js b/src/app/shell.js
index eeab176..3335454 100644
--- a/src/app/shell.js
+++ b/src/app/shell.js
@@ -29,10 +29,6 @@ export class ShellIntegration {
this._settings = new Gio.Settings({ schema_id: 'org.gnome.Weather' });
- this._settings.connect('changed::automatic-location', () => {
- this._impl.emit_property_changed('AutomaticLocation',
- new GLib.Variant('b', this.AutomaticLocation));
- });
this._settings.connect('changed::locations', () => {
this._impl.emit_property_changed('Locations',
new GLib.Variant('av', this.Locations));
@@ -48,7 +44,8 @@ export class ShellIntegration {
}
get AutomaticLocation() {
- return this._settings.get_boolean('automatic-location');
+ // We follow whether the user has location services on.
+ return true;
}
get Locations() {
diff --git a/src/app/window.js b/src/app/window.js
index e1c4db2..486438d 100644
--- a/src/app/window.js
+++ b/src/app/window.js
@@ -60,9 +60,12 @@ export const MainWindow = GObject.registerClass({
this._searchView.icon_name = pkg.name;
- this._searchEntry.connect('notify::location', (entry) => {
- this._searchLocationChanged(entry);
- });
+ // this._searchEntry.connect('notify::location', (entry, location) => {
+ // if (location) {
+ // let info = this._model.addNewLocation(location);
+ // this._model.setSelectedLocation(info);
+ // }
+ // });
this._pageWidgets[Page.CITY].push(this._refresh);
@@ -98,13 +101,6 @@ export const MainWindow = GObject.registerClass({
this._cityView.update();
}
- _searchLocationChanged(entry) {
- if (entry.location) {
- let info = this._model.addNewLocation(entry.location, false);
- this.showInfo(info, false);
- }
- }
-
_goToPage(page) {
for (let i = 0; i < this._pageWidgets[this._currentPage].length; i++)
this._pageWidgets[this._currentPage][i].hide();
@@ -120,12 +116,12 @@ export const MainWindow = GObject.registerClass({
this._showingDefault = true;
this._refreshRevealer.reveal_child = false;
let clc = this.application.currentLocationController;
- let autoLocation = clc.autoLocation;
- let currentLocation = clc.currentLocation;
- if (currentLocation)
- this.showInfo(this._model.getCurrentLocation(), false);
- else if (autoLocation != CurrentLocationController.AutoLocation.ENABLED)
- this.showInfo(this._model.getRecent(), false);
+
+ let mostRecent = this._model.getRecent();
+ if (mostRecent)
+ this.showInfo(mostRecent);
+ else
+ this.showSearch();
}
showSearch(text) {
@@ -139,29 +135,14 @@ export const MainWindow = GObject.registerClass({
this._searchEntry.get_completion().complete();
}
- showInfo(info, isCurrentLocation) {
+ updateCurrentLocation(info) { }
+
+ showInfo(info) {
if (!info) {
- if (isCurrentLocation && this._showingDefault)
- this.showDefault();
+ this.showDefault();
return;
}
- /*
- * Only show location updates if we have no loaded info and no
- * search text or if we are currently showing the previous
- * current location.
- */
- if (isCurrentLocation) {
- if (this._currentPage == Page.CITY) {
- if (!this._cityView.info._isCurrentLocation)
- return;
- } else if (this._currentPage == Page.SEARCH) {
- // TODO
- // if (this._searchEntry.text.length > 0)
- // return;
- }
- }
-
this._showingDefault = false;
this._refreshRevealer.reveal_child = true;
this.currentInfo = info;
diff --git a/src/app/world.js b/src/app/world.js
index a493ccf..b45cf2f 100644
--- a/src/app/world.js
+++ b/src/app/world.js
@@ -20,123 +20,20 @@
import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
-
-// TODO: Finish converting into a proper GObject w/ properties
-export const LocationRow = GObject.registerClass(class LocationRow extends Gtk.Widget {
-
- _init(locationName, isCurrentLocation) {
- super._init({});
-
- this._locationName = locationName;
- this._isCurrentLocation = isCurrentLocation;
-
- this._build();
- }
-
- get locationName() { return this._locationName };
-
- get isCurrentLocation() { return this._isCurrentLocation; }
-
- set locationName(value) {
- this._locationName = value;
- this._build();
- }
-
- set isCurrentLocation(value) {
- this._isCurrentLocation = value;
- this._build();
- }
-
- _build() {
-
- if (!this.grid) {
- this.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 grid = this.grid;
- let locationGrid = new Gtk.Grid({
- orientation: Gtk.Orientation.HORIZONTAL,
- column_spacing: 12,
- halign: Gtk.Align.START,
- hexpand: true,
- visible: true
- });
- this.locationLabel = new Gtk.Label({
- label: this.locationName,
- use_markup: true,
- halign: Gtk.Align.START,
- visible: true
- });
-
- locationGrid.attach(this.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
- });
- this.tempLabel = tempLabel;
- grid.attach(tempLabel, 1, 0, 1, 1);
-
- this.image = new Gtk.Image({
- icon_size: Gtk.IconSize.LARGE,
- use_fallback: true,
- halign: Gtk.Align.END
- });
- grid.attach(this.image, 2, 0, 1, 1);
- }
-
- if (this.isCurrentLocation && !this.currentImage) {
- this.currentImage = new Gtk.Image({
- icon_size: Gtk.IconSize.LARGE,
- icon_name: 'mark-location-symbolic',
- use_fallback: true,
- halign: Gtk.Align.START
- });
- this.grid.attach(this.currentImage, 1, 0, 1, 1);
- } else if (!this.isCurrentLocation && this.currentImage) {
- this.currentImage.unparent();
- this.currentImage = null;
- }
-
- this.locationLabel.label = this.locationName;
-
- }
-
- vfunc_root() {
- super.vfunc_root();
-
- this.grid.set_parent(this);
- }
-
- vfunc_unroot() {
- this.grid.unparent();
- this.grid = null;
-
- super.vfunc_unroot();
- }
-});
-LocationRow.set_layout_manager_type(Gtk.BoxLayout);
+import { LocationRow } from './locationRow.js';
class _WorldContentView extends Gtk.Popover {
static [GObject.TypeName] = 'WorldContentView';
_init(application, window, params = {}) {
super._init({
+ // halign: Gtk.Align.START,
hexpand: false,
vexpand: false,
...params,
});
+ this.add_css_class('weather-popover');
this.update_property([Gtk.AccessibleProperty.LABEL], [_("World view")]);
let builder = new Gtk.Builder();
builder.add_from_resource('/org/gnome/Weather/places-popover.ui');
@@ -144,12 +41,10 @@ class _WorldContentView extends Gtk.Popover {
let grid = builder.get_object('popover-grid');
this.set_child(grid);
- this._searchGrid = builder.get_object('empty-search-grid');
- this._searchResultsGrid = builder.get_object('search-grid');
- this._locationsGrid = builder.get_object('locations-grid');
this._searchListView = builder.get_object('search-list-view');
this._searchListScrollWindow = builder.get_object('search-list-scroll-window');
- this._searchListScrollWindow.set_size_request(-1, 400);
+ this._searchListScrollWindow.set_size_request(300, 400);
+
this.model = application.model;
this._window = window;
@@ -166,56 +61,72 @@ class _WorldContentView extends Gtk.Popover {
});
this._locationEntry = builder.get_object('location-entry');
-
+
this._locationEntry.setListView(this._searchListView);
- this._locationEntry.connect('search-updated', (_, term) => {
- if (term) {
- this._stackPopover.set_visible_child(this._searchResultsGrid);
- } else {
- this._syncStackPopover();
- }
+ this._locationEntry.connect('search-started', (entry, term) => {
+ this._syncStackPopover();
+ });
+ this._locationEntry.connect('notify::location', (entry) => {
+ if (entry.searchText)
+ entry.searchText = '';
+
+ this._locationChanged(entry.location);
+ this._syncStackPopover();
+
+ if (!entry.searchText)
+ this.popdown();
});
- this._locationEntry.connect('notify::location', (entry) => this._locationChanged(entry));
this.connect('show', () => {
this._locationEntry.grab_focus();
});
-
-
this._currentLocationController = application.currentLocationController;
-
-
this._listbox.connect('row-activated', (listbox, row) => {
- this._window.showInfo(row._info, false);
- this.model.moveLocationToFront(row._info);
- this.hide();
+ if (row._info)
+ this.model.setSelectedLocation(row._info);
+ this.popdown();
+ });
+
+ this.model.connect('selected-location-changed', (model, info) => {
+ console.log('selected')
+ this._window.showInfo(info);
+ this._onLocationAdded(model);
});
this.model.connect('current-location-changed', (model, info) => {
- this._window.showInfo(info, true);
+ this._onLocationAdded(model);
});
+
this._stackPopover = builder.get_object('popover-stack');
+ this._stackPopover.set_size_request(350, 400);
this._listbox.set_filter_func((row) => this._filterListbox(row));
- this.model.connect('location-added', (model, info, is_current) => {
- this._onLocationAdded(model, info, is_current);
+ this.model.connect('location-added', (model) => {
+ this._onLocationAdded(model);
});
- this.model.connect('location-removed', (model, info) => {
- this._onLocationRemoved(model, info);
+ this.model.connect('location-removed', (model) => {
+ this._onLocationAdded(model);
});
this._currentLocationAdded = false;
- let list = this.model.getAll();
- for (let i = list.length - 1; i >= 0; i--)
- this._onLocationAdded(this.model, list[i], list[i]._isCurrentLocation);
+
+ this._onLocationAdded(this.model);
}
vfunc_unroot() {
this._listbox.set_header_func(null);
+ this._window = null;
+ // TODO
+ [...this._listbox].forEach(row => {
+
+ row._info = null;
+ row.child.unparent();
+ });
+ this._listbox = null;
super.vfunc_unroot();
}
@@ -225,10 +136,11 @@ class _WorldContentView extends Gtk.Popover {
}
_syncStackPopover() {
- if (this.model.length == 1)
- this._stackPopover.set_visible_child(this._searchGrid);
- else
- this._stackPopover.set_visible_child(this._locationsGrid);
+ if (this._locationEntry.searchText) {
+ this._stackPopover.set_visible_child(this._searchListScrollWindow);
+ } else {
+ this._stackPopover.set_visible_child(this._listbox);
+ }
}
_filterListbox(row) {
@@ -236,70 +148,38 @@ class _WorldContentView extends Gtk.Popover {
row._info != this._window.currentInfo;
}
- _locationChanged(entry) {
- if (entry.location) {
- let info = this.model.addNewLocation(entry.location, false);
- this._window.showInfo(info, false);
- this.hide();
- entry.location = null;
+ _locationChanged(location) {
+ if (location) {
+ let info = this.model.addNewLocation(location);
+ this._window.showInfo(info);
}
}
- _onLocationAdded(model, info, isCurrentLocation) {
- let location = info.location;
+ // vfunc_unmap() {
- let name = location.get_city_name();
- const grid = new LocationRow(name, isCurrentLocation);
- let row = new Gtk.ListBoxRow({ visible: true });
- row.set_child(grid);
- row._info = info;
- row._isCurrentLocation = isCurrentLocation;
+ // super.vfunc_unmap();
+ // }
- if (isCurrentLocation) {
- if (this._currentLocationAdded) {
- let row0 = this._listbox.get_row_at_index(0);
- if (row0) {
- // TODO: GTK4
- delete row0._info;
- this._listbox.remove(row0);
- }
- }
+ _onLocationAdded(model) {
+ const infos = model.getAll();
- this._currentLocationAdded = true;
- this._listbox.insert(row, 0);
- } else {
- if (this._currentLocationAdded)
- this._listbox.insert(row, 1);
- else
- this._listbox.insert(row, 0);
- }
+ [...this._listbox].forEach(row => this._listbox.remove(row));
- if (info._updatedId)
- return;
+ for (const info of infos) {
+ let location = info.location;
- info._updatedId = info.connect('updated', (info) => {
- grid.tempLabel.label = info.get_temp_summary();
- grid.image.icon_name = info.get_symbolic_icon_name();
- });
+ let name = location.get_city_name() ?? location.get_name();
+ let countryName = location.get_country_name();
- this._syncStackPopover();
- this._currentLocationController.currentLocation = info
- }
+ const grid = new LocationRow({ name, countryName, isSelected: model.isSelectedLocation(info),
isCurrentLocation: model.isCurrentLocation(info) });
+ const row = new Gtk.ListBoxRow({ child: grid });
+ row._info = info;
- _onLocationRemoved(model, info) {
- Array.from(this._listbox).forEach((row) => {
- delete row._info;
- this._listbox.remove(row);
- });
+ this._listbox.append(row);
- if (info._updatedId) {
- info.disconnect(info._updatedId);
- info._updatedId = 0;
}
- if (info._isCurrentLocation)
- this._currentLocationAdded = false;
this._syncStackPopover();
}
diff --git a/src/org.gnome.Weather.src.gresource.xml.in b/src/org.gnome.Weather.src.gresource.xml.in
index 1383c50..8b06e1d 100644
--- a/src/org.gnome.Weather.src.gresource.xml.in
+++ b/src/org.gnome.Weather.src.gresource.xml.in
@@ -5,6 +5,8 @@
<file>app/city.js</file>
<file>app/currentLocationController.js</file>
<file>app/hourlyForecast.js</file>
+ <file>app/locationRow.js</file>
+ <file>app/locationRow.ui</file>
<file>app/thermometer.js</file>
<file>app/thermometer.ui</file>
<file>app/dailyForecast.js</file>
diff --git a/src/shared/world.js b/src/shared/world.js
index 3badf5b..b404264 100644
--- a/src/shared/world.js
+++ b/src/shared/world.js
@@ -24,9 +24,10 @@ import * as Util from '../misc/util.js';
export const WorldModel = GObject.registerClass({
Signals: {
- 'current-location-changed': { param_types: [ GWeather.Info ] },
- 'location-added': { param_types: [ GWeather.Info, GObject.Boolean ] },
- 'location-removed': { param_types: [ GWeather.Info ] }
+ 'selected-location-changed': { param_types: [GWeather.Info] },
+ 'current-location-changed': { param_types: [GWeather.Info] },
+ 'location-added': { param_types: [GWeather.Info] },
+ 'location-removed': { param_types: [GWeather.Info] }
},
Properties: {
'loading': GObject.ParamSpec.boolean('loading', '', '', GObject.ParamFlags.READABLE, false)
@@ -48,19 +49,39 @@ export const WorldModel = GObject.registerClass({
}
get length() {
- return this._infoList.length + (this._currentLocationInfo ? 1 : 0);
+ return this.getAll().length
}
getAll() {
- if (this._currentLocationInfo)
- return [this._currentLocationInfo].concat(this._infoList);
- else
- return [].concat(this._infoList);
+ // TODO: Clean this up
+ const infos = [...this._infoList];
+ const currentIndex = infos.findIndex(info => this._currentLocationInfo &&
info.get_location().equal(this._currentLocationInfo.get_location()))
+ const selectIndex = infos.findIndex(info => this._selectedLocation &&
info.get_location().equal(this._selectedLocation.get_location()));
+ if (this._currentLocationInfo && currentIndex > 0) {
+ infos.splice(currentIndex, 1);
+ infos.unshift(this._currentLocationInfo)
+ }
+
+ if (this._selectedLocation && selectIndex > 0) {
+ infos.splice(selectIndex, 1);
+
+ infos.unshift(this._selectedLocation)
+ }
+
+
+
+ return infos;
}
getAtIndex(index) {
- if (this._currentLocationInfo) {
+ if (this._selectedLocation) {
if (index == 0)
+ return this._selectedLocation;
+ else
+ index--;
+ }
+ if (this._currentLocationInfo) {
+ if (index == 1)
return this._currentLocationInfo;
else
index--;
@@ -74,15 +95,10 @@ export const WorldModel = GObject.registerClass({
}
currentLocationChanged(location) {
- if (this._currentLocationInfo)
- this._removeLocationInternal(this._currentLocationInfo, false);
-
- let info;
if (location)
- info = this.addNewLocation(location, true);
- else
- info = null;
- this.emit('current-location-changed', info);
+ this._currentLocationInfo = this.buildInfo(location);
+ if (this._currentLocationInfo)
+ this.emit('current-location-changed', this._currentLocationInfo);
}
getRecent() {
@@ -92,11 +108,11 @@ export const WorldModel = GObject.registerClass({
return null;
}
- load () {
+ load() {
let locations = this._settings.get_value('locations').deep_unpack();
- if (locations.length > 5) {
- locations = locations.slice(0, 5);
+ if (locations.length > 10) {
+ locations = locations.slice(0, 10).filter(location => !!location);
this._settings.set_value('locations', new GLib.Variant('av', locations));
}
@@ -105,9 +121,9 @@ export const WorldModel = GObject.registerClass({
let variant = locations[i];
let location = this._world.deserialize(variant);
- info = this._addLocationInternal(location, false);
+ info = this._addLocationInternal(location);
}
- this._currentLocationInfo = info
+ this.setSelectedLocation(info)
}
_updateLoadingCount(delta) {
@@ -138,21 +154,24 @@ export const WorldModel = GObject.registerClass({
return this._loadingCount > 0;
}
- addNewLocation(newLocation, isCurrentLocation) {
- if (!isCurrentLocation) {
- for (let info of this._infoList) {
- let location = info.location;
- if (location.equal(newLocation)) {
- this.moveLocationToFront(info);
- return info;
- }
- }
- }
+ setSelectedLocation(info) {
+ this._selectedLocation = info;
+ this.addNewLocation(info.get_location());
+ this.emit('selected-location-changed', info);
+ }
+
+ isSelectedLocation(info) {
+ return !!this._selectedLocation &&
((this._selectedLocation.get_location()?.equal(info.get_location())) ?? false);
+ }
+
+ isCurrentLocation(info) {
+ return !!this._currentLocationInfo &&
(this._currentLocationInfo.get_location()?.equal(info.get_location()) ?? false);
+ }
- let info = this._addLocationInternal(newLocation, isCurrentLocation);
+ addNewLocation(newLocation) {
+ let info = this._addLocationInternal(newLocation);
- if (!isCurrentLocation)
- this._queueSaveSettings();
+ this._queueSaveSettings();
return info;
}
@@ -205,6 +224,8 @@ export const WorldModel = GObject.registerClass({
}
_removeLocationInternal(oldInfo, skipDisconnect) {
+ if (!oldInfo) return;
+
if (oldInfo._loadingId && !skipDisconnect) {
oldInfo.disconnect(oldInfo._loadingId);
oldInfo._loadingId = 0;
@@ -224,35 +245,36 @@ export const WorldModel = GObject.registerClass({
this.emit('location-removed', oldInfo);
}
- _addLocationInternal(newLocation, isCurrentLocation) {
+ buildInfo(location) {
+ return new GWeather.Info({
+ application_id: pkg.name,
+ contact_info: 'https://gitlab.gnome.org/GNOME/gnome-weather/-/raw/master/gnome-weather.doap',
+ location,
+ enabled_providers: this._providers
+ });
+ }
+
+ _addLocationInternal(newLocation) {
for (let i = 0; i < this._infoList.length; i++) {
let info = this._infoList[i];
if (info.get_location().equal(newLocation))
return info;
}
- let info = new GWeather.Info({
- application_id: pkg.name,
- contact_info: 'https://gitlab.gnome.org/GNOME/gnome-weather/-/raw/master/gnome-weather.doap',
- location: newLocation,
- enabled_providers: this._providers
- });
- this._addInfoInternal(info, isCurrentLocation);
+ let info = this.buildInfo(newLocation);
+ this._addInfoInternal(info);
return info;
}
- _addInfoInternal(info, isCurrentLocation) {
- info._isCurrentLocation = isCurrentLocation;
+ _addInfoInternal(info) {
+
this._infoList.unshift(info);
this.updateInfo(info);
- if (isCurrentLocation)
- this._currentLocationInfo = info;
-
- this.emit('location-added', info, isCurrentLocation);
+ this.emit('location-added', info);
- if (this._infoList.length > 5) {
+ if (this._infoList.length > 10) {
let oldInfo = this._infoList.pop();
this._removeLocationInternal(oldInfo);
}
diff --git a/tests/testutil.py b/tests/testutil.py
index 25233ad..43dc04c 100644
--- a/tests/testutil.py
+++ b/tests/testutil.py
@@ -70,7 +70,6 @@ def reset_settings():
"(0.79354303905785273, "
"0.16057029118347829))>)>]")
settings.set_value("locations", parsed)
- settings.set_value("automatic-location", GLib.Variant.new_boolean(False))
def init():
@@ -78,12 +77,10 @@ def init():
settings = Gio.Settings("org.gnome.Weather")
_previous_locations = settings.get_value("locations")
- _automatic_location = settings.get_value("automatic-location")
reset_settings()
def fini():
settings.set_value("locations", _previous_locations)
- settings.set_value("automatic-location", _automatic_location)
_do_bus_call("ActivateAction",
GLib.Variant('(sava{sv})', ('quit', [], [])))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]