[gnome-weather] Final new design



commit 74b80a2962d30193a01723df9c6a62dbe90e1107
Author: Saurabh <srp201201051 gmail com>
Date:   Wed Jul 30 23:05:21 2014 +0530

    Final new design
    
    https://bugzilla.gnome.org/show_bug.cgi?id=733236

 Makefile.am                                        |    4 +-
 autogen.sh                                         |    2 -
 configure.ac                                       |    9 -
 data/application.css                               |   23 +-
 data/city.ui                                       |  213 ++++++---
 data/new-location-dialog.ui                        |   63 ---
 ...rg.gnome.Weather.Application.data.gresource.xml |    2 +-
 data/org.gnome.Weather.Application.gschema.xml     |    8 +
 data/places-popover.ui                             |  299 +++++++++++
 data/window.ui                                     |  159 +------
 libgd                                              |    1 -
 src/app/city.js                                    |  149 ++++--
 src/app/currentLocationController.js               |   61 ++-
 src/app/forecast.js                                |  343 ++-----------
 src/app/main.js                                    |   61 ++-
 src/app/weeklyForecast.js                          |  140 +++++
 src/app/window.js                                  |  221 ++-------
 src/misc/util.js                                   |   25 +-
 ...org.gnome.Weather.Application.src.gresource.xml |    1 +
 src/shared/world.js                                |  545 ++++++++++----------
 20 files changed, 1180 insertions(+), 1149 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 0be1a60..2738258 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
-ACLOCAL_AMFLAGS = -I m4 -I libgd ${ACLOCAL_FLAGS}
+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
 DISTCHECK_CONFIGURE_FLAGS = --disable-dogtail
 
-SUBDIRS = po data libgd src tests
+SUBDIRS = po data src tests
 
 MAINTAINERCLEANFILES = \
        $(srcdir)/INSTALL \
diff --git a/autogen.sh b/autogen.sh
index a7a6ed9..fdf163f 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -4,7 +4,6 @@
 srcdir=`dirname $0`
 test -z "$srcdir" && srcdir=.
 
-ACLOCAL_FLAGS="-I libgd ${ACLOCAL_FLAGS}"
 PKG_NAME="gnome-weather"
 
 test -f $srcdir/configure.ac || {
@@ -21,6 +20,5 @@ which gnome-autogen.sh || {
 
 (cd "$srcdir" ;
 test -d m4 || mkdir m4/ ;
-git submodule update --init --recursive ;
 )
 . gnome-autogen.sh
diff --git a/configure.ac b/configure.ac
index e57bb87..c8638c4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,8 +23,6 @@ AC_PROG_CC
 AM_PROG_CC_C_O
 LT_INIT([disable-static])
 
-LIBGD_INIT([main-view gir])
-
 PKG_PROG_PKG_CONFIG([0.22])
 
 APPSTREAM_XML
@@ -63,12 +61,6 @@ if test x$enable_coverage = xyes; then
     if test x$LCOV = x || test x$GENHTML = x; then
         AC_MSG_ERROR([lcov and genhtml are required for --enable-coverage])
     fi
-
-    # only enable these if we ever want code coverage for libgd
-    # (which we don't)
-    #CFLAGS="$CFLAGS -g -O0 --coverage"
-    #CXXFLAGS="$CXXFLAGS -g -O0 --coverage"
-    #LIBS="$LIBS -lgcov"
 fi
 AM_CONDITIONAL([ENABLE_COVERAGE], [test x$enable_coverage = xyes])
 
@@ -81,7 +73,6 @@ AC_CONFIG_FILES([
   Makefile
   data/Makefile
   data/icons/Makefile
-  libgd/Makefile
   src/Makefile
   tests/Makefile
   po/Makefile.in
diff --git a/data/application.css b/data/application.css
index 0886843..367da2b 100644
--- a/data/application.css
+++ b/data/application.css
@@ -1,8 +1,3 @@
-#weather-page {
-    text-shadow: 1px 1px 3px black;
-    icon-shadow: 1px 1px 3px black;
-}
-
 #weather-page-placeholder-title {
     font-weight: bold;
     font-size: 1.2em;
@@ -18,41 +13,50 @@
 
 #weather-page-content-view.weather-clear {
     background-image: url("weather-clear.jpg");
+    color: rgba(0,0,0,0.8);
 }
 
 #weather-page-content-view.weather-clear-night {
     background-image: url("weather-clear-night.jpg");
+    color: rgba(255,255,255,0.8);
 }
 
 #weather-page-content-view.weather-few-clouds {
     background-image: url("weather-few-clouds.jpg");
+    color: rgba(0,0,0,0.6);
 }
 
 #weather-page-content-view.weather-few-clouds-night {
     background-image: url("weather-few-clouds-night.jpg");
+    color: rgba(255,255,255,0.8);
 }
 
 #weather-page-content-view.weather-fog {
     background-image: url("weather-fog.jpg");
     background-position: center 20%;
+    color: rgba(255,255,255,0.8);
 }
 
 #weather-page-content-view.weather-overcast {
     background-image: url("weather-overcast.jpg");
+    color: rgba(255,255,255,0.8);
 }
 
 #weather-page-content-view.weather-showers,
 #weather-page-content-view.weather-showers-scattered {
     background-image: url("weather-showers.jpg");
+    color: rgba(255,255,255,0.8);
 }
 
 #weather-page-content-view.weather-snow {
     background-image: url("weather-snow.jpg");
+    color: rgba(255,255,255,0.8);
 }
 
 #weather-page-content-view.weather-storm {
     background-image: url("weather-storm.jpg");
     background-position: center 80%;
+    color: rgba(255,255,255,0.8);
 }
 
 #loading-label {
@@ -81,6 +85,15 @@
     padding: 12px;
 }
 
+#weekly-forecast-frame {
+    background-color: rgba(0, 0, 0, 0.5);
+    color: white;
+}
+
 .content-view.cell {
     font-weight: bold;
 }
+
+#locations-list-box {
+    border: 1px solid @borders;
+}
\ No newline at end of file
diff --git a/data/city.ui b/data/city.ui
index 6a48271..f8e63c3 100644
--- a/data/city.ui
+++ b/data/city.ui
@@ -24,6 +24,9 @@
                 <property name="valign">center</property>
                 <property name="hexpand">True</property>
                 <property name="vexpand">True</property>
+                <property name="margin-start">50</property>
+                <property name="margin-end">20</property>
+                <property name="row_spacing">32</property>
                 <child>
                   <object class="GtkGrid" id="inner-grid">
                     <property name="name">conditions-grid</property>
@@ -55,9 +58,8 @@
                         <property name="name">temperature-label</property>
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="valign">end</property>
-                        <property name="vexpand">True</property>
-                        <property name="xalign">0</property>
+                        <property name="valign">start</property>
+                        <property name="halign">start</property>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
@@ -71,8 +73,9 @@
                         <property name="name">conditions-label</property>
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="valign">end</property>
-                        <property name="xalign">0</property>
+                        <property name="valign">start</property>
+                        <property name="vexpand">True</property>
+                        <property name="halign">start</property>
                       </object>
                       <packing>
                         <property name="left_attach">1</property>
@@ -85,8 +88,141 @@
                   <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="GtkGrid" id="stack-grid">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkStackSwitcher" id="day-stack-switcher">
+                        <property name="visible">True</property>
+                        <property name="stack">day-stack</property>
+                        <style>
+                          <class name="osd"/>
+                        </style>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkStack" id="day-stack">
+                        <property name="visible">False</property>
+                        <property name="no_show_all">True</property>
+                        <child>
+                          <object class="GtkButton" id="today-Button">
+                            <property name="visible">True</property>
+                          </object>
+                          <packing>
+                            <property name="name">today-button</property>
+                            <property name="title">Today</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkButton" id="tomorrow-button">
+                            <property name="visible">True</property>
+                          </object>
+                          <packing>
+                            <property name="name">tomorrow-button</property>
+                            <property name="title">Tomorrow</property>
+                          </packing>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkGrid" id="parent-grid">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <child>
+                      <object class="GtkScrolledWindow" id="forecast-scrolled-window">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="vscrollbar_policy">never</property>
+                        <property name="min_content_width">360</property>
+                        <property name="margin-start">32</property>
+                        <property name="margin-end">32</property>
+                        <child>
+                          <object class="GtkViewport" id="forecast-viewport">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="hscroll_policy">natural</property>
+                            <property name="vscroll_policy">natural</property>
+                            <child>
+                              <object class="GtkGrid" id="forecast-grid">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="halign">center</property>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="left-button">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="valign">center</property>
+                        <style>
+                          <class name="osd"/>
+                        </style>
+                        <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>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkButton" id="right-button">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <property name="receives_default">True</property>
+                        <property name="valign">center</property>
+                        <style>
+                          <class name="osd"/>
+                        </style>
+                        <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>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="left_attach">2</property>
+                        <property name="top_attach">0</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
                   </packing>
                 </child>
               </object>
@@ -101,13 +237,17 @@
               <object class="GtkGrid" id="time-grid">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
+                <property name="halign">end</property>
+                <property name="margin-end">20</property>
                 <child>
                   <object class="GtkImage" id="clock-image">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="xalign">1</property>
-                    <property name="xpad">10</property>
-                    <property name="ypad">15</property>
+                    <property name="halign">start</property>
+                    <property name="margin-start">10</property>
+                    <property name="margin-end">10</property>
+                    <property name="margin-top">15</property>
+                    <property name="margin-bottom">15</property>
                     <property name="icon_name">document-open-recent-symbolic</property>
                   </object>
                   <packing>
@@ -121,7 +261,8 @@
                   <object class="GtkLabel" id="time-label">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
-                    <property name="ypad">15</property>
+                    <property name="margin-top">15</property>
+                    <property name="margin-bottom">15</property>
                     <property name="label">label</property>
                   </object>
                   <packing>
@@ -143,55 +284,5 @@
         </child>
       </object>
     </child>
-    <child type="overlay">
-      <object class="GtkGrid" id="revealer-grid">
-        <property name="visible">True</property>
-        <property name="halign">end</property>
-        <child>
-          <object class="GtkButton" id="reveal-button">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="halign">center</property>
-            <property name="valign">center</property>
-            <property name="margin_right">20</property>
-            <style>
-              <class name="image-button"/>
-              <class name="osd"/>
-            </style>
-            <child internal-child="accessible">
-              <object class="AtkObject" id="reveal-button-a11y">
-                <property name="accessible-name" translatable="yes">Detailed forecast</property>
-                <property name="accessible-role">7</property><!-- check_box -->
-              </object>
-            </child>
-            <child>
-              <object class="GtkImage" id="reveal-button-image">
-                <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="icon-size">1</property>
-              </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="GtkRevealer" id="revealer">
-            <property name="reveal-child">false</property>
-            <property name="transition-type">slide-left</property>
-          </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>
-      </object>
-    </child>
   </object>
 </interface>
diff --git a/data/org.gnome.Weather.Application.data.gresource.xml 
b/data/org.gnome.Weather.Application.data.gresource.xml
index d0ae379..22d1ea4 100644
--- a/data/org.gnome.Weather.Application.data.gresource.xml
+++ b/data/org.gnome.Weather.Application.data.gresource.xml
@@ -3,8 +3,8 @@
   <gresource prefix="/org/gnome/Weather/Application">
     <file preprocess="xml-stripblanks">app-menu.ui</file>
     <file preprocess="xml-stripblanks">window.ui</file>
-    <file preprocess="xml-stripblanks">new-location-dialog.ui</file>
     <file preprocess="xml-stripblanks">city.ui</file>
+    <file preprocess="xml-stripblanks">places-popover.ui</file>
     <file>application.css</file>
     <file>weather-clear.jpg</file>
     <file>weather-clear-night.jpg</file>
diff --git a/data/org.gnome.Weather.Application.gschema.xml b/data/org.gnome.Weather.Application.gschema.xml
index 76677e4..aaf9d79 100644
--- a/data/org.gnome.Weather.Application.gschema.xml
+++ b/data/org.gnome.Weather.Application.gschema.xml
@@ -8,5 +8,13 @@
         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
new file mode 100644
index 0000000..3a80f68
--- /dev/null
+++ b/data/places-popover.ui
@@ -0,0 +1,299 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.16.1 -->
+<interface>
+  <requires lib="gtk+" version="3.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>
+    <child>
+      <object class="GWeatherLocationEntry" id="location-entry">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="width-request">300</property>
+      </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>
+        <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>
+              <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>
+          </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">Locating....</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <property name="vexpand">False</property>
+          </object>
+          <packing>
+            <property name="name">locating-label</property>
+          </packing>
+        </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>
+    </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>
+        <child>
+          <object class="GtkGrid" id="search-grid">
+            <property name="visible">True</property>
+            <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>
+            <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="halign">center</property>
+                <property name="valign">center</property>
+                <property name="vexpand">False</property>
+              </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">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>
+              </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">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>
+              <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>
+                <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>
+                  </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>
+            </child>
+          </object>
+          <packing>
+            <property name="name">locations-grid</property>
+          </packing>
+        </child>
+      </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>
+  <object class="GtkGrid" id="initial-grid">
+    <property name="visible">True</property>
+    <property name="name">initial-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>
+    <child>
+      <object class="GtkImage" id="mark-location-image">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="icon_name">mark-location-symbolic</property>
+        <property name="icon_size">6</property>
+        <property name="use_fallback">True</property>
+        <property name="halign">center</property>
+        <property name="valign">center</property>
+        <property name="vexpand">False</property>
+      </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-location-label">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="label">Search for a location</property>
+        <property name="halign">center</property>
+        <property name="valign">center</property>
+        <property name="vexpand">False</property>
+      </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>
+        <child>
+      <object class="GtkLabel" id="search-nereby-location-label">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="label">To see weather information, enter the name of a city.</property>
+        <property name="halign">center</property>
+        <property name="valign">center</property>
+        <property name="vexpand">False</property>
+      </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>
+    <child>
+    <object class="GWeatherLocationEntry" id="initial-grid-location-entry">
+      <property name="visible">True</property>
+      <property name="can_focus">True</property>
+    </object>
+    <packing>
+      <property name="left_attach">0</property>
+      <property name="top_attach">3</property>
+      <property name="width">1</property>
+      <property name="height">1</property>
+    </packing>
+    </child>
+  </object>
+</interface>
diff --git a/data/window.ui b/data/window.ui
index 5b1352a..e48d9b3 100644
--- a/data/window.ui
+++ b/data/window.ui
@@ -1,68 +1,16 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <!-- interface-requires gtk+ 3.10 -->
-  <menu id="selection-menu">
-    <section>
-      <item>
-        <attribute name="action">win.select-all</attribute>
-        <attribute name="label" translatable="yes">Select All</attribute>
-        <attribute name="accel">&lt;Primary&gt;a</attribute>
-      </item>
-      <item>
-        <attribute name="action">win.select-none</attribute>
-        <attribute name="label" translatable="yes">Select None</attribute>
-      </item>
-    </section>
-  </menu>
-  <object class="GtkMenuButton" id="selection-menu-button">
-    <property name="menu-model">selection-menu</property>
-    <property name="visible">True</property>
-    <property name="can-focus">True</property>
-    <child>
-      <object class="GtkBox" id="selection-menu-button-box">
-        <property name="visible">True</property>
-        <property name="can-focus">False</property>
-        <property name="orientation">horizontal</property>
-        <property name="spacing">6</property>
-        <child>
-          <object class="GtkLabel" id="selection-menu-button-label">
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <property name="label" translatable="yes">Click on locations to select them</property>
-          </object>
-          <packing>
-            <property name="pack-type">start</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkArrow" id="selection-menu-button-arrow">
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <property name="arrow-type">down</property>
-            <property name="shadow-type">none</property>
-          </object>
-          <packing>
-            <property name="pack-type">start</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-    <style>
-      <class name="selection-menu"/>
-    </style>
-  </object>
   <object class="GtkHeaderBar" id="header-bar">
     <property name="visible">True</property>
     <property name="vexpand">False</property>
     <property name="show-close-button">True</property>
     <child>
-      <object class="GtkButton" id="new-button">
+      <object class="GtkMenuButton" id="places-button">
         <property name="visible">True</property>
         <property name="can_focus">True</property>
-        <property name="label" translatable="yes">New</property>
-        <property name="action-name">win.new-location</property>
+        <property name="label" translatable="yes">Places</property>
+        <property name="use-popover">True</property>
         <property name="valign">center</property>
         <style>
           <class name="text-button"/>
@@ -73,78 +21,6 @@
       </packing>
     </child>
     <child>
-      <object class="GtkButton" id="world-button">
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="action-name">win.go-world</property>
-        <property name="valign">center</property>
-        <style>
-          <class name="image-button"/>
-        </style>
-        <child internal-child="accessible">
-          <object class="AtkObject" id="world-button-a11y">
-            <property name="accessible-name" translatable="yes">Back</property>
-          </object>
-        </child>
-        <child>
-          <object class="GtkImage" id="world-button-image">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="icon-size">1</property>
-            <property name="icon-name">go-previous-symbolic</property>
-          </object>
-        </child>
-      </object>
-      <packing>
-        <property name="pack_type">start</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkButton" id="select-button">
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="action-name">win.selection-mode</property>
-        <property name="action-target">true</property>
-        <property name="valign">center</property>
-        <style>
-          <class name="image-button"/>
-        </style>
-        <child internal-child="accessible">
-          <object class="AtkObject" id="select-button-a11y">
-            <property name="accessible-name" translatable="yes">Select</property>
-          </object>
-        </child>
-        <child>
-          <object class="GtkImage" id="select-button-image">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="icon-name">object-select-symbolic</property>
-            <property name="icon-size">1</property>
-          </object>
-        </child>
-      </object>
-      <packing>
-        <property name="pack_type">end</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkButton" id="done-button">
-        <property name="visible">True</property>
-        <property name="no_show_all">True</property>
-        <property name="can_focus">True</property>
-        <property name="label" translatable="yes">Cancel</property>
-        <property name="valign">center</property>
-        <property name="action-name">win.selection-mode</property>
-        <property name="action-target">false</property>
-        <style>
-          <class name="text-button"/>
-        </style>
-          </object>
-          <packing>
-            <property name="pack_type">end</property>
-          </packing>
-    </child>
-    <child>
       <object class="GtkButton" id="refresh-button">
         <property name="visible">True</property>
         <property name="can_focus">True</property>
@@ -193,34 +69,5 @@
         <property name="height">1</property>
       </packing>
     </child>
-    <child>
-      <object class="GtkActionBar" id="selection-bar">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="no-show-all">True</property>
-        <child>
-          <object class="GtkButton" id="delete-button">
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">True</property>
-            <property name="label" translatable="yes">Delete</property>
-            <property name="action-name">win.delete-selected</property>
-            <property name="valign">center</property>
-            <style>
-              <class name="text-button"/>
-            </style>
-          </object>
-          <packing>
-            <property name="pack_type">end</property>
-          </packing>
-        </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>
-    </child>
   </object>
 </interface>
diff --git a/src/app/city.js b/src/app/city.js
index b29e02e..c17b2d4 100644
--- a/src/app/city.js
+++ b/src/app/city.js
@@ -16,14 +16,13 @@
 // with Gnome Weather; if not, write to the Free Software Foundation,
 // Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-const Atk = imports.gi.Atk;
-const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const GLib = imports.gi.GLib;
 const Gnome = imports.gi.GnomeDesktop;
 const Lang = imports.lang;
 
 const Forecast = imports.app.forecast;
+const WForecast = imports.app.weeklyForecast;
 const Params = imports.misc.params;
 const Util = imports.misc.util;
 
@@ -39,49 +38,115 @@ const WeatherWidget = new Lang.Class({
         this.parent(params);
 
         this._currentStyle = null;
+        this._info = null;
 
         let builder = new Gtk.Builder();
         builder.add_from_resource('/org/gnome/Weather/Application/city.ui');
 
         let outerBox = builder.get_object('outer-box');
         this._contentFrame = builder.get_object('content-frame');
-        let outerGrid = builder.get_object('outer-grid');
+        this._outerGrid = builder.get_object('outer-grid');
+        this._forecastGrid = builder.get_object('forecast-grid');
+        this._wForecastFrame = builder.get_object('weekly-forecast-frame');
+        let forecastScrollingWindow = builder.get_object('forecast-scrolled-window');
         this._icon = builder.get_object('conditions-image');
         this._temperature = builder.get_object('temperature-label');
         this._conditions = builder.get_object('conditions-label');
-        this._revealButton = builder.get_object('reveal-button');
-        this._revealer = builder.get_object('revealer');
-        this._time = builder.get_object('time-label');
+        this.timeLabel = builder.get_object('time-label');
+        this.timeGrid = builder.get_object('time-grid');
+        this._dayStack = builder.get_object('day-stack');
+        this._leftButton = builder.get_object('left-button');
+        this._rightButton = builder.get_object('right-button');
+
+        this._forecasts = new Forecast.ForecastBox({ hexpand: false });
+        this._forecastGrid.attach(this._forecasts, 0, 0, 1, 1);
+
+        this._weeklyForecasts = new WForecast.WeeklyForecastFrame();
+        this._outerGrid.attach(this._weeklyForecasts, 1, 0, 1, 2);
+
+        this._hscrollbar = forecastScrollingWindow.get_hscrollbar();
+        this._hscrollbar.set_opacity(0.0);
+
+        this._hadjustment = forecastScrollingWindow.get_hadjustment();
+
+        this._hadjustment.connect('changed', Lang.bind(this, function() {
+            if ((this._hadjustment.get_upper() - this._hadjustment.get_lower()) == 
this._hadjustment.page_size) {
+                this._leftButton.set_sensitive(false);
+                this._rightButton.set_sensitive(false);
+            } else if (this._hadjustment.value == this._hadjustment.get_lower()){
+                this._leftButton.set_sensitive(false);
+                this._rightButton.set_sensitive(true);
+            } else if (this._hadjustment.value >= (this._hadjustment.get_upper() - 
this._hadjustment.page_size)){
+                this._leftButton.set_sensitive(true);
+                this._rightButton.set_sensitive(false);
+            } else {
+                this._leftButton.set_sensitive(true);
+                this._rightButton.set_sensitive(true);
+            }
+        }));
 
-        this._forecasts = new Forecast.ForecastBox({ hexpand: true });
-        outerGrid.attach(this._forecasts, 0, 2, 1, 1);
+        this._dayStack.connect('notify::visible-child', Lang.bind(this, function() {
+            this.clear();
+            if (this._info) {
+                let forecasts = this._info.get_forecast_list();
+                this._forecasts.update(forecasts, this._dayStack.get_visible_child_name());
+                this._hadjustment.value = this._hadjustment.get_lower();
+                this._forecasts.show();
+            }
+        }));
 
-        this._today = new Forecast.TodaySidebar({ vexpand: true,
-                                                  name: 'today-sidebar' });
-        this._revealer.child = this._today;
+        this._leftButton.connect('clicked', Lang.bind(this, function() {
+            this._target = this._hadjustment.value - this._hadjustment.page_size;
+            if (this._target <= this._hadjustment.get_lower()) {
+                this._leftButton.set_sensitive(false);
+                this._rightButton.set_sensitive(true);
+            } else
+                this._rightButton.set_sensitive(true);
+
+            this._start = new Date().getTime();
+            this._end = this._start + 700;
+            this._tickId = this._forecastGrid.add_tick_callback(Lang.bind(this, this._animate));
+        }));
 
-        this._revealButton.connect('clicked', Lang.bind(this, function() {
-            this._revealer.reveal_child = !this._revealer.reveal_child;
-            this._syncRevealButton();
+        this._rightButton.connect('clicked', Lang.bind(this, function() {
+            this._target = this._hadjustment.value + this._hadjustment.page_size;
+            if (this._target >= this._hadjustment.get_upper() - this._hadjustment.page_size) {
+                this._rightButton.set_sensitive(false);
+                this._leftButton.set_sensitive(true);
+            } else
+                this._leftButton.set_sensitive(true);
+
+            this._start = new Date().getTime();
+            this._end = this._start + 700;
+            this._tickId = this._forecastGrid.add_tick_callback(Lang.bind(this, this._animate));
         }));
-        this._syncRevealButton();
 
         this.add(outerBox);
     },
 
-    _syncRevealButton: function() {
-        if (this._revealer.reveal_child) {
-            this._revealButton.get_child().icon_name = 'go-next-symbolic';
-            this._revealButton.get_accessible().ref_state_set().add_state(Atk.StateType.CHECKED);
+    _animate: function() {
+        let value = this._hadjustment.value;
+        let t = 1.0;
+        let now = new Date().getTime();
+        if (now < this._end) {
+            t = (now - this._start) / 700;
+            t = this._easeOutCubic (t);
+            this._hadjustment.value = value + t * (this._target - value);
+            return true;
         } else {
-            this._revealButton.get_child().icon_name = 'go-previous-symbolic';
-            this._revealButton.get_accessible().ref_state_set().remove_state(Atk.StateType.CHECKED);
+            this._hadjustment.value = value + t * (this._target - value);
+            this._forecastGrid.remove_tick_callback(this._tickId);
+            return false;
         }
     },
 
+    _easeOutCubic: function(value) {
+        let temp = value - 1;
+        return temp * temp * temp + 1;
+    },
+
     clear: function() {
         this._forecasts.clear();
-        this._today.clear();
     },
 
     _get_style_class: function(info) {
@@ -91,6 +156,8 @@ const WeatherWidget = new Lang.Class({
     },
 
     update: function(info) {
+        this._info = info;
+
         this._conditions.label = Util.getWeatherConditions(info);
         this._temperature.label = info.get_temp_summary();
 
@@ -102,17 +169,14 @@ const WeatherWidget = new Lang.Class({
         context.add_class(this._currentStyle);
 
         let forecasts = info.get_forecast_list();
-        if (forecasts.length > 0) {
-            this._forecasts.update(forecasts);
-            this._forecasts.show();
+        this._forecasts.update(forecasts, this._dayStack.get_visible_child_name());
+        this._forecasts.show();
 
-            this._today.update(info);
-            this._revealButton.show();
-            this._revealer.show();
+        if (forecasts.length == 0) {
+            this._weeklyForecasts.hide();
         } else {
-            this._forecasts.hide();
-            this._revealButton.hide();
-            this._revealer.hide();
+            this._weeklyForecasts.show();
+            this._weeklyForecasts.update(forecasts);
         }
     }
 });
@@ -136,13 +200,16 @@ const WeatherView = new Lang.Class({
                                         name: "loading-label" }));
         this.add_named(loadingPage, 'loading');
 
-        this._infoPage = new WeatherWidget();
-        this.add_named(this._infoPage, 'info');
+        this.infoPage = new WeatherWidget();
+        this.add_named(this.infoPage, 'info');
 
         this._info = null;
         this._updateId = 0;
 
         this.connect('destroy', Lang.bind(this, this._onDestroy));
+
+        this._wallClock = new Gnome.WallClock();
+        this._clockHandlerId = null;
     },
 
     get info() {
@@ -154,7 +221,7 @@ const WeatherView = new Lang.Class({
             this._info.disconnect(this._updateId);
             this._updateId = 0;
 
-            this._infoPage.clear();
+            this.infoPage.clear();
         }
 
         this._info = info;
@@ -177,26 +244,25 @@ const WeatherView = new Lang.Class({
     update: function() {
         this.visible_child_name = 'loading';
         this._spinner.start();
-        this._infoPage.clear();
+        this.infoPage.clear();
 
         getApp().model.updateInfo(this._info);
     },
 
     _onUpdate: function(info) {
-        this._infoPage.clear();
-        this._infoPage.update(info);
+        this.infoPage.clear();
+        this.infoPage.update(info);
         this._updateTime();
         this._spinner.stop();
         this.visible_child_name = 'info';
     },
 
     connectClock: function() {
-        this._wallClock = new Gnome.WallClock();
         this._clockHandlerId = this._wallClock.connect('notify::clock', Lang.bind(this, this._updateTime));
     },
 
     _updateTime: function() {
-        this._infoPage._time.label = this._getTime();
+        this.infoPage.timeLabel.label = this._getTime();
     },
 
     _getTime: function() {
@@ -210,6 +276,9 @@ const WeatherView = new Lang.Class({
     },
 
     disconnectClock: function() {
-        this._wallClock.disconnect(this._clockHandlerId);
+        if (this._clockHandlerId) {
+            this._wallClock.disconnect(this._clockHandlerId);
+            this._clockHandlerId = null;
+        }
     }
 });
diff --git a/src/app/currentLocationController.js b/src/app/currentLocationController.js
index c4df077..dd64c9b 100644
--- a/src/app/currentLocationController.js
+++ b/src/app/currentLocationController.js
@@ -17,12 +17,13 @@
 // Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 const GLib = imports.gi.GLib;
-const GObject = imports.gi.GObject;
 const Gio = imports.gi.Gio;
 const Lang = imports.lang;
 const GWeather = imports.gi.GWeather;
 const Geocode = imports.gi.GeocodeGlib;
 
+const Util = imports.misc.util;
+
 const ManagerInterface = '<node> \
 <interface name="org.freedesktop.GeoClue2.Manager"> \
     <method name="GetClient"> \
@@ -70,9 +71,19 @@ const CurrentLocationController = new Lang.Class({
 
     _init: function(world) {
         this._world = world;
+        this._processStarted = false;
+        this._settings = Util.getSettings('org.gnome.Weather.Application');
+        this.autoLocation = this._settings.get_value('automatic-location').deep_unpack();
+        if(this.autoLocation)
+            this._startGeolocationService();
+        this.currentLocation = null;
+    },
+
+    _startGeolocationService: function() {
+        this._processStarted = true;
         this._managerProxy = new ManagerProxy(Gio.DBus.system,
-                                               "org.freedesktop.GeoClue2",
-                                               "/org/freedesktop/GeoClue2/Manager");
+                                              "org.freedesktop.GeoClue2",
+                                              "/org/freedesktop/GeoClue2/Manager");
 
         this._managerProxy.GetClientRemote(this._onGetClientReady.bind(this));
     },
@@ -80,6 +91,7 @@ const CurrentLocationController = new Lang.Class({
     _onGetClientReady: function(result, e) {
         if (e) {
             log ("Failed to connect to GeoClue2 service: " + e.message);
+            this._world.currentLocationChanged(null);
             return;
         }
 
@@ -100,11 +112,12 @@ const CurrentLocationController = new Lang.Class({
             this._clientProxy.connectSignal("LocationUpdated",
                                             this._getCurrentLocation.bind(this));
 
-        this._clientProxy.StartRemote(function(result, e) {
+        this._clientProxy.StartRemote(Lang.bind(this, function(result, e) {
             if (e) {
                 log ("Failed to connect to GeoClue2 service: " + e.message);
+                this._world.currentLocationChanged(null);
             }
-        });
+        }));
     },
 
     _getCurrentLocation: function(proxy, sender, [oldPath, newPath]) {
@@ -117,35 +130,25 @@ const CurrentLocationController = new Lang.Class({
                                               description: geoclueLocation.Description });
 
         this.currentLocation = GWeather.Location.get_world().find_nearest_city (location.latitude, 
location.longitude);
-        this._addCurrentLocation();
+        this._world.currentLocationChanged(this.currentLocation);
     },
 
-    _addCurrentLocation: function() {
-        let allLocations = this._world.getAllSavedLocations();
-        let isSimilar = Lang.bind(this, function(location) {
-            return this._isLocationSimilar(location);
-        });
-        if (allLocations.some(isSimilar))
-            return;
-
-        this._world.addLocation(this.currentLocation, false);
+    setAutoLocation: function(active) {
+        this._settings.set_value('automatic-location', new GLib.Variant('b', active));
+        this._autoLocationChanged(active);
     },
 
-    _isLocationSimilar: function(location) {
-        if (this.currentLocation != null) {
-            let station_code = location.get_code ();
-            let currentLocationCode = this.currentLocation.get_code();
-
-            if (station_code && currentLocationCode && (station_code == currentLocationCode)) {
-                let name = location.get_name ();
-                let currentLocationName = this.currentLocation.get_name();
-
-                if (name && currentLocationName && (name == currentLocationName)) {
-                    return true;
-                }
+    _autoLocationChanged: function(active) {
+        if (active) {
+            if (!this._processStarted) {
+                this._startGeolocationService();
+            } else {
+                this._locationUpdatedId =
+                    this._clientProxy.connectSignal("LocationUpdated",
+                                                    Lang.bind(this, this._getCurrentLocation));
             }
+        } else {
+            this._clientProxy.disconnectSignal(this._locationUpdatedId);
         }
-
-        return false;
     }
 });
diff --git a/src/app/forecast.js b/src/app/forecast.js
index baec9a3..f850762 100644
--- a/src/app/forecast.js
+++ b/src/app/forecast.js
@@ -19,7 +19,6 @@
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const Gtk = imports.gi.Gtk;
-const GWeather = imports.gi.GWeather;
 const Lang = imports.lang;
 
 const Params = imports.misc.params;
@@ -27,8 +26,6 @@ const Strings = imports.shared.strings;
 const Util = imports.misc.util;
 
 // In microseconds
-const ONE_DAY = 24*3600*1000*1000;
-const TWELVE_HOURS = 12*3600*1000*1000;
 const ONE_HOUR = 3600*1000*1000;
 
 const ForecastBox = new Lang.Class({
@@ -40,177 +37,15 @@ const ForecastBox = new Lang.Class({
         this.parent(params);
         this.get_accessible().accessible_name = _("Forecast");
 
+        this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
+
         this._grid = new Gtk.Grid({ orientation: Gtk.Orientation.HORIZONTAL,
-                                    column_spacing: 24,
+                                    column_spacing: 32,
                                     row_spacing: 6,
-                                    margin: 12,
+                                    margin_top: 12,
+                                    margin_bottom: 12,
                                     column_homogeneous: true });
         this.add(this._grid);
-
-        let context = this.get_style_context();
-        context.add_class('background');
-        context.add_class('osd');
-    },
-
-    update: function(infos) {
-        let dates = infos.map(function(i) {
-            let [ok, date] = i.get_value_update();
-            return GLib.DateTime.new_from_unix_local(date);
-        });
-
-        let subday = this._hasSubdayResolution(dates);
-        this._today = GLib.DateTime.new_now_local();
-        this._tomorrow = this._today.add_days(1);
-
-        let current, currentPart;
-        let n = 0;
-        // limit to 5 infos max
-        for (let i = 0; i < dates.length && n < 5; i++) {
-            let info = infos[i];
-
-            // only show forecasts if they're separated by
-            // at least 12 hours
-            let [ok, date] = info.get_value_update();
-            let datetime = GLib.DateTime.new_from_unix_local(date);
-            let part = Strings.getDatetimePart(datetime);
-
-            // Filter out "uninteresting" times (ie, during the night)
-            if (part == -1)
-                continue;
-
-            // Filter two datetime that would give the same "Day Part" string
-            if (current && part == currentPart &&
-                Util.arrayEqual(current.get_ymd(), datetime.get_ymd()))
-                continue;
-
-            let text = '<b>' + this._getDate(datetime, subday) + '</b>';
-            let label = new Gtk.Label({ label: text,
-                                        use_markup: true,
-                                        visible: true });
-            this._grid.attach(label, n, 0, 1, 1);
-
-            let image = new Gtk.Image({ icon_name: info.get_symbolic_icon_name(),
-                                        icon_size: Gtk.IconSize.DIALOG,
-                                        use_fallback: true,
-                                        visible: true });
-            this._grid.attach(image, n, 1, 1, 1);
-
-            let temperature = new Gtk.Label({ label: this._getTemperature(info),
-                                              visible: true });
-            this._grid.attach(temperature, n, 2, 1, 1);
-
-            current = datetime;
-            currentPart = part;
-            n++;
-        }
-    },
-
-    clear: function() {
-        this._grid.foreach(function(w) { w.destroy(); });
-    },
-
-    _hasSubdayResolution: function(dates) {
-        if (dates.length == 1)
-            return false;
-
-        if (dates[1].difference(dates[0]) < ONE_DAY)
-            return true;
-        else
-            return false;
-    },
-
-    _getDate: function(datetime, subday) {
-        if (Util.arrayEqual(this._today.get_ymd(),
-                            datetime.get_ymd())) {
-            if (subday)
-                return Strings.formatToday(datetime);
-            else
-                return _("Today");
-        } else if (Util.arrayEqual(this._tomorrow.get_ymd(),
-                                   datetime.get_ymd())) {
-            if (subday)
-                return Strings.formatTomorrow(datetime);
-            else
-                return _("Tomorrow");
-        } else {
-            if (subday)
-                return Strings.formatDayPart(datetime);
-            else
-                return datetime.format('%A');
-        }
-    },
-
-    _getTemperature: function(info) {
-        let [ok1, ] = info.get_value_temp_min(GWeather.TemperatureUnit.DEFAULT);
-        let [ok2, ] = info.get_value_temp_max(GWeather.TemperatureUnit.DEFAULT);
-
-        if (ok1 && ok2) {
-            // TRANSLATORS: this is the temperature string, minimum and maximum.
-            // The two values are already formatted, so it would be something like
-            // "7 °C / 19 °C"
-            return _("%s / %s").format(info.get_temp_min(), info.get_temp_max());
-        } else {
-            return info.get_temp_summary();
-        }
-    }
-});
-
-const TodaySidebar = new Lang.Class({
-    Name: 'TodaySidebar',
-    Extends: Gtk.ScrolledWindow,
-
-    _init: function(params) {
-        params = Params.fill(params, { hscrollbar_policy: Gtk.PolicyType.NEVER });
-        this.parent(params);
-
-        let context = this.get_style_context();
-        context.add_class('view');
-        context.add_class('content-view');
-
-        this._settings = new Gio.Settings({ schema: 'org.gnome.desktop.interface' });
-
-        let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
-                                vexpand: true });
-        this.add(box);
-
-        this._grid = new Gtk.Grid({ column_spacing: 12,
-                                    row_spacing: 6,
-                                    margin: 12 });
-        box.add(this._grid);
-
-        this._headline = new Gtk.Label({ use_markup: true,
-                                         xalign: 0.0 });
-        this._grid.attach(this._headline, 0, 0, 3, 1);
-
-        this._subline = new Gtk.Label({ margin_bottom: 4,
-                                        xalign: 0.0 });
-        this._grid.attach(this._subline, 0, 1, 3, 1);
-
-        this._attribution = new Gtk.Label({ xalign: 0.5,
-                                            wrap: true,
-                                            max_width_chars: 32,
-                                            margin_bottom: 10,
-                                            name: 'attribution-label',
-                                            use_markup: true });
-        box.pack_end(this._attribution, false, false, 0);
-
-        this._moreButton = new Gtk.Button({ label: _("More…"),
-                                            margin_top: 4,
-                                            halign: Gtk.Align.END,
-                                            visible: true });
-        this._moreButton.connect('clicked', Lang.bind(this, this._changeView));
-        this._tomorrow = false;
-
-        this._infoWidgets = [];
-        this._trimmedIndex = -1;
-    },
-
-    clear: function() {
-        this._infoWidgets.forEach(function(w) { w.destroy(); });
-        this._infoWidgets = [];
-
-        if (this._moreButton.get_parent())
-            this._grid.remove(this._moreButton);
     },
 
     // Ensure that infos are sufficiently spaced, and
@@ -256,57 +91,31 @@ const TodaySidebar = new Lang.Class({
         return ret;
     },
 
-    update: function(info) {
-        let infos = info.get_forecast_list();
-
-        let [ok, v_first] = infos[0].get_value_update();
+    update: function(infos, day) {
+        if (infos.length > 0) {
+            let now = GLib.DateTime.new_now_local();
+            if (day == "tomorrow-button")
+                now = now.add_days(1);
+            let dayInfo = this._preprocess(now, infos);
 
-        let now = GLib.DateTime.new_now_local();
-        let first = GLib.DateTime.new_from_unix_local(v_first);
-
-        this._trimmedToday = this._preprocess(now, infos);
-        this._trimmedTomorrow = this._preprocess(now.add_days(1), infos);
-
-        let hasToday = this._trimmedToday.length > 0;
-        let hasTomorrow = this._trimmedTomorrow.length > 0;
-
-        this._tomorrow = !hasToday;
-        this._updateHeadline();
-
-        let i;
-        let infos = hasToday ? this._trimmedToday : this._trimmedTomorrow;
-
-        // Show at most 6 hours now, we'll show more with the ... button
-        for (i = 0; i < Math.min(infos.length, 6); i++) {
-            let info = infos[i];
-            this._addOneInfo(info, i + 2);
-        }
-
-        this._grid.attach(this._moreButton, 2, i+2, 1, 1);
-
-        this._trimmedIndex = i;
-        this._hasMore = false;
-        if (this._trimmedIndex < infos.length) {
-            this._hasMore = true;
-            this._moreButton.label = _("More…");
-            this._moreButton.show();
-        } else if (hasToday && hasTomorrow) {
-            this._moreButton.show();
-            this._moreButton.label = _("Tomorrow");
-        } else {
-            this._moreButton.hide();
-        }
+            if (dayInfo.length == 0) {
+                now = now.add_hours(-2);
+                dayInfo = this._preprocess(now, infos);
+            }
 
-        let attr = info.get_attribution();
-        if (attr) {
-            this._attribution.label = attr;
-            this._attribution.show();
+            for (let i = 0; i < dayInfo.length; i++) {
+                let info = dayInfo[i];
+                this._addOneInfo(info, i);
+            }
         } else {
-            this._attribution.hide();
+            let label = new Gtk.Label({ label: _("Forecast not available"),
+                                        use_markup: true,
+                                        visible: true });
+            this._grid.attach(label, 0, 0, 1, 1);
         }
     },
 
-    _addOneInfo: function(info, row) {
+    _addOneInfo: function(info, col) {
         let [ok, date] = info.get_value_update();
         let datetime = GLib.DateTime.new_from_unix_local(date);
 
@@ -321,104 +130,22 @@ const TodaySidebar = new Lang.Class({
             timeFormat = _("%R");
 
         let label = new Gtk.Label({ label: datetime.format(timeFormat),
-                                    visible: true,
-                                    xalign: 1.0 });
-        label.get_style_context().add_class('dim-label');
-        this._grid.attach(label, 0, row, 1, 1);
-        this._infoWidgets.push(label);
+                                    use_markup: true,
+                                    visible: true });
+        this._grid.attach(label, col, 0, 1, 1);
 
         let image = new Gtk.Image({ icon_name: info.get_symbolic_icon_name(),
-                                    icon_size: Gtk.IconSize.MENU,
+                                    pixel_size: 32,
                                     use_fallback: true,
                                     visible: true });
-        this._grid.attach(image, 1, row, 1, 1);
-        this._infoWidgets.push(image);
+        this._grid.attach(image, col, 1, 1, 1);
 
-        let conditions = new Gtk.Label({ label: Util.getWeatherConditions(info),
-                                         visible: true,
-                                         xalign: 0.0 });
-        this._grid.attach(conditions, 2, row, 1, 1);
-        this._infoWidgets.push(conditions);
+        let temperature = new Gtk.Label({ label: Util.getTemperature(info),
+                                          visible: true });
+        this._grid.attach(temperature, col, 2, 1, 1);
     },
 
-    _updateHeadline: function() {
-        // Show today if we have it
-
-        let date = GLib.DateTime.new_now_local();
-        if (this._tomorrow)
-            date = date.add_days(1);
-
-        if (this._tomorrow)
-            this._headline.label = '<b>' + _("Forecast for Tomorrow") + '</b>';
-        else
-            this._headline.label = '<b>' + _("Forecast for Today") + '</b>';
-
-        // Translators: this is the date format for the sidebar date
-        // It's a long date (explicit day name), relative to this week
-        this._subline.label = date.format(_("%B %d"));
-    },
-
-    _changeView: function() {
-        if (this._hasMore) {
-            this._hasMore = false;
-            this._grid.remove(this._moreButton);
-
-            let hasToday = this._trimmedToday.length > 0;
-            let hasTomorrow = this._trimmedTomorrow.length > 0;
-
-            let infos = hasToday ? this._trimmedToday : this._trimmedTomorrow;
-
-            let i;
-            for (i = this._trimmedIndex; i < infos.length; i++) {
-                let info = infos[i];
-                this._addOneInfo(info, i + 2);
-            }
-            this._trimmedIndex = i;
-
-            this._grid.attach(this._moreButton, 2, i+2, 1, 1);
-
-            if (hasToday && hasTomorrow) {
-                this._moreButton.show();
-                this._moreButton.label = _("Tomorrow");
-            } else {
-                this._moreButton.hide();
-            }
-        } else {
-            this.clear();
-
-            let hasToday = this._trimmedToday.length > 0;
-            let hasTomorrow = this._trimmedTomorrow.length > 0;
-            let infos;
-
-            if (this._tomorrow && hasToday) {
-                infos = this._trimmedToday;
-                this._tomorrow = false;
-            } else if (!this._tomorrow && hasTomorrow) {
-                infos = this._trimmedTomorrow;
-                this._tomorrow = true;
-            }
-            this._updateHeadline();
-
-            let i;
-            for (i = 0; i < infos.length; i++) {
-                let info = infos[i];
-                this._addOneInfo(info, i + 2);
-            }
-            this._trimmedIndex = i;
-
-            this._grid.attach(this._moreButton, 2, i+2, 1, 1);
-
-            if (hasToday && hasTomorrow) {
-                this._moreButton.show();
-
-                if (this._tomorrow)
-                    this._moreButton.label = _("Today");
-                else
-                    this._moreButton.label = _("Tomorrow");
-            } else {
-                this._moreButton.hide();
-            }
-
-        }
-    },
+    clear: function() {
+        this._grid.foreach(function(w) { w.destroy(); });
+    }
 });
diff --git a/src/app/main.js b/src/app/main.js
index 43ffc7a..0a87ca8 100644
--- a/src/app/main.js
+++ b/src/app/main.js
@@ -16,19 +16,15 @@
 // with Gnome Weather; if not, write to the Free Software Foundation,
 // Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-pkg.initSubmodule('libgd');
 pkg.initGettext();
 pkg.initFormat();
-pkg.require({ 'Gd': '1.0',
-              'Gdk': '3.0',
-              'GdkPixbuf': '2.0',
+pkg.require({ 'Gdk': '3.0',
               'Gio': '2.0',
               'GLib': '2.0',
               'GObject': '2.0',
               'Gtk': '3.0',
               'GWeather': '3.0' });
 
-const Gd = imports.gi.Gd;
 const Gdk = imports.gi.Gdk;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
@@ -91,7 +87,6 @@ const Application = new Lang.Class({
 
     vfunc_startup: function() {
         this.parent();
-        Gd.ensure_types();
 
         Util.loadStyleSheet('/org/gnome/Weather/Application/application.css');
 
@@ -100,7 +95,7 @@ const Application = new Lang.Class({
 
         this.world = GWeather.Location.get_world();
         this.model = new World.WorldModel(this.world, true);
-        this._currentLocationController = new 
CurrentLocationController.CurrentLocationController(this.model);
+        this.currentLocationController = new CurrentLocationController.CurrentLocationController(this.model);
 
         this.model.connect('notify::loading', Lang.bind(this, function() {
             if (this.model.loading)
@@ -120,7 +115,7 @@ const Application = new Lang.Class({
                           { name: 'new-location',
                             activate: this._onNewLocation }]);
 
-        let gwSettings = new Gio.Settings({ schema: 'org.gnome.GWeather' });
+        let gwSettings = new Gio.Settings({ schema_id: 'org.gnome.GWeather' });
         this.add_action(gwSettings.create_action('temperature-unit'));
 
         this._initAppMenu();
@@ -131,24 +126,42 @@ const Application = new Lang.Class({
 
     _createWindow: function() {
         let win = new Window.MainWindow({ application: this });
-
-        if (this.model.loading) {
-            let timeoutId, notifyId;
-            let model = this.model;
-
-            timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, function() {
-                log('Timeout during model load, perhaps the network is not available?');
-                model.disconnect(notifyId);
+        let notifyId;
+
+        if (!this.currentLocationController.autoLocation) {
+            if (this.model.loading) {
+                let timeoutId;
+                let model = this.model;
+
+                timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, function() {
+                    log('Timeout during model load, perhaps the network is not available?');
+                    model.disconnect(notifyId);
+                    win.show();
+                    return false;
+                });
+                notifyId = this.model.connect('notify::loading', function(model) {
+                    if (model.loading)
+                        return;
+
+                    model.disconnect(notifyId);
+                    GLib.source_remove(timeoutId);
+                    win.show();
+                });
+            } else {
                 win.show();
-                return false;
-            });
-            notifyId = this.model.connect('notify::loading', function(model) {
-                model.disconnect(notifyId);
-                GLib.source_remove(timeoutId);
-                win.show();
-            });
+            }
         } else {
-            win.show();
+            if (this.model.loading) {
+                notifyId = this.model.connect('notify::loading', Lang.bind(this, function(model) {
+                    if (model.loading)
+                        return;
+
+                    model.disconnect(notifyId);
+                    win.show();
+                }));
+            } else {
+                win.show();
+            }
         }
 
         return win;
diff --git a/src/app/weeklyForecast.js b/src/app/weeklyForecast.js
new file mode 100644
index 0000000..b135fa3
--- /dev/null
+++ b/src/app/weeklyForecast.js
@@ -0,0 +1,140 @@
+// -*- Mode: js; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*-
+//
+// Copyright (c) 2014 Saurabh Patel <srp201201051 gmail com>
+//
+// Gnome Weather is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2 of the License, or (at your
+// option) any later version.
+//
+// Gnome Weather is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with Gnome Weather; if not, write to the Free Software Foundation,
+// Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+
+const Params = imports.misc.params;
+const Strings = imports.shared.strings;
+const Util = imports.misc.util;
+
+const WeeklyForecastFrame = new Lang.Class({
+    Name: 'WeeklyForecastFrame',
+    Extends: Gtk.Frame,
+
+    _init: function(params) {
+        params = Params.fill(params, { shadow_type: Gtk.ShadowType.NONE,
+                                       name: _("weekly-forecast-frame"),
+                                       width_request: 220 });
+        this.parent(params);
+        this.get_accessible().accessible_name = _("WeeklyForecast");
+
+        this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.interface' });
+
+        this._grid = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL,
+                                    margin: 24,
+                                    valign: Gtk.Align.START,
+                                    halign: Gtk.Align.START,
+                                    row_spacing: 25,
+                                    row_homogeneous: true });
+
+        this.add(this._grid);
+    },
+
+    // get infos for the correct day
+    _preprocess: function(infos, day) {
+        let ret = [];
+        let i;
+
+        // First ignore all infos that are on a different
+        // older than day.
+        // infos are ordered by time, and it's assumed at some point
+        // there is an info for the day (otherwise, nothing
+        // is shown)
+        for (i = 0; i < infos.length; i++) {
+            let info = infos[i];
+
+            let [ok, date] = info.get_value_update();
+            let datetime = GLib.DateTime.new_from_unix_local(date);
+
+            if (Util.arrayEqual(day.get_ymd(), datetime.get_ymd())) {
+                break;
+            }
+        }
+
+        let infoCount = 0;
+        while (i < infos.length && infoCount < 5) {
+            let count = 0;
+            let temp = [];
+            for ( ; i < infos.length; i++) {
+                let info = infos[i];
+                let [ok, date] = info.get_value_update();
+                let datetime = GLib.DateTime.new_from_unix_local(date);
+
+                if (!Util.arrayEqual(day.get_ymd(),
+                                     datetime.get_ymd()))
+                    break;
+
+                temp[count++] = info;
+            }
+            if (count > 0)
+                ret.push(temp[Math.floor(count/2)]);
+            day = day.add_days(1);
+            infoCount++;
+        }
+        return ret;
+    },
+
+    update: function(infos) {
+        let day = GLib.DateTime.new_now_local();
+        day = day.add_days(2);
+
+        let weeklyInfo = this._preprocess(infos, day);
+        this.clear();
+
+        for (let i = 0; i < weeklyInfo.length; i++) {
+            let info = weeklyInfo[i];
+            let [ok, date] = info.get_value_update();
+            let datetime = GLib.DateTime.new_from_unix_local(date);
+
+            // Translators: this is the time format for full weekday name according to the current locale
+            let timeFormat = _("%A");
+
+            let grid = new Gtk.Grid({ orientation: Gtk.Orientation.HORIZONTAL,
+                                      row_spacing: 5,
+                                      column_spacing: 10 });
+
+            let label = new Gtk.Label({ label: datetime.format(timeFormat).bold(),
+                                        use_markup: true,
+                                        halign: Gtk.Align.START,
+                                        visible: true });
+            grid.attach(label, 0, 0, 2, 1);
+
+            let image = new Gtk.Image({ icon_name: info.get_symbolic_icon_name(),
+                                        icon_size: Gtk.IconSize.DIALOG,
+                                        use_fallback: true,
+                                        halign: Gtk.Align.START,
+                                        visible: true });
+            grid.attach(image, 0, 1, 1, 1);
+
+            let temperature = new Gtk.Label({ label: Util.getTemperature(info),
+                                              halign: Gtk.Align.START,
+                                              valign: Gtk.Align.START,
+                                              visible: true });
+            grid.attach(temperature, 1, 1, 1, 1);
+            grid.show();
+            this._grid.attach(grid, 0, i, 1, 1);
+        }
+    },
+
+    clear: function() {
+        this._grid.foreach(function(w) { w.destroy(); });
+    }
+});
diff --git a/src/app/window.js b/src/app/window.js
index 3838321..444635c 100644
--- a/src/app/window.js
+++ b/src/app/window.js
@@ -16,8 +16,6 @@
 // with Gnome Weather; if not, write to the Free Software Foundation,
 // Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-const GLib = imports.gi.GLib;
-const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const GWeather = imports.gi.GWeather;
 const Lang = imports.lang;
@@ -27,60 +25,11 @@ const Params = imports.misc.params;
 const World = imports.shared.world;
 const Util = imports.misc.util;
 
-const Gettext = imports.gettext;
-const Tweener = imports.tweener.tweener;
-
 const Page = {
     WORLD: 0,
     CITY: 1
 };
 
-const NewLocationController = new Lang.Class({
-    Name: 'NewLocationController',
-
-    _init: function(parentWindow, worldModel) {
-        this._worldModel = worldModel;
-
-        let builder = Util.loadUI('/org/gnome/Weather/Application/new-location-dialog.ui',
-                                  { 'parent-window': parentWindow });
-
-        let dialog = builder.get_object('location-dialog');
-        let entry = builder.get_object('location-entry');
-
-        dialog.add_button(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL);
-        dialog.add_button(Gtk.STOCK_ADD, Gtk.ResponseType.OK);
-        dialog.set_default_response(Gtk.ResponseType.OK);
-
-        dialog.connect('response', Lang.bind(this, this._onResponse));
-        entry.connect('notify::location', Lang.bind(this, this._locationChanged));
-
-        this._dialog = dialog;
-        this._entry = entry;
-    },
-
-    run: function() {
-        this._dialog.show();
-        this._locationChanged(this._entry);
-    },
-
-    _onResponse: function(dialog, response) {
-        dialog.destroy();
-
-        if (response != Gtk.ResponseType.OK)
-            return;
-
-        let location = this._entry.location;
-        if (!location)
-            return;
-
-        this._worldModel.addLocation(location, true);
-    },
-
-    _locationChanged: function(entry) {
-           this._dialog.set_response_sensitive(Gtk.ResponseType.OK, entry.location != null);
-    }
-});
-
 const MainWindow = new Lang.Class({
     Name: 'MainWindow',
     Extends: Gtk.ApplicationWindow,
@@ -96,24 +45,10 @@ const MainWindow = new Lang.Class({
         this._pageWidgets = [[],[]];
 
         Util.initActions(this,
-                         [{ name: 'new-location',
-                            activate: this._newLocation },
-                          { name: 'about',
+                         [{ name: 'about',
                             activate: this._showAbout },
                           { name: 'close',
                             activate: this._close },
-                          { name: 'selection-mode',
-                            activate: this._setSelectionMode,
-                            parameter_type: new GLib.VariantType('b'),
-                            state: new GLib.Variant('b', false) },
-                          { name: 'go-world',
-                            activate: this._goWorld },
-                          { name: 'select-all',
-                            activate: this._selectAll },
-                          { name: 'select-none',
-                            activate: this._selectNone },
-                          { name: 'delete-selected',
-                            activate: this._deleteSelected },
                           { name: 'refresh',
                             activate: this.update }]);
 
@@ -127,93 +62,46 @@ const MainWindow = new Lang.Class({
         this._header.title = title;
         this._header.subtitle = subtitle;
 
-        let newButton = builder.get_object('new-button');
-        this._pageWidgets[Page.WORLD].push(newButton);
+        this._worldView = new World.WorldContentView(this.application, { visible: true });
+        this._worldView.hide();
+
+        this._model = this._worldView.model;
+        this._model.connect('show-info', Lang.bind(this, function(model, info) {
+            this.showInfo(info);
+        }));
+        this._model.connect('no-cityview', Lang.bind(this, function() {
+            for (let i = 0; i < this._pageWidgets[Page.WORLD].length; i++)
+                this._pageWidgets[Page.WORLD][i].show_all();
+        }));
+
+        this._initialGrid = this._worldView.initialGrid;
+        this._pageWidgets[Page.WORLD].push(this._initialGrid);
 
-        let goWorldButton = builder.get_object('world-button');
-        this._pageWidgets[Page.CITY].push(goWorldButton);
+        let placesButton = builder.get_object('places-button');
+        this._pageWidgets[Page.CITY].push(placesButton);
 
-        let select = builder.get_object('select-button');
-        this._pageWidgets[Page.WORLD].push(select);
+        placesButton.set_popover(this._worldView);
 
         let refresh = builder.get_object('refresh-button');
         this._pageWidgets[Page.CITY].push(refresh);
 
-        let selectDone = builder.get_object('done-button');
-        this._pageWidgets[Page.WORLD].push(selectDone);
-
-        let selectionBar = builder.get_object('selection-bar');
-        let selectionMenu = builder.get_object("selection-menu");
-
-        this._selectionMenuButton = builder.get_object('selection-menu-button');
-        this._selectionMenuButtonLabel = builder.get_object('selection-menu-button-label');
         this._stack = builder.get_object('main-stack');
 
-        this._deleteButton = builder.get_object('delete-button');
-
         this._cityView = new City.WeatherView({ hexpand: true,
                                                 vexpand: true });
         this._stack.add(this._cityView);
 
-        this._worldView = new World.WorldContentView(this.application.model, { visible: true });
-        let iconView = this._worldView.iconView;
-        this._stack.add(this._worldView);
-
-        iconView.connect('item-activated', Lang.bind(this, this._itemActivated));
-
-        iconView.connect('notify::selection-mode', Lang.bind(this, function() {
-            if (iconView.selection_mode) {
-                this._header.get_style_context().add_class('selection-mode');
-                this._header.set_custom_title(this._selectionMenuButton);
-            } else {
-                this._header.get_style_context().remove_class('selection-mode');
-                this._header.set_custom_title(null);
-            }
+        this._stack.add(this._initialGrid);
 
-            let selectionState = new GLib.Variant('b', iconView.selection_mode);
-            this.lookup_action('selection-mode').set_state(selectionState);
-        }));
-
-        iconView.bind_property('selection-mode', newButton, 'visible',
-                               GObject.BindingFlags.INVERT_BOOLEAN);
-        iconView.bind_property('selection-mode', this._header, 'show-close-button',
-                               GObject.BindingFlags.INVERT_BOOLEAN);
-        iconView.bind_property('selection-mode', select, 'visible',
-                               GObject.BindingFlags.INVERT_BOOLEAN);
-        iconView.bind_property('selection-mode', selectDone, 'visible',
-                               GObject.BindingFlags.SYNC_CREATE);
-        iconView.bind_property('selection-mode', selectionBar, 'visible',
-                               GObject.BindingFlags.SYNC_CREATE);
-        this._worldView.bind_property('empty', this.lookup_action('selection-mode'), 'enabled',
-                                      GObject.BindingFlags.SYNC_CREATE |
-                                      GObject.BindingFlags.INVERT_BOOLEAN);
-
-        this._stack.set_visible_child(this._worldView);
-
-        iconView.connect('view-selection-changed', Lang.bind(this, function() {
-            let items = iconView.get_selection();
-            let label;
-            let sensitive;
-
-            if (items.length > 0) {
-                label = Gettext.ngettext("%d selected",
-                                         "%d selected",
-                                         items.length).format(items.length);
-                sensitive = true;
-            } else {
-                label = _("Click on locations to select them");
-                sensitive = false;
-            }
-
-            this._selectionMenuButtonLabel.label = label;
-            this._deleteButton.sensitive = sensitive;
-        }));
+        this._stack.set_visible_child(this._initialGrid);
 
         this.add(grid);
         grid.show_all();
 
         for (let i = 0; i < this._pageWidgets[Page.CITY].length; i++)
             this._pageWidgets[Page.CITY][i].hide();
+
+        this._model.fillCityView(this.application.currentLocationController.autoLocation);
     },
 
     update: function() {
@@ -222,7 +110,7 @@ const MainWindow = new Lang.Class({
 
     _getTitle: function() {
         if (this._currentPage == Page.WORLD)
-            return [_("World Weather"), null];
+            return [_("Select Location"), null];
 
         let location = this._cityView.info.location;
         let city = location;
@@ -241,9 +129,6 @@ const MainWindow = new Lang.Class({
     },
 
     _goToPage: function(page) {
-        if (page == this._currentPage)
-            return;
-
         for (let i = 0; i < this._pageWidgets[this._currentPage].length; i++)
             this._pageWidgets[this._currentPage][i].hide();
 
@@ -260,47 +145,24 @@ const MainWindow = new Lang.Class({
         this._header.subtitle = subtitle;
     },
 
-    _itemActivated: function(view, id, path) {
-        let [ok, iter] = view.model.get_iter(path);
-        let info = view.model.get_value(iter, World.Columns.INFO);
-
-        this.showInfo(info);
-    },
-
     showInfo: function(info) {
         this._cityView.info = info;
-        this._cityView.connectClock();
+        this._cityView.disconnectClock();
+        let isCurrentLocation = false;
+        let currentLocation = this.application.currentLocationController.currentLocation;
+        if (currentLocation) {
+            isCurrentLocation = currentLocation.get_timezone().get_tzid() == 
info.location.get_timezone().get_tzid();
+        }
+        if (isCurrentLocation) {
+            this._cityView.infoPage.timeGrid.hide();
+        } else {
+            this._cityView.connectClock();
+            this._cityView.infoPage.timeGrid.show();
+        }
         this._stack.set_visible_child(this._cityView);
         this._goToPage(Page.CITY);
     },
 
-    _goWorld: function() {
-        this._stack.set_visible_child(this._worldView);
-        this._goToPage(Page.WORLD);
-        this._cityView.disconnectClock();
-    },
-
-    _newLocation: function() {
-        let controller = new NewLocationController(this.get_toplevel(),
-                                                   this._worldView.model);
-
-        controller.run();
-    },
-
-    _setSelectionMode: function(action, param) {
-        this._worldView.iconView.selection_mode = param.get_boolean();
-        this._deleteButton.sensitive = false;
-    },
-
-    _selectAll: function() {
-        this._worldView.iconView.selection_mode = true;
-        this._worldView.iconView.select_all();
-    },
-
-    _selectNone: function() {
-        this._worldView.iconView.unselect_all();
-    },
-
     _showAbout: function() {
         let artists = [ 'Jakub Steiner <jimmac gmail com>',
                         'Pink Sherbet Photography (D. Sharon Pruitt)',
@@ -333,19 +195,6 @@ const MainWindow = new Lang.Class({
         });
     },
 
-    _deleteSelected: function() {
-        let items = this._worldView.iconView.get_selection();
-        let model = this._worldView.iconView.model;
-
-        for (let i = items.length - 1; i >= 0; i--) {
-            let [res, iter] = model.get_iter(items[i]);
-            if (res)
-                model.removeLocation(iter);
-        }
-
-        this._worldView.iconView.selection_mode = false;
-    },
-
     _close: function() {
         this.destroy();
     }
diff --git a/src/misc/util.js b/src/misc/util.js
index fc08e3f..73b37d2 100644
--- a/src/misc/util.js
+++ b/src/misc/util.js
@@ -29,6 +29,7 @@ const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const Gtk = imports.gi.Gtk;
 const System = imports.system;
+const GWeather = imports.gi.GWeather;
 
 const Params = imports.misc.params;
 
@@ -147,7 +148,25 @@ function normalizeCasefoldAndUnaccent(str) {
     return str.replace(/[\u0300-\u036f]|[\u1dc0-\u1dff]|[\u20d0-\u20ff]|[\ufe20-\ufe2f]/, '');
 }
 
-function assertEqual(one, two) {
-    if (one != two)
-        throw Error('Assertion failed: ' + one + ' != ' + two);
+function getTemperature(info) {
+    let [ok1, ] = info.get_value_temp_min(GWeather.TemperatureUnit.DEFAULT);
+    let [ok2, ] = info.get_value_temp_max(GWeather.TemperatureUnit.DEFAULT);
+
+    if (ok1 && ok2) {
+        // TRANSLATORS: this is the temperature string, minimum and maximum.
+        // The two values are already formatted, so it would be something like
+        // "7 °C / 19 °C"
+        return _("%s / %s").format(info.get_temp_min(), info.get_temp_max());
+    } else {
+        return info.get_temp_summary();
+    }
+}
+
+function getEnabledProviders() {
+    let provider_override = GLib.getenv('GWEATHER_DEBUG_BACKEND');
+    if (provider_override) {
+        return (GWeather.Provider.METAR | GWeather.Provider[provider_override]);
+    } else {
+        return (GWeather.Provider.METAR | GWeather.Provider.YR_NO | GWeather.Provider.OWM);
+    }
 }
diff --git a/src/org.gnome.Weather.Application.src.gresource.xml 
b/src/org.gnome.Weather.Application.src.gresource.xml
index 3e59a63..33a1ebe 100644
--- a/src/org.gnome.Weather.Application.src.gresource.xml
+++ b/src/org.gnome.Weather.Application.src.gresource.xml
@@ -4,6 +4,7 @@
     <file>app/city.js</file>
     <file>app/currentLocationController.js</file>
     <file>app/forecast.js</file>
+    <file>app/weeklyForecast.js</file>
     <file>app/main.js</file>
     <file>app/window.js</file>
     <file>misc/params.js</file>
diff --git a/src/shared/world.js b/src/shared/world.js
index 4c6861e..27e49b5 100644
--- a/src/shared/world.js
+++ b/src/shared/world.js
@@ -16,8 +16,6 @@
 // with Gnome Weather; if not, write to the Free Software Foundation,
 // Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-const Gd = imports.gi.Gd;
-const GdkPixbuf = imports.gi.GdkPixbuf;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
@@ -27,42 +25,22 @@ const Lang = imports.lang;
 const Params = imports.misc.params;
 const Util = imports.misc.util;
 
-const Columns = {
-    ID: Gd.MainColumns.ID,
-    URI: Gd.MainColumns.URI,
-    PRIMARY_TEXT: Gd.MainColumns.PRIMARY_TEXT,
-    SECONDARY_TEXT: Gd.MainColumns.SECONDARY_TEXT,
-    ICON: Gd.MainColumns.ICON,
-    MTIME: Gd.MainColumns.MTIME,
-    SELECTED: Gd.MainColumns.SELECTED,
-    PULSE: Gd.MainColumns.PULSE,
-    LOCATION: Gd.MainColumns.LAST,
-    INFO: Gd.MainColumns.LAST+1,
-    AUTOMATIC: Gd.MainColumns.LAST+2
-};
-const ColumnTypes = {
-    ID: String,
-    URI: String,
-    PRIMARY_TEXT: String,
-    SECONDARY_TEXT: String,
-    ICON: GdkPixbuf.Pixbuf,
-    MTIME: GObject.Int,
-    SELECTED: Boolean,
-    PULSE: GObject.UInt,
-    LOCATION: GWeather.Location,
-    INFO: GWeather.Info,
-    AUTOMATIC: Boolean
-};
-Util.assertEqual(Object.keys(Columns).length, Object.keys(ColumnTypes).length);
-Util.assertEqual(Gd.MainColumns.LAST+3, Object.keys(ColumnTypes).length);
-
-const ICON_SIZE = 128;
+function getLabelFromRow(row) {
+    let grid = row.get_child();
+    let cityGrid = grid.get_child_at(0, 0);
+    let label = cityGrid.get_child_at(0, 0);
+    return label.get_text();
+}
 
 const WorldModel = new Lang.Class({
     Name: 'WorldModel',
-    Extends: Gtk.ListStore,
+    Extends: GObject.Object,
     Signals: {
-        'updated': { param_types: [ GWeather.Info ] }
+        'updated': { param_types: [ GWeather.Info ] },
+        'no-cityview': { param_types: [] },
+        'show-info': { param_types: [ GWeather.Info ] },
+        'current-location-changed': { param_types: [ GWeather.Location ] },
+        'validate-listbox': { param_types: [ GWeather.Location ] }
     },
     Properties: {
         'loading': GObject.ParamSpec.boolean('loading', '', '', GObject.ParamFlags.READABLE, false)
@@ -70,31 +48,100 @@ const WorldModel = new Lang.Class({
 
     _init: function(world, enableGtk) {
         this.parent();
-        this.set_column_types([ColumnTypes[c] for (c in ColumnTypes)]);
+
         this._world = world;
 
         this._settings = Util.getSettings('org.gnome.Weather.Application');
 
-        let provider_override = GLib.getenv('GWEATHER_DEBUG_BACKEND');
-        if (provider_override) {
-            this._providers = GWeather.Provider.METAR | GWeather.Provider[provider_override];
-        } else {
-            this._providers = GWeather.Provider.METAR | GWeather.Provider.YR_NO |
-                GWeather.Provider.OWM;
-        }
+        this._providers = Util.getEnabledProviders();
 
         this._loadingCount = 0;
 
+        this._infoList = [];
+
+        this._enableGtk = enableGtk;
+
+        this._currentLocationInfo = null;
+
+        this.currentlyLoadedInfo = null;
+
+        this.addedCurrentLocation = false;
+    },
+
+    currentLocationChanged: function(location) {
+        if (location) {
+            this._newCurrentLocationInfo = new GWeather.Info({ location: location,
+                                                               enabled_providers: this._providers });
+            if (this._currentLocationInfo) {
+                if (!this._currentLocationInfo.location.equal(location)) {
+                    this._newCurrentLocationInfo.connect('updated', Lang.bind(this, function(info) {
+                        this._updateLoadingCount(-1);
+                        this.emit('updated', this._newCurrentLocationInfo);
+                    }));
+                    this.updateInfo(this._newCurrentLocationInfo);
+                    this._currentLocationInfo = this._newCurrentLocationInfo;
+                }
+            } else {
+                this._newCurrentLocationInfo.connect('updated', Lang.bind(this, function(info) {
+                    this._updateLoadingCount(-1);
+                    this.emit('updated', this._newCurrentLocationInfo);
+                }));
+                this.updateInfo(this._newCurrentLocationInfo);
+                this._currentLocationInfo = this._newCurrentLocationInfo;
+            }
+        }
+
+        this.emit('current-location-changed', location);
+    },
+
+    rowActivated: function(listbox, row) {
+        let cityName = getLabelFromRow(row);
+        this.emit('show-info', this._infoList[cityName]);
+        this.currentlyLoadedInfo = this._infoList[cityName];
+        this.emit('validate-listbox', this.currentlyLoadedInfo.location);
+    },
+
+    showRecent: function(listbox) {
+        let row = listbox.get_row_at_index(0);
+        if (row) {
+            this.rowActivated(null, row);
+            return;
+        } else
+            this.emit('no-cityview');
+    },
+
+    _showCurrentLocation: function() {
+        if (this._currentLocationInfo) {
+            this.emit('show-info', this._currentLocationInfo);
+            this.currentlyLoadedInfo = this._currentLocationInfo;
+        }
+    },
+
+    fillListbox: function (listbox) {
         let locations = this._settings.get_value('locations').deep_unpack();
-        for (let i = 0; i < locations.length; i++) {
-            let variant = locations[i];
-            let location = this._world.deserialize(variant);
-            this._addLocationInternal(location, false);
+        if (locations.length != 0) {
+            for (let i = 0; i < locations.length && i < 5; i++) {
+                let variant = locations[i];
+                let location = this._world.deserialize(variant);
+                this._addLocationInternal(location, listbox, false);
+            }
         }
+    },
 
-        this._settings.connect('changed::locations', Lang.bind(this, this._onChanged));
+    fillCityView: function(autoLocation) {
+        let locations = this._settings.get_value('locations').deep_unpack();
 
-        this._enableGtk = enableGtk;
+        if (!autoLocation) {
+            if (locations.length > 0) {
+                let variant = locations[locations.length-1];
+                let location = this._world.deserialize(variant);
+                this.emit('show-info', this._infoList[location.get_city_name()]);
+                this.currentlyLoadedInfo = this._infoList[location.get_city_name()];
+                this.emit('validate-listbox', this.currentlyLoadedInfo.location);
+            } else {
+                this.emit('no-cityview');
+            }
+        }
     },
 
     _updateLoadingCount: function(delta) {
@@ -115,265 +162,245 @@ const WorldModel = new Lang.Class({
         return this._loadingCount > 0;
     },
 
-    _addLocationInternal: function(location, automatic) {
+    _addLocationInternal: function(location, listbox, isCurrentLocation) {
+        let grid = new Gtk.Grid({ orientation: Gtk.Orientation.HORIZONTAL,
+                                  column_spacing: 12,
+                                  margin: 12 });
+
+        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 });
+        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 });
+        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 });
+            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 });
+        grid.attach(image, 2, 0, 1, 1);
+
+        grid.show();
+        if(isCurrentLocation) {
+            if (this.addedCurrentLocation) {
+                let children = listbox.get_children();
+                children[0].destroy();
+            }
+            listbox.insert(grid, 0);
+        } else {
+            if (this.addedCurrentLocation)
+                listbox.insert(grid, 1);
+            else
+                listbox.insert(grid, 0);
+        }
+
         let info = new GWeather.Info({ location: location,
                                        enabled_providers: this._providers });
-        let iter;
+
+        this._infoList[locationLabel.get_label()] = info;
+
         info.connect('updated', Lang.bind(this, function(info) {
-            let secondary_text = Util.getWeatherConditions(info);
-            if (this._enableGtk) {
-                let icon = Util.loadIcon(info.get_symbolic_icon_name(), ICON_SIZE);
-                this.set(iter,
-                         [Columns.ICON, Columns.SECONDARY_TEXT],
-                         [icon, secondary_text]);
-            } else {
-                this.set_value(iter, Columns.SECONDARY_TEXT, secondary_text);
-            }
+            tempLabel.label = info.get_temp_summary();
+            image.icon_name = info.get_symbolic_icon_name();
 
             this._updateLoadingCount(-1);
             this.emit('updated', info);
         }));
         this.updateInfo(info);
-
-        let primary_text = location.get_city_name();
-
-        iter = this.insert_with_valuesv(-1,
-                                        [Columns.PRIMARY_TEXT,
-                                         Columns.LOCATION,
-                                         Columns.INFO,
-                                         Columns.AUTOMATIC],
-                                        [primary_text,
-                                         location,
-                                         info,
-                                         automatic]);
-
-        if (this._enableGtk) {
-            let icon = Util.loadIcon('view-refresh-symbolic', ICON_SIZE);
-            this.set_value(iter, Columns.ICON, icon);
-        }
     },
 
-    _onChanged: function() {
-        let newLocations = this._settings.get_value('locations').deep_unpack();
-        let toErase = [];
+    addNewLocation: function(newLocation, listbox, isCurrentLocation) {
+        if (newLocation) {
+            let locations = this._settings.get_value('locations').deep_unpack();
+
+            if (!isCurrentLocation) {
+                for (let i = 0; i < locations.length; i++) {
+                    let location = this._world.deserialize(locations[i]);
+                    if (location.equal(newLocation)) {
+                        this.emit('show-info', this._infoList[location.get_city_name()]);
+                        this.currentlyLoadedInfo = this._infoList[location.get_city_name()];
+                        this.emit('validate-listbox', this.currentlyLoadedInfo.location);
+                        return;
+                    }
+                }
 
-        let [ok, iter] = this.get_iter_first();
-        while (ok) {
-            let auto = this.get_value(iter, Columns.AUTOMATIC);
-            if (auto) {
-                ok = this.iter_next(iter);
-                continue;
-            }
-            let location = this.get_value(iter, Columns.LOCATION);
+                locations.push(newLocation.serialize());
 
-            let found = false;
-            for (let j = 0; j < newLocations.length; j++) {
-                let variant = newLocations[j];
-                if (variant == null)
-                    continue;
+                if (locations.length > 5) {
+                    let children = listbox.get_children();
+                    children[children.length-1].destroy();
+                }
 
-                let newLocation = this._world.deserialize(variant);
+                this._settings.set_value('locations', new GLib.Variant('av', locations));
+            }
 
-                if (location.equal(newLocation)) {
-                    newLocations[j] = null;
-                    found = true;
-                    break;
+            this._addLocationInternal(newLocation, listbox, isCurrentLocation);
+            if (!isCurrentLocation) {
+                this.emit('show-info', this._infoList[newLocation.get_city_name()]);
+                this.currentlyLoadedInfo = this._infoList[newLocation.get_city_name()];
+                this.emit('validate-listbox', this.currentlyLoadedInfo.location);
+            }
+            else {
+                if(!this.addedCurrentLocation) {
+                    this.emit('show-info', this._currentLocationInfo);
+                    this.currentlyLoadedInfo = this._currentLocationInfo;
+                    this.emit('validate-listbox', this.currentlyLoadedInfo.location);
                 }
+                this.addedCurrentLocation = true;
             }
+        }
+    }
+});
 
-            if (!found)
-                toErase.push(iter.copy());
+const WorldContentView = new Lang.Class({
+    Name: 'WorldContentView',
+    Extends: Gtk.Popover,
 
-            ok = this.iter_next(iter);
-        }
+    _init: function(application, params) {
+        params = Params.fill(params, { hexpand: false, vexpand: false });
+        this.parent(params);
 
-        for (let i = 0; i < toErase.length; i++)
-            this.remove(toErase[i]);
+        this.get_accessible().accessible_name = _("World view");
 
-        for (let i = 0; i < newLocations.length; i++) {
-            let variant = newLocations[i];
-            if (variant == null)
-                continue;
+        let builder = new Gtk.Builder();
+        builder.add_from_resource('/org/gnome/Weather/Application/places-popover.ui');
 
-            let newLocation = this._world.deserialize(variant);
-            this._addLocationInternal(newLocation, false);
-        }
-    },
+        let grid = builder.get_object('popover-grid');
+        this.add(grid);
 
-    _addSavedLocation: function(location) {
-        let newLocations = this._settings.get_value('locations').deep_unpack();
-        newLocations.push(location.serialize());
-        this._settings.set_value('locations', new GLib.Variant('av', newLocations));
-    },
+        this.initialGrid = builder.get_object('initial-grid');
 
-    getAllSavedLocations: function() {
-        let locations = this._settings.get_value('locations').deep_unpack();
-        let returnValue = [];
+        let stackPopover = builder.get_object('popover-stack');
+
+        this.model = application.model;
 
-        for (let i = 0; i < locations.length; i++) {
-            let variant = locations[i];
-            if (variant == null) {
-                log('null stored in GSettings?');
-                continue;
+        let listbox = builder.get_object('locations-list-box');
+        listbox.set_header_func(function (row, previous) {
+            let hasHeader = row.get_header() != null;
+            let shouldHaveHeader = previous != null;
+            if (hasHeader != shouldHaveHeader) {
+                if (shouldHaveHeader)
+                    row.set_header(new Gtk.Separator());
+                else
+                    row.set_header(null);
             }
+        });
 
-            returnValue.push(this._world.deserialize(variant));
-        }
+        let initialGridLocEntry = builder.get_object('initial-grid-location-entry');
+        initialGridLocEntry.connect('notify::location', Lang.bind(this, function(entry) {
+            this._locationChanged(entry, listbox);
+        }));
 
-        return returnValue;
-    },
+        let locationEntry = builder.get_object('location-entry');
+        locationEntry.connect('notify::location', Lang.bind(this, function(entry) {
+            this._locationChanged(entry, listbox)
+        }));
 
-    getLocationInfo: function(location) {
-        let [ok, iter] = this.get_iter_first();
-        while (ok) {
-            let storedLocation = this.get_value(iter, Columns.LOCATION);
-            if (storedLocation.equal(location))
-                return this.get_value(iter, Columns.INFO);
+        this.model.fillListbox(listbox);
 
-            ok = this.iter_next(iter);
-        }
+        this.connect('notify::visible', Lang.bind(this, function() {
+            listbox.set_selection_mode(0);
+            locationEntry.grab_focus();
+            listbox.set_selection_mode(1);
+        }));
 
-        return null;
-    },
+        let autoLocStack = builder.get_object('auto-location-stack');
 
-    addLocation: function(location, saved) {
-        if (saved)
-            this._addSavedLocation(location);
-        else
-            this._addLocationInternal(location, true);
-    },
+        let autoLocSwitch = builder.get_object('auto-location-switch');
 
-    removeLocation: function(iter) {
-        let auto = this.get_value(iter, Columns.AUTOMATIC);
-        if (auto) {
-            this.remove(iter);
-            return;
-        }
+        let currentLocationController = application.currentLocationController;
 
-        let location = this.get_value(iter, Columns.LOCATION);
-        let variant = location.serialize();
+        let handlerId = autoLocSwitch.connect('notify::active', Lang.bind(this, function() {
+            currentLocationController.setAutoLocation(autoLocSwitch.get_active());
 
-        let newLocations = this._settings.get_value('locations').deep_unpack();
+            if (autoLocSwitch.get_active() && !this.model.addedCurrentLocation)
+                autoLocStack.set_visible_child_name('locating-label');
 
-        for (let i = 0; i < newLocations.length; i++) {
-            if (newLocations[i].equal(variant)) {
-                newLocations.splice(i, 1);
-                break;
-            }
-        }
+            this.hide();
+        }));
 
-        this._settings.set_value('locations', new GLib.Variant('av', newLocations));
-    },
-});
+        if(currentLocationController.autoLocation)
+            autoLocStack.set_visible_child_name('locating-label');
+        else {
+            autoLocStack.set_visible_child_name('auto-location-switch-grid');
+            GObject.signal_handler_block(autoLocSwitch, handlerId);
+            autoLocSwitch.set_active(false);
+            GObject.signal_handler_unblock(autoLocSwitch, handlerId);
+        }
 
-const WorldIconView = new Lang.Class({
-    Name: 'WorldView',
-    Extends: Gd.MainView,
+        listbox.connect('row-activated', Lang.bind(this, function(listbox, row) {
+            this.hide();
+            this.model.rowActivated(listbox, row);
+        }));
 
-    _init: function(params) {
-        params = Params.fill(params, { view_type: Gd.MainViewType.ICON });
-        this.parent(params);
-        this.get_accessible().accessible_name = _("Cities");
+        this.model.connect('current-location-changed', Lang.bind(this, function(model, location) {
+            autoLocStack.set_visible_child_name('auto-location-switch-grid');
+            if (location) {
+                this.model.addNewLocation(location, listbox, true);
 
-        this.connect('selection-mode-request', Lang.bind(this, function() {
-            this.selection_mode = true;
-        }));
-    }
-});
+                GObject.signal_handler_block(autoLocSwitch, handlerId);
+                autoLocSwitch.set_active(true);
+                GObject.signal_handler_unblock(autoLocSwitch, handlerId);
+            } else {
+                if (!this.model.addedCurrentLocation)
+                    this.model.showRecent(listbox);
 
-const WorldContentView = new Lang.Class({
-    Name: 'WorldContentView',
-    Extends: Gtk.Bin,
-    Properties: { 'empty': GObject.ParamSpec.boolean('empty', '', '', GObject.ParamFlags.READABLE, false) },
+                GObject.signal_handler_block(autoLocSwitch, handlerId);
+                autoLocSwitch.set_active(false);
+                GObject.signal_handler_unblock(autoLocSwitch, handlerId);
 
-    _init: function(model, params) {
-        params = Params.fill(params, { hexpand: true, vexpand: true,
-                                       halign: Gtk.Align.FILL, valign: Gtk.Align.FILL });
-        this.parent(params);
-        this.get_accessible().accessible_name = _("World view");
+                autoLocSwitch.set_sensitive(false);
+            }
+        }));
 
-        this.iconView = new WorldIconView({ model: model, visible: true });
-
-        this._placeHolder = new Gtk.Grid({ halign: Gtk.Align.CENTER,
-                                           valign: Gtk.Align.CENTER,
-                                           name: 'weather-page-placeholder',
-                                           column_spacing: 6 });
-        this._placeHolder.get_style_context().add_class('dim-label');
-
-        let iconGrid = new Gtk.Grid({ row_spacing: 4, column_spacing: 4,
-                                      valign: Gtk.Align.CENTER });
-        iconGrid.attach(new Gtk.Image({ icon_name: 'weather-overcast-symbolic',
-                                        icon_size: Gtk.IconSize.LARGE_TOOLBAR }),
-                        0, 0, 1, 1);
-        iconGrid.attach(new Gtk.Image({ icon_name: 'weather-few-clouds-symbolic',
-                                        icon_size: Gtk.IconSize.LARGE_TOOLBAR }),
-                        1, 0, 1, 1);
-        iconGrid.attach(new Gtk.Image({ icon_name: 'weather-clear-symbolic',
-                                        icon_size: Gtk.IconSize.LARGE_TOOLBAR }),
-                        0, 1, 1, 1);
-        iconGrid.attach(new Gtk.Image({ icon_name: 'weather-showers-symbolic',
-                                        icon_size: Gtk.IconSize.LARGE_TOOLBAR }),
-                        1, 1, 1, 1);
-
-        this._placeHolder.attach(iconGrid, 0, 0, 1, 2);
-
-        this._placeHolder.attach(new Gtk.Label({ name: 'weather-page-placeholder-title',
-                                                 label: _("Add locations"),
-                                                 xalign: 0.0 }),
-                                 1, 0, 1, 1);
-        this._placeHolder.attach(new Gtk.Label({ label: _("Use the <b>New</b> button on the toolbar to add 
more world locations"),
-                                                 use_markup: true,
-                                                 max_width_chars: 30,
-                                                 wrap: true,
-                                                 xalign: 0.0,
-                                                 halign: Gtk.Align.START,
-                                                 valign: Gtk.Align.START }),
-                                 1, 1, 1, 1);
-        this._placeHolder.show_all();
-
-        this.model = model;
-        this._rowInsertedId = model.connect('row-inserted', Lang.bind(this, this._updateEmpty));
-        this._rowDeletedId = model.connect('row-deleted', Lang.bind(this, this._updateEmpty));
-
-        let [ok, ] = model.get_iter_first();
-        if (ok)
-            this.add(this.iconView);
-        else
-            this.add(this._placeHolder);
-        this._empty = !ok;
-
-        this.connect('destroy', Lang.bind(this, this._onDestroy));
-    },
+        this.model.connect('validate-listbox', Lang.bind(this, function() {
+            listbox.invalidate_filter();
+            let children = listbox.get_children();
+            if (children.length == 1) {
+                stackPopover.set_visible_child_name("search-grid");
+                return;
+            }
+            stackPopover.set_visible_child_name("locations-grid");
+        }));
 
-    get empty() {
-        return this._empty;
+        listbox.set_filter_func(Lang.bind(this, this._filterListbox, this.model));
     },
 
-    _onDestroy: function() {
-        if (this._rowInsertedId) {
-            this.model.disconnect(this._rowInsertedId);
-            this._rowInsertedId = 0;
-        }
-        if (this._rowDeletedId) {
-            this.model.disconnect(this._rowDeletedId);
-            this._rowDeletedId = 0;
+    _filterListbox: function(row, model) {
+        if(model.currentlyLoadedInfo) {
+            let cityName = getLabelFromRow(row);
+            let loadedCity = model.currentlyLoadedInfo.location.get_city_name();
+            return (cityName != loadedCity);
         }
+        return true;
     },
 
-    _updateEmpty: function() {
-        let [ok, iter] = this.model.get_iter_first();
-
-        if (!ok != this._empty) {
-            if (ok) {
-                this.remove(this._placeHolder);
-                this.add(this.iconView);
-            } else {
-                this.remove(this.iconView);
-                this.add(this._placeHolder);
-            }
-
-            this._empty = !ok;
-            this.notify('empty');
+    _locationChanged: function(entry, listbox) {
+        if (entry.location) {
+            this.model.addNewLocation(entry.location, listbox, false);
+            this.hide();
+            entry.location = null;
         }
     }
 });


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