[seahorse/wip/nielsdg/adaptive: 2/3] Initial steps towards an adaptive UI



commit aac4145d1177a99c6a9ebe0657289ce1ca7e9048
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Tue Jan 28 22:01:41 2020 +0100

    Initial steps towards an adaptive UI
    
    We use Purism's `libhandy` for this. Since some distro's might not have
    the version we need, we also add a meson subproject (backed by a git
    submodule).

 .gitmodules                       |   3 +
 build-aux/org.gnome.Seahorse.json |  15 ++
 libseahorse/seahorse.css          |   7 -
 meson.build                       |  19 +++
 src/key-manager.vala              |  56 +++++++-
 src/main.vala                     |   2 +
 src/meson.build                   |   6 +
 src/seahorse-key-manager.ui       | 293 ++++++++++++++++++++++++++------------
 src/sidebar.vala                  |  23 +--
 subprojects/libhandy              |   1 +
 10 files changed, 313 insertions(+), 112 deletions(-)
---
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..f4788ba4
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "subprojects/libhandy"]
+       path = subprojects/libhandy
+       url = https://source.puri.sm/Librem5/libhandy.git
diff --git a/build-aux/org.gnome.Seahorse.json b/build-aux/org.gnome.Seahorse.json
index 334b5ca7..ee0a2b41 100644
--- a/build-aux/org.gnome.Seahorse.json
+++ b/build-aux/org.gnome.Seahorse.json
@@ -123,6 +123,21 @@
                 }
             ]
         },
+        {
+            "name": "libhandy",
+            "buildsystem": "meson",
+            "builddir": true,
+            "config-opts": [
+                "-Dglade_catalog=disabled"
+            ],
+            "sources": [
+                {
+                    "type": "git",
+                    "url": "https://source.puri.sm/Librem5/libhandy.git";,
+                    "branch": "libhandy-0-0"
+               }
+            ]
+        },
         {
             "name": "seahorse",
             "buildsystem": "meson",
diff --git a/libseahorse/seahorse.css b/libseahorse/seahorse.css
index e0dfcbc7..1de94e86 100644
--- a/libseahorse/seahorse.css
+++ b/libseahorse/seahorse.css
@@ -1,10 +1,3 @@
-.sidebar {
-    border-width: 1px 0 0 0;
-    border-style: solid;
-    border-color: shade (@theme_bg_color, 0.66);
-    border-radius: 0;
-}
-
 .seahorse-sidebar-item-header {
   margin-top: 6px;
   font-weight: bold;
diff --git a/meson.build b/meson.build
index d2e2f111..8347f31a 100644
--- a/meson.build
+++ b/meson.build
@@ -49,6 +49,25 @@ glib_deps = [
   dependency('gmodule-2.0', version: '>=' + min_glib_version),
 ]
 gtk = dependency('gtk+-3.0', version: '>= 3.22.0')
+libhandy_dep = dependency('libhandy-0.0', version: '>= 0.0.12', required: false)
+if not libhandy_dep.found()
+  libhandy_subproj = subproject(
+    'libhandy',
+    default_options: [
+      'examples=false',
+      'glade_catalog=disabled',
+      'tests=false',
+    ]
+  )
+
+  # Make sure to also get the VAPI file
+  libhandy_dep = declare_dependency(
+    dependencies: [
+      libhandy_subproj.get_variable('libhandy_dep'),
+      libhandy_subproj.get_variable('libhandy_vapi'),
+    ]
+  )
+endif
 gcr = dependency('gcr-3',       version: '>=' + min_gcr_version)
 gcr_ui = dependency('gcr-ui-3', version: '>=' + min_gcr_version)
 libsecret = dependency('libsecret-1', version: '>= 0.16')
diff --git a/src/key-manager.vala b/src/key-manager.vala
index 9049bbe1..95e6fb5a 100644
--- a/src/key-manager.vala
+++ b/src/key-manager.vala
@@ -23,13 +23,22 @@
 [GtkTemplate (ui = "/org/gnome/Seahorse/seahorse-key-manager.ui")]
 public class Seahorse.KeyManager : Catalog {
 
+    [GtkChild]
+    private Hdy.Leaflet header;
+    [GtkChild]
+    private Gtk.HeaderBar left_header;
+    [GtkChild]
+    private Gtk.HeaderBar right_header;
+    [GtkChild]
+    private Gtk.Revealer back_revealer;
+
     [GtkChild]
     private Gtk.SearchBar search_bar;
     [GtkChild]
     private Gtk.SearchEntry filter_entry;
 
     [GtkChild]
-    private Gtk.Paned sidebar_panes;
+    private Hdy.Leaflet content_box;
     [GtkChild]
     private Gtk.ScrolledWindow sidebar_area;
     private Sidebar sidebar;
@@ -230,6 +239,39 @@ public class Seahorse.KeyManager : Catalog {
         this.item_list.filter_text = this.filter_entry.text;
     }
 
+    [GtkCallback]
+    private void on_back_clicked() {
+        show_sidebar_pane();
+    }
+
+    private void show_sidebar_pane() {
+        this.content_box.visible_child_name = "sidebar-pane";
+        update_header();
+    }
+
+    private void show_item_list_pane() {
+        this.content_box.visible_child_name = "item-list-pane";
+        update_header();
+    }
+
+    [GtkCallback]
+    private void on_fold () {
+        update_header();
+    }
+
+    private void update_header() {
+        bool folded = this.content_box.fold == Hdy.Fold.FOLDED;
+
+        this.left_header.show_close_button =
+            !folded || header.visible_child == left_header;
+
+        this.right_header.show_close_button =
+            !folded || header.visible_child == right_header;
+
+        this.back_revealer.reveal_child = this.back_revealer.visible =
+            folded && header.visible_child == right_header;
+    }
+
     public void import_files(string[]? uris) {
         ImportDialog dialog = new ImportDialog(this);
         dialog.add_uris(uris);
@@ -387,16 +429,11 @@ public class Seahorse.KeyManager : Catalog {
 
     private Gcr.Collection setup_sidebar() {
         this.sidebar = new Sidebar();
-        sidebar.hexpand = true;
 
         /* Make sure we update the empty state on any change */
         this.sidebar.selected_rows_changed.connect(on_sidebar_selected_rows_changed);
         this.sidebar.current_collection_changed.connect((sidebar) => { check_empty_state (); });
 
-        this.sidebar_panes.position = this.settings.get_int("sidebar-width");
-        this.sidebar_panes.realize.connect(() =>   { this.sidebar_panes.position = 
this.settings.get_int("sidebar-width"); });
-        this.sidebar_panes.unrealize.connect(() => { this.settings.set_int("sidebar-width", 
this.sidebar_panes.position);  });
-
         foreach (weak Backend backend in get_backends()) {
             ActionGroup actions = backend.actions;
             actions.catalog = this;
@@ -411,6 +448,13 @@ public class Seahorse.KeyManager : Catalog {
 
     private void on_sidebar_selected_rows_changed(Gtk.ListBox sidebar) {
         check_empty_state();
+
+        show_item_list_pane();
+
+        Place? place = this.sidebar.get_focused_place();
+        if (place != null)
+            this.right_header.title = place.label;
+
         // FIXME
         //this.settings.set_strv("keyrings-selected", );
     }
diff --git a/src/main.vala b/src/main.vala
index 96d1f9f0..49bb1bb0 100644
--- a/src/main.vala
+++ b/src/main.vala
@@ -24,6 +24,8 @@ public int main (string[] args) {
     Intl.bind_textdomain_codeset(Config.GETTEXT_PACKAGE, "UTF-8");
     Intl.textdomain(Config.GETTEXT_PACKAGE);
 
+    Hdy.init (ref args);
+
     Seahorse.Application app = new Seahorse.Application();
     int status = app.run(args);
 
diff --git a/src/meson.build b/src/meson.build
index 6d07c18c..dea58a3d 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -20,6 +20,7 @@ seahorse_sources = [
 seahorse_dependencies = [
   glib_deps,
   gtk,
+  libhandy_dep,
   libsecret,
   common_dep,
   libseahorse_dep,
@@ -32,6 +33,10 @@ seahorse_linkedlibs = [
   libtreemultidnd_lib,
 ]
 
+seahorse_c_flags = [
+  '-DHANDY_USE_UNSTABLE_API',
+]
+
 seahorse_vala_flags = [
 ]
 
@@ -49,6 +54,7 @@ seahorse_exe = executable('seahorse',
   seahorse_sources,
   dependencies: seahorse_dependencies,
   vala_args: seahorse_vala_flags,
+  c_args: seahorse_c_flags,
   link_with: seahorse_linkedlibs,
   install: true,
 )
diff --git a/src/seahorse-key-manager.ui b/src/seahorse-key-manager.ui
index 664f2b73..d201e253 100644
--- a/src/seahorse-key-manager.ui
+++ b/src/seahorse-key-manager.ui
@@ -2,30 +2,6 @@
 <interface>
   <requires lib="gtk+" version="3.22"/>
   <menu id="main_menu">
-    <section>
-      <attribute name="label" translatable="yes">Filter items:</attribute>
-      <item>
-        <attribute name="label" translatable="yes">Show p_ersonal</attribute>
-        <attribute name="action">win.filter-items</attribute>
-        <attribute name="target">personal</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">Show _trusted</attribute>
-        <attribute name="action">win.filter-items</attribute>
-        <attribute name="target">trusted</attribute>
-      </item>
-      <item>
-        <attribute name="label" translatable="yes">Show an_y</attribute>
-        <attribute name="action">win.filter-items</attribute>
-        <attribute name="target">any</attribute>
-      </item>
-    </section>
-    <section>
-      <item>
-        <attribute name="label" translatable="yes">_Combine all keyrings</attribute>
-        <attribute name="action">win.combine-keyrings</attribute>
-      </item>
-    </section>
     <section>
       <item>
         <attribute name="label" translatable="yes">_Find remote keys…</attribute>
@@ -54,6 +30,34 @@
       </item>
     </section>
   </menu>
+
+  <menu id="items_menu">
+    <section>
+      <attribute name="label" translatable="yes">Filter items:</attribute>
+      <item>
+        <attribute name="label" translatable="yes">Show p_ersonal</attribute>
+        <attribute name="action">win.filter-items</attribute>
+        <attribute name="target">personal</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Show _trusted</attribute>
+        <attribute name="action">win.filter-items</attribute>
+        <attribute name="target">trusted</attribute>
+      </item>
+      <item>
+        <attribute name="label" translatable="yes">Show an_y</attribute>
+        <attribute name="action">win.filter-items</attribute>
+        <attribute name="target">any</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
+        <attribute name="label" translatable="yes">_Combine all keyrings</attribute>
+        <attribute name="action">win.combine-keyrings</attribute>
+      </item>
+    </section>
+  </menu>
+
   <object class="GtkPopover" id="new_item_menu_popover">
     <signal name="grab-notify" handler="on_popover_grab_notify" after="yes"/>
     <child>
@@ -265,88 +269,190 @@
       </object>
     </child>
   </object>
+
   <template class="SeahorseKeyManager" parent="SeahorseCatalog">
     <property name="default-width">600</property>
     <property name="default-height">476</property>
     <signal name="drag-data-received" handler="on_drag_data_received" />
     <signal name="key-press-event" handler="on_key_pressed"/>
     <child type="titlebar">
-      <object class="GtkHeaderBar">
+      <object class="HdyTitleBar" id="titlebar">
         <property name="visible">True</property>
-        <property name="show-close-button">True</property>
-        <property name="title" translatable="yes">Passwords and Keys</property>
         <child>
-          <object class="GtkMenuButton" id="new_item_button">
+          <object class="HdyLeaflet" id="header">
             <property name="visible">True</property>
-            <property name="hexpand">True</property>
-            <property name="halign">start</property>
-            <property name="tooltip_text" translatable="yes">Add a new key or item</property>
-            <property name="popover">new_item_menu_popover</property>
+            <property name="can_focus">False</property>
+            <property name="mode-transition-duration" bind-source="content_box" 
bind-property="mode-transition-duration" bind-flags="bidirectional|sync-create"/>
+            <property name="child-transition-duration" bind-source="content_box" 
bind-property="child-transition-duration" bind-flags="bidirectional|sync-create"/>
+            <property name="transition-type" bind-source="content_box" bind-property="transition-type" 
bind-flags="bidirectional|sync-create"/>
             <child>
-              <object class="GtkImage">
+              <object class="GtkHeaderBar" id="left_header">
                 <property name="visible">True</property>
-                <property name="icon_name">list-add-symbolic</property>
+                <property name="hexpand">False</property>
+                <property name="can_focus">False</property>
+                <property name="title" translatable="yes">Passwords and Keys</property>
+                <property name="show_close_button">True</property>
+                <child>
+                  <object class="GtkMenuButton" id="new_item_button">
+                    <property name="visible">True</property>
+                    <property name="halign">start</property>
+                    <property name="tooltip_text" translatable="yes">Add a new key or item</property>
+                    <property name="popover">new_item_menu_popover</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="visible">True</property>
+                        <property name="icon_name">list-add-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="pack_type">start</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="main_menu_button">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="focus_on_click">False</property>
+                    <property name="menu-model">main_menu</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="icon_name">open-menu-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="pack_type">end</property>
+                  </packing>
+                </child>
               </object>
+              <packing>
+                <property name="name">sidebar-pane</property>
+              </packing>
             </child>
-          </object>
-        </child>
-        <child>
-          <object class="GtkMenuButton" id="main_menu_button">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="focus_on_click">False</property>
-            <property name="menu-model">main_menu</property>
             <child>
-              <object class="GtkImage">
+              <object class="GtkSeparator" id="header_separator">
                 <property name="visible">True</property>
-                <property name="can_focus">False</property>
-                <property name="icon_name">open-menu-symbolic</property>
+                <style>
+                  <class name="sidebar"/>
+                </style>
               </object>
+              <packing>
+                <property name="allow-visible">False</property>
+              </packing>
             </child>
-          </object>
-          <packing>
-            <property name="pack_type">end</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkToggleButton" id="show_search_button">
-            <property name="visible">True</property>
-            <property name="tooltip_text" translatable="yes">Search for a key or password</property>
             <child>
-              <object class="GtkImage">
+              <object class="GtkHeaderBar" id="right_header">
                 <property name="visible">True</property>
-                <property name="icon_name">edit-find-symbolic</property>
+                <property name="hexpand">True</property>
+                <property name="show_close_button">True</property>
+                <child>
+                  <object class="GtkRevealer" id="back_revealer">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="transition-type">slide-right</property>
+                    <property name="transition-duration" bind-source="content_box" 
bind-property="mode-transition-duration" bind-flags="bidirectional|sync-create"/>
+                    <child>
+                      <object class="GtkButton" id="back">
+                        <property name="visible">True</property>
+                        <property name="valign">center</property>
+                        <property name="use-underline">True</property>
+                        <signal name="clicked" handler="on_back_clicked"/>
+                        <style>
+                          <class name="image-button"/>
+                        </style>
+                        <child internal-child="accessible">
+                          <object class="AtkObject" id="a11y-back">
+                            <property name="accessible-name" translatable="yes">Back</property>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkImage" id="back_image">
+                            <property name="visible">True</property>
+                            <property name="icon-name">go-previous-symbolic</property>
+                            <property name="icon-size">1</property>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkMenuButton" id="items_menu_button">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="focus_on_click">False</property>
+                    <property name="menu-model">items_menu</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="icon_name">view-more-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="pack_type">end</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkToggleButton" id="show_search_button">
+                    <property name="visible">True</property>
+                    <property name="tooltip_text" translatable="yes">Search for a key or password</property>
+                    <child>
+                      <object class="GtkImage">
+                        <property name="visible">True</property>
+                        <property name="icon_name">edit-find-symbolic</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="pack_type">end</property>
+                  </packing>
+                </child>
               </object>
+              <packing>
+                <property name="name">item-list-pane</property>
+              </packing>
             </child>
           </object>
-          <packing>
-            <property name="pack_type">end</property>
-          </packing>
         </child>
       </object>
     </child>
+
     <child>
-      <object class="GtkPaned" id="sidebar_panes">
+      <object class="HdyLeaflet" id="content_box">
         <property name="visible">True</property>
         <property name="vexpand">True</property>
         <property name="can_focus">True</property>
+        <property name="can-swipe-back">True</property>
+        <property name="transition-type">over</property>
+        <signal name="notify::fold" handler="on_fold" object="SeahorseKeyManager" after="yes" swapped="no"/>
         <child>
           <object class="GtkScrolledWindow" id="sidebar_area">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="hscrollbar-policy">never</property>
-            <property name="shadow-type">out</property>
-            <property name="width-request">170</property>
+          </object>
+          <packing>
+            <property name="name">sidebar-pane</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkSeparator">
+            <property name="visible">True</property>
             <style>
               <class name="sidebar"/>
             </style>
           </object>
           <packing>
-            <property name="shrink">False</property>
+            <property name="allow-visible">False</property>
           </packing>
         </child>
         <child>
-          <object class="GtkBox">
+          <object class="GtkBox" id="right_content">
             <property name="visible">True</property>
             <property name="orientation">vertical</property>
             <child>
@@ -374,37 +480,21 @@
                     <property name="can_focus">True</property>
                     <property name="hscrollbar-policy">never</property>
                     <child>
-                      <object class="GtkBox">
+                      <object class="HdyColumn">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
-                        <property name="orientation">horizontal</property>
-                        <property name="margin-top">24</property>
-                        <property name="margin-bottom">24</property>
-                        <child>
-                          <object class="GtkBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="hexpand">True</property>
-                          </object>
-                        </child>
-                        <child>
-                          <object class="GtkBox">
-                            <property name="visible">True</property>
-                            <property name="can_focus">False</property>
-                            <property name="hexpand">True</property>
-                          </object>
-                          <packing>
-                            <property name="pack_type">end</property>
-                          </packing>
-                        </child>
+                        <property name="linear-growth-width">400</property>
+                        <property name="maximum-width">800</property>
+                        <property name="margin-top">12</property>
+                        <property name="margin-bottom">12</property>
                         <child>
                           <object class="GtkListBox" id="item_listbox">
                             <property name="visible">True</property>
                             <property name="hexpand">True</property>
                             <property name="can-focus">True</property>
                             <property name="has-focus">True</property>
-                            <property name="margin-start">18</property>
-                            <property name="margin-end">18</property>
+                            <property name="margin-start">12</property>
+                            <property name="margin-end">12</property>
                             <property name="activate-on-single-click">False</property>
                             <property name="selection-mode">multiple</property>
                             <style>
@@ -502,10 +592,37 @@
             </child>
           </object>
           <packing>
-            <property name="shrink">False</property>
+            <property name="name">item-list-pane</property>
           </packing>
         </child>
       </object>
     </child>
   </template>
+
+  <object class="GtkSizeGroup" id="left_pane_size_group">
+    <property name="mode">horizontal</property>
+    <widgets>
+      <widget name="left_header"/>
+      <widget name="sidebar_area"/>
+    </widgets>
+  </object>
+  <object class="GtkSizeGroup" id="right_pane_size_group">
+    <property name="mode">horizontal</property>
+    <widgets>
+      <widget name="right_header"/>
+      <widget name="right_content"/>
+    </widgets>
+  </object>
+  <object class="HdyHeaderGroup" id="header_group">
+    <headerbars>
+      <headerbar name="left_header"/>
+      <headerbar name="right_header"/>
+    </headerbars>
+  </object>
+  <object class="HdySwipeGroup" id="swipe_group">
+    <swipeables>
+      <swipeable name="header"/>
+      <swipeable name="content_box"/>
+    </swipeables>
+  </object>
 </interface>
diff --git a/src/sidebar.vala b/src/sidebar.vala
index 76dc73cb..fc53e502 100644
--- a/src/sidebar.vala
+++ b/src/sidebar.vala
@@ -144,8 +144,9 @@ public class Seahorse.Sidebar : Gtk.ListBox {
                 label.tooltip_text = b.description;
                 label.get_style_context().add_class("seahorse-sidebar-item-header");
                 label.xalign = 0f;
-                label.margin_start = 6;
+                label.margin_start = 9;
                 label.margin_top = 6;
+                label.margin_bottom = 3;
                 label.show();
                 row.set_header(label);
                 return;
@@ -343,27 +344,27 @@ internal class Seahorse.SidebarItem : Gtk.ListBoxRow {
     public signal void place_changed();
 
     construct {
-      var grid = new Gtk.Grid();
-      grid.get_style_context().add_class("seahorse-sidebar-item");
-      grid.valign = Gtk.Align.CENTER;
-      grid.row_spacing = 6;
-      grid.column_spacing = 6;
-      add(grid);
+      var box = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 6);
+      box.get_style_context().add_class("seahorse-sidebar-item");
+      box.valign = Gtk.Align.CENTER;
+      box.margin_top = 3;
+      box.margin_bottom = 3;
+      add(box);
 
       var icon = new Gtk.Image.from_gicon(place.icon, Gtk.IconSize.BUTTON);
-      grid.attach(icon, 0, 0);
+      box.pack_start(icon, false, false);
 
       var label = new Gtk.Label(place.label);
-      label.hexpand = true;
       label.ellipsize = Pango.EllipsizeMode.END;
       label.xalign = 0f;
-      grid.attach(label, 1, 0);
+      box.pack_start(label);
 
       var lockable = place as Lockable;
       if (lockable != null && (lockable.lockable || lockable.unlockable)) {
           this.lock_button = new Gtk.Button.from_icon_name(get_lock_icon_name(lockable),
                                                           Gtk.IconSize.BUTTON);
           this.lock_button.get_style_context().add_class("flat");
+          this.lock_button.halign = Gtk.Align.END;
           this.lock_button.clicked.connect((b) => {
               if (lockable.unlockable)
                   place_unlock(lockable, (Gtk.Window) get_toplevel());
@@ -372,7 +373,7 @@ internal class Seahorse.SidebarItem : Gtk.ListBoxRow {
 
               update_lock_icon(lockable);
           });
-          grid.attach(this.lock_button, 2, 0);
+          box.pack_end(this.lock_button, false, false);
       }
 
       show_all();
diff --git a/subprojects/libhandy b/subprojects/libhandy
new file mode 160000
index 00000000..aa6b6f43
--- /dev/null
+++ b/subprojects/libhandy
@@ -0,0 +1 @@
+Subproject commit aa6b6f43d505383538a2a3e7b4fcdd6a8ada85ff


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