[gnome-shell: 4/14] dateMenu: Add Weather section
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell: 4/14] dateMenu: Add Weather section
- Date: Wed, 1 Mar 2017 09:59:12 +0000 (UTC)
commit 62606c68b965e1b7a6b538c6bc725b29376db543
Author: Florian Müllner <fmuellner gnome org>
Date: Fri Feb 24 13:15:39 2017 +0100
dateMenu: Add Weather section
Similar to the Clocks integration we've had in the date+time drop-down for
a while, the designs have called for a similar section that integrates
GNOME weather as well. Use the WeatherClient added in the previous commit
to implement that section and add it to the popover.
https://bugzilla.gnome.org/show_bug.cgi?id=754031
data/theme/gnome-shell-high-contrast.css | 8 ++
data/theme/gnome-shell-sass | 2 +-
data/theme/gnome-shell.css | 8 ++
js/ui/dateMenu.js | 131 ++++++++++++++++++++++++++++++
4 files changed, 148 insertions(+), 1 deletions(-)
---
diff --git a/data/theme/gnome-shell-high-contrast.css b/data/theme/gnome-shell-high-contrast.css
index be92d53..33c95cc 100644
--- a/data/theme/gnome-shell-high-contrast.css
+++ b/data/theme/gnome-shell-high-contrast.css
@@ -736,6 +736,7 @@ StScrollBar {
.datemenu-today-button,
.world-clocks-button,
+.weather-button,
.message-list-section-title {
border-radius: 4px;
padding: .4em; }
@@ -749,11 +750,14 @@ StScrollBar {
.datemenu-today-button:hover, .datemenu-today-button:focus,
.world-clocks-button:hover,
.world-clocks-button:focus,
+.weather-button:hover,
+.weather-button:focus,
.message-list-section-title:hover,
.message-list-section-title:focus {
background-color: #0d0d0d; }
.datemenu-today-button:active,
.world-clocks-button:active,
+.weather-button:active,
.message-list-section-title:active {
color: white;
background-color: #215d9c; }
@@ -762,6 +766,7 @@ StScrollBar {
font-size: 1.5em; }
.world-clocks-header,
+.weather-header,
.message-list-section-title {
color: #999999;
font-weight: bold; }
@@ -769,6 +774,9 @@ StScrollBar {
.world-clocks-grid {
spacing-rows: 0.4em; }
+.weather-box {
+ spacing: 0.4em; }
+
.calendar-month-label {
color: #f2f2f2;
font-weight: bold;
diff --git a/data/theme/gnome-shell-sass b/data/theme/gnome-shell-sass
index 50bbd0b..2af7107 160000
--- a/data/theme/gnome-shell-sass
+++ b/data/theme/gnome-shell-sass
@@ -1 +1 @@
-Subproject commit 50bbd0b50ff81d2a6d8441d79ac9e7be64517bb8
+Subproject commit 2af71071ae2f4e4e89851dee93befd5007d4d693
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index f6d2f67..88ec11b 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -736,6 +736,7 @@ StScrollBar {
.datemenu-today-button,
.world-clocks-button,
+.weather-button,
.message-list-section-title {
border-radius: 4px;
padding: .4em; }
@@ -749,11 +750,14 @@ StScrollBar {
.datemenu-today-button:hover, .datemenu-today-button:focus,
.world-clocks-button:hover,
.world-clocks-button:focus,
+.weather-button:hover,
+.weather-button:focus,
.message-list-section-title:hover,
.message-list-section-title:focus {
background-color: #454c4c; }
.datemenu-today-button:active,
.world-clocks-button:active,
+.weather-button:active,
.message-list-section-title:active {
color: white;
background-color: #215d9c; }
@@ -762,6 +766,7 @@ StScrollBar {
font-size: 1.5em; }
.world-clocks-header,
+.weather-header,
.message-list-section-title {
color: #8e8e80;
font-weight: bold; }
@@ -769,6 +774,9 @@ StScrollBar {
.world-clocks-grid {
spacing-rows: 0.4em; }
+.weather-box {
+ spacing: 0.4em; }
+
.calendar-month-label {
color: #e2e2df;
font-weight: bold;
diff --git a/js/ui/dateMenu.js b/js/ui/dateMenu.js
index 9e49e2d..5380672 100644
--- a/js/ui/dateMenu.js
+++ b/js/ui/dateMenu.js
@@ -8,6 +8,7 @@ const Gtk = imports.gi.Gtk;
const GWeather = imports.gi.GWeather;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
+const Pango = imports.gi.Pango;
const Cairo = imports.cairo;
const Clutter = imports.gi.Clutter;
const Shell = imports.gi.Shell;
@@ -20,6 +21,7 @@ const Main = imports.ui.main;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
const Calendar = imports.ui.calendar;
+const Weather = imports.misc.weather;
function _isToday(date) {
let now = new Date();
@@ -192,6 +194,133 @@ const WorldClocksSection = new Lang.Class({
}
});
+const WeatherSection = new Lang.Class({
+ Name: 'WeatherSection',
+
+ _init: function() {
+ this._weatherClient = new Weather.WeatherClient();
+
+ this.actor = new St.Button({ style_class: 'weather-button',
+ x_fill: true,
+ can_focus: true });
+ this.actor.connect('clicked', () => {
+ this._weatherClient.activateApp();
+
+ Main.overview.hide();
+ Main.panel.closeCalendar();
+ });
+ this.actor.connect('notify::mapped', () => {
+ if (this.actor.mapped)
+ this._weatherClient.update();
+ });
+
+ let box = new St.BoxLayout({ style_class: 'weather-box',
+ vertical: true });
+
+ this.actor.child = box;
+
+ box.add_child(new St.Label({ style_class: 'weather-header',
+ x_align: Clutter.ActorAlign.START,
+ text: _("Weather") }));
+
+ this._conditionsLabel = new St.Label({ style_class: 'weather-conditions',
+ x_align: Clutter.ActorAlign.START });
+ this._conditionsLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
+ this._conditionsLabel.clutter_text.line_wrap = true;
+ box.add_child(this._conditionsLabel);
+
+ this._weatherClient.connect('changed', Lang.bind(this, this._sync));
+ this._sync();
+ },
+
+ _getSummary: function(info) {
+ let summary = info.get_conditions();
+ if (summary == '-')
+ return info.get_sky();
+ return summary;
+ },
+
+ _sameSummary: function(info1, info2) {
+ let [ok1, phenom1, qualifier1] = info1.get_value_conditions();
+ let [ok2, phenom2, qualifier2] = info2.get_value_conditions();
+ if (ok1 || ok2)
+ return ok1 == ok2 && phenom1 == phenom2 && qualifier1 == qualifier2;
+
+ let [, sky1] = info1.get_value_sky();
+ let [, sky2] = info2.get_value_sky();
+ return sky1 == sky2;
+ },
+
+ _getSummaryText: function() {
+ let info = this._weatherClient.info;
+ let forecasts = info.get_forecast_list();
+ if (forecasts.length == 0) // No forecasts, just current conditions
+ return '%s.'.format(this._getSummary(info));
+
+ let current = info;
+ let summaries = [this._getSummary(info)];
+ for (let i = 0; i < forecasts.length; i++) {
+ let [ok, timestamp] = forecasts[i].get_value_update();
+ if (!_isToday(new Date(timestamp * 1000)))
+ continue; // Ignore forecasts from other days
+
+ if (this._sameSummary(current, forecasts[i]))
+ continue; // Ignore consecutive runs of equal summaries
+
+ current = forecasts[i];
+ if (summaries.push(this._getSummary(current)) == 3)
+ break; // Use a maximum of three summaries
+ }
+
+ let fmt;
+ switch(summaries.length) {
+ /* Translators: %s is a weather condition like "Clear sky"; see
+ libgweather for the possible condition strings. If at all
+ possible, the sentence should match the grammatical case etc. of
+ the inserted conditions. */
+ case 1: fmt = _("%s all day."); break;
+
+ /* Translators: %s is a weather condition like "Clear sky"; see
+ libgweather for the possible condition strings. If at all
+ possible, the sentence should match the grammatical case etc. of
+ the inserted conditions. */
+ case 2: fmt = _("%s, then %s later."); break;
+
+ /* Translators: %s is a weather condition like "Clear sky"; see
+ libgweather for the possible condition strings. If at all
+ possible, the sentence should match the grammatical case etc. of
+ the inserted conditions. */
+ case 3: fmt = _("%s, then %s, followed by %s later."); break;
+ }
+ return String.prototype.format.apply(fmt, summaries);
+ },
+
+ _getLabelText: function() {
+ if (this._weatherClient.loading)
+ return _("Loading…");
+
+ let info = this._weatherClient.info;
+ if (info.is_valid())
+ return this._getSummaryText() + ' ' +
+ /* Translators: %s is a temperature with unit, e.g. "23℃" */
+ _("Feels like %s.").format(info.get_apparent());
+
+ if (info.network_error())
+ return _("Go online for weather information");
+
+ return _("Weather information is currently unavailable");
+ },
+
+ _sync: function() {
+ this.actor.visible = this._weatherClient.available;
+
+ if (!this.actor.visible)
+ return;
+
+ this._conditionsLabel.text = this._getLabelText();
+ }
+});
+
const MessagesIndicator = new Lang.Class({
Name: 'MessagesIndicator',
@@ -394,6 +523,8 @@ const DateMenuButton = new Lang.Class({
this._clocksItem = new WorldClocksSection();
displaysBox.add(this._clocksItem.actor, { x_fill: true });
+ this._weatherItem = new WeatherSection();
+ displaysBox.add(this._weatherItem.actor, { x_fill: true });
// Done with hbox for calendar and event list
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]