[gtk+] gtkplacessidebar: Adapt to libcloudproviders 0.2.x



commit f54e7712c53f914dc1bd04b7ebaaef30dc2ce86c
Author: Carlos Soriano <csoriano gnome org>
Date:   Mon Oct 30 21:38:41 2017 +0100

    gtkplacessidebar: Adapt to libcloudproviders 0.2.x
    
    And a few improvements on the way.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=786123

 gtk/gtkplacessidebar.c |  264 +++++++++++++++++++++++++++---------------------
 gtk/gtksidebarrow.c    |   90 ++++++++++++++---
 meson.build            |    2 +-
 3 files changed, 227 insertions(+), 129 deletions(-)
---
diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c
index 09e8f35..92b3806 100644
--- a/gtk/gtkplacessidebar.c
+++ b/gtk/gtkplacessidebar.c
@@ -25,8 +25,9 @@
 
 #include <gio/gio.h>
 #ifdef HAVE_CLOUDPROVIDERS
-#include <cloudproviders/cloudproviders.h>
-#include <cloudproviders/cloudprovideraccount.h>
+#include <cloudproviders/cloudproviderscollector.h>
+#include <cloudproviders/cloudprovidersaccount.h>
+#include <cloudproviders/cloudprovidersprovider.h>
 #endif
 
 #include "gtkplacessidebarprivate.h"
@@ -127,8 +128,8 @@ struct _GtkPlacesSidebar {
   GtkBookmarksManager     *bookmarks_manager;
 
 #ifdef HAVE_CLOUDPROVIDERS
-  CloudProviders *cloud_manager;
-  GList *cloud_rows;
+  CloudProvidersCollector *cloud_manager;
+  GList *unready_accounts;
 #endif
 
   GVolumeMonitor    *volume_monitor;
@@ -458,7 +459,7 @@ add_place (GtkPlacesSidebar            *sidebar,
            GVolume                     *volume,
            GMount                      *mount,
 #ifdef HAVE_CLOUDPROVIDERS
-           CloudProviderAccount        *cloud_provider_account,
+           CloudProvidersAccount       *cloud_provider_account,
 #else
            gpointer                    *cloud_provider_account,
 #endif
@@ -493,7 +494,7 @@ add_place (GtkPlacesSidebar            *sidebar,
                       "volume", volume,
                       "mount", mount,
 #ifdef HAVE_CLOUDPROVIDERS
-                      "cloud-provider", cloud_provider_account,
+                      "cloud-provider-account", cloud_provider_account,
 #endif
                       NULL);
 
@@ -914,61 +915,80 @@ update_trash_icon (GtkPlacesSidebar *sidebar)
 }
 
 #ifdef HAVE_CLOUDPROVIDERS
-static void
-cloud_row_update (CloudProviderAccount *cloud_provider_account,
-                  GtkWidget          *cloud_row)
+
+static gboolean
+create_cloud_provider_account_row (GtkPlacesSidebar      *sidebar,
+                                   CloudProvidersAccount *account)
 {
   GIcon *end_icon;
-  gint provider_status;
-  provider_status = cloud_provider_account_get_status (cloud_provider_account);
-  switch (provider_status)
+  GIcon *start_icon;
+  gchar *mount_uri;
+  gchar *name;
+  gchar *tooltip;
+  guint provider_account_status;
+
+  start_icon = cloud_providers_account_get_icon (account);
+  name = cloud_providers_account_get_name (account);
+  provider_account_status = cloud_providers_account_get_status (account);
+  mount_uri = cloud_providers_account_get_path (account);
+  if (start_icon != NULL
+      && name != NULL
+      && provider_account_status != CLOUD_PROVIDERS_ACCOUNT_STATUS_INVALID
+      && mount_uri != NULL)
     {
-      case CLOUD_PROVIDER_STATUS_IDLE:
-        end_icon = NULL;
-        break;
+      switch (provider_account_status)
+        {
+          case CLOUD_PROVIDERS_ACCOUNT_STATUS_IDLE:
+            end_icon = NULL;
+          break;
 
-      case CLOUD_PROVIDER_STATUS_SYNCING:
-        end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic");
-        break;
+          case CLOUD_PROVIDERS_ACCOUNT_STATUS_SYNCING:
+            end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic");
+          break;
 
-      case CLOUD_PROVIDER_STATUS_ERROR:
-        end_icon = g_themed_icon_new ("dialog-warning-symbolic");
-        break;
+          case CLOUD_PROVIDERS_ACCOUNT_STATUS_ERROR:
+            end_icon = g_themed_icon_new ("dialog-warning-symbolic");
+          break;
 
-      default:
-        return;
-    }
+          default:
+            return FALSE;
+        }
 
-  gtk_sidebar_row_set_end_icon (GTK_SIDEBAR_ROW (cloud_row), end_icon);
-  if (end_icon != NULL)
-    g_object_unref (end_icon);
+      mount_uri = g_strconcat ("file://", mount_uri, NULL);
 
-  g_object_set (cloud_row,
-                "label", cloud_provider_account_get_name (cloud_provider_account),
-                NULL);
-  g_object_set (cloud_row,
-                "tooltip", cloud_provider_account_get_status_details (cloud_provider_account),
-                NULL);
+      /* translators: %s is the name of a cloud provider for files */
+      tooltip = g_strdup_printf (_("Open %s"), name);
 
-}
+      add_place (sidebar, PLACES_BUILT_IN,
+                 SECTION_CLOUD,
+                 name, start_icon, end_icon, mount_uri,
+                 NULL, NULL, NULL, account, 0,
+                 tooltip);
 
-void
-cloud_row_destroy (GtkWidget *object,
-                   gpointer   user_data)
-{
-  GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
-  CloudProviderAccount *cloud_provider_account = NULL;
-  g_object_get (GTK_SIDEBAR_ROW (object), "cloud-provider", &cloud_provider_account, NULL);
-  if (cloud_provider_account != NULL)
+      return TRUE;
+    }
+  else
     {
-      g_signal_handlers_disconnect_matched (cloud_provider_account,
-                                            G_SIGNAL_MATCH_DATA,
-                                            0, 0, 0, cloud_row_update, object);
-      g_object_unref (object);
-      g_object_unref (cloud_provider_account);
+      return FALSE;
     }
-  sidebar->cloud_rows = g_list_remove (sidebar->cloud_rows, object);
 }
+
+static void
+on_account_updated (GObject    *object,
+                    GParamSpec *pspec,
+                    gpointer    user_data)
+{
+    CloudProvidersAccount *account = CLOUD_PROVIDERS_ACCOUNT (object);
+    GtkPlacesSidebar *sidebar = GTK_PLACES_SIDEBAR (user_data);
+
+    if (create_cloud_provider_account_row (sidebar, account))
+      {
+          g_signal_handlers_disconnect_by_data (account, sidebar);
+          sidebar->unready_accounts = g_list_remove (sidebar->unready_accounts, account);
+          g_object_unref (account);
+      }
+}
+
 #endif
 
 static void
@@ -991,10 +1011,10 @@ update_places (GtkPlacesSidebar *sidebar)
   GList *network_mounts, *network_volumes;
   GIcon *new_bookmark_icon;
 #ifdef HAVE_CLOUDPROVIDERS
-  GIcon *end_icon;
-  GList *cloud_provider_proxies;
-  guint provider_status;
-  gchar *cloudprovider_path;
+  GList *cloud_providers;
+  GList *cloud_providers_accounts;
+  CloudProvidersAccount *cloud_provider_account;
+  CloudProvidersProvider *cloud_provider;
 #endif
   GtkStyleContext *context;
 
@@ -1103,52 +1123,39 @@ update_places (GtkPlacesSidebar *sidebar)
 
   /* Cloud providers */
 #ifdef HAVE_CLOUDPROVIDERS
-  cloud_provider_proxies = cloud_providers_get_providers (sidebar->cloud_manager);
-  for (l = cloud_provider_proxies; l != NULL; l = l->next)
+  cloud_providers = cloud_providers_collector_get_providers (sidebar->cloud_manager);
+  for (l = sidebar->unready_accounts; l != NULL; l = l->next)
     {
-      start_icon = cloud_provider_account_get_icon (l->data);
-      name = cloud_provider_account_get_name (l->data);
-      provider_status = cloud_provider_account_get_status (l->data);
-      cloudprovider_path = cloud_provider_account_get_path (l->data);
-      if (start_icon == NULL
-          || name == NULL
-          || provider_status == CLOUD_PROVIDER_STATUS_INVALID
-          || cloudprovider_path == NULL)
-        continue;
-      cloudprovider_path = g_strconcat ("file://", cloud_provider_account_get_path (l->data), NULL);
-      switch (provider_status)
+        g_signal_handlers_disconnect_by_data (l->data, sidebar);
+    }
+  g_list_free_full (sidebar->unready_accounts, g_object_unref);
+  sidebar->unready_accounts = NULL;
+  for (l = cloud_providers; l != NULL; l = l->next)
+    {
+      cloud_provider = CLOUD_PROVIDERS_PROVIDER (l->data);
+      g_signal_connect_swapped (cloud_provider, "accounts-changed",
+                                G_CALLBACK (update_places), sidebar);
+      cloud_providers_accounts = cloud_providers_provider_get_accounts (cloud_provider);
+      for (ll = cloud_providers_accounts; ll != NULL; ll = ll->next)
         {
-        case CLOUD_PROVIDER_STATUS_IDLE:
-          end_icon = NULL;
-          break;
-
-        case CLOUD_PROVIDER_STATUS_SYNCING:
-          end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic");
-          break;
+          cloud_provider_account = CLOUD_PROVIDERS_ACCOUNT (ll->data);
+          if (!create_cloud_provider_account_row (sidebar, cloud_provider_account))
+            {
 
-        case CLOUD_PROVIDER_STATUS_ERROR:
-          end_icon = g_themed_icon_new ("dialog-warning-symbolic");
-          break;
+              g_signal_connect (cloud_provider_account, "notify::name",
+                                G_CALLBACK (on_account_updated), sidebar);
+              g_signal_connect (cloud_provider_account, "notify::status",
+                                G_CALLBACK (on_account_updated), sidebar);
+              g_signal_connect (cloud_provider_account, "notify::status-details",
+                                G_CALLBACK (on_account_updated), sidebar);
+              g_signal_connect (cloud_provider_account, "notify::path",
+                                G_CALLBACK (on_account_updated), sidebar);
+              sidebar->unready_accounts = g_list_append (sidebar->unready_accounts,
+                                                         g_object_ref (cloud_provider_account));
+              continue;
+            }
 
-        default:
-          continue;
         }
-
-      /* translators: %s is the name of a cloud provider for files */
-      tooltip = g_strdup_printf (_("Open %s"), name);
-
-      GtkWidget *cloud_row = NULL;
-      cloud_row = add_place (sidebar, PLACES_BUILT_IN,
-                               SECTION_CLOUD,
-                               name, start_icon, end_icon, cloudprovider_path,
-                               NULL, NULL, NULL, l->data, 0,
-                               tooltip);
-
-      g_signal_connect (l->data, "changed", G_CALLBACK (cloud_row_update), cloud_row);
-      g_signal_connect (cloud_row, "destroy", G_CALLBACK (cloud_row_destroy), sidebar);
-      g_object_ref (cloud_row);
-      g_object_ref (l->data);
-      sidebar->cloud_rows = g_list_append (sidebar->cloud_rows, cloud_row);
     }
 #endif
 
@@ -3542,17 +3549,17 @@ on_row_popover_destroy (GtkWidget        *row_popover,
 static void
 build_popup_menu_using_gmenu (GtkSidebarRow *row)
 {
-  CloudProviderAccount *cloud_provider_account;
+  CloudProvidersAccount *cloud_provider_account;
   GtkPlacesSidebar *sidebar;
   GMenuModel *cloud_provider_menu;
   GActionGroup *cloud_provider_action_group;
 
   g_object_get (row,
                 "sidebar", &sidebar,
-                "cloud-provider", &cloud_provider_account,
+                "cloud-provider-account", &cloud_provider_account,
                 NULL);
 
-  /* Cloud provider */
+  /* Cloud provider account */
   if (cloud_provider_account)
     {
       GMenu *menu = g_menu_new ();
@@ -3569,19 +3576,23 @@ build_popup_menu_using_gmenu (GtkSidebarRow *row)
       g_menu_item_set_action_and_target_value (item, "row.open-other",
                                                g_variant_new_int32 (GTK_PLACES_OPEN_NEW_WINDOW));
       g_menu_append_item (menu, item);
-      cloud_provider_menu = cloud_provider_account_get_menu_model (cloud_provider_account);
-      g_menu_append_section (menu, NULL, cloud_provider_menu);
-      cloud_provider_action_group = cloud_provider_account_get_action_group (cloud_provider_account);
-      gtk_widget_insert_action_group (GTK_WIDGET (sidebar),
-                                      "cloudprovider",
-                                      G_ACTION_GROUP (cloud_provider_action_group));
+      cloud_provider_menu = cloud_providers_account_get_menu_model (cloud_provider_account);
+      cloud_provider_action_group = cloud_providers_account_get_action_group (cloud_provider_account);
+      if (cloud_provider_menu != NULL && cloud_provider_action_group != NULL)
+        {
+          g_menu_append_section (menu, NULL, cloud_provider_menu);
+          gtk_widget_insert_action_group (GTK_WIDGET (sidebar),
+                                          "cloudprovider",
+                                          G_ACTION_GROUP (cloud_provider_action_group));
+        }
       add_actions (sidebar);
       if (sidebar->popover)
         gtk_widget_destroy (sidebar->popover);
 
       sidebar->popover = gtk_popover_new_from_model (GTK_WIDGET (sidebar),
                                                      G_MENU_MODEL (menu));
-      g_signal_connect (sidebar->popover, "destroy", G_CALLBACK (on_row_popover_destroy), sidebar);
+      g_signal_connect (sidebar->popover, "destroy",
+                        G_CALLBACK (on_row_popover_destroy), sidebar);
       g_object_unref (sidebar);
       g_object_unref (cloud_provider_account);
     }
@@ -3597,15 +3608,15 @@ create_row_popover (GtkPlacesSidebar *sidebar,
   GtkWidget *box;
 
 #ifdef HAVE_CLOUDPROVIDERS
-  CloudProviderAccount *cloud_provider_account;
+  CloudProvidersAccount *cloud_provider_account;
 
-  g_object_get (row, "cloud-provider", &cloud_provider_account, NULL);
+  g_object_get (row, "cloud-provider-account", &cloud_provider_account, NULL);
 
   if (cloud_provider_account)
-  {
-    build_popup_menu_using_gmenu (row);
-    return;
-  }
+    {
+      build_popup_menu_using_gmenu (row);
+       return;
+    }
 #endif
 
   sidebar->popover = gtk_popover_new (GTK_WIDGET (sidebar));
@@ -4112,13 +4123,11 @@ gtk_places_sidebar_init (GtkPlacesSidebar *sidebar)
 
   /* Cloud providers */
 #ifdef HAVE_CLOUDPROVIDERS
-  sidebar->cloud_rows = NULL;
-  sidebar->cloud_manager = cloud_providers_dup_singleton ();
+  sidebar->cloud_manager = cloud_providers_collector_dup_singleton ();
   g_signal_connect_swapped (sidebar->cloud_manager,
-                            "owners-changed",
+                            "providers-changed",
                             G_CALLBACK (update_places),
                             sidebar);
-  cloud_providers_update (sidebar->cloud_manager);
 #endif
 
   /* populate the sidebar */
@@ -4247,6 +4256,9 @@ static void
 gtk_places_sidebar_dispose (GObject *object)
 {
   GtkPlacesSidebar *sidebar;
+#ifdef HAVE_CLOUDPROVIDERS
+  GList *l;
+#endif
 
   sidebar = GTK_PLACES_SIDEBAR (object);
 
@@ -4332,13 +4344,36 @@ gtk_places_sidebar_dispose (GObject *object)
   sidebar->shortcuts = NULL;
 
 #ifdef HAVE_CLOUDPROVIDERS
-  g_clear_object (&sidebar->cloud_manager);
+  for (l = cloud_providers_collector_get_providers (sidebar->cloud_manager);
+       l != NULL; l = l->next)
+    {
+      g_signal_handlers_disconnect_by_data (l->data, sidebar);
+    }
+  for (l = sidebar->unready_accounts; l != NULL; l = l->next)
+    {
+        g_signal_handlers_disconnect_by_data (l->data, sidebar);
+    }
+  g_list_free_full (sidebar->unready_accounts, g_object_unref);
+  sidebar->unready_accounts = NULL;
 #endif
 
   G_OBJECT_CLASS (gtk_places_sidebar_parent_class)->dispose (object);
 }
 
 static void
+gtk_places_sidebar_finalize (GObject *object)
+{
+  GtkPlacesSidebar *sidebar;
+
+  sidebar = GTK_PLACES_SIDEBAR (object);
+#ifdef HAVE_CLOUDPROVIDERS
+  g_clear_object (&sidebar->cloud_manager);
+#endif
+
+  G_OBJECT_CLASS (gtk_places_sidebar_parent_class)->finalize (object);
+}
+
+static void
 gtk_places_sidebar_class_init (GtkPlacesSidebarClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
@@ -4346,6 +4381,7 @@ gtk_places_sidebar_class_init (GtkPlacesSidebarClass *class)
 
 
   gobject_class->dispose = gtk_places_sidebar_dispose;
+  gobject_class->finalize = gtk_places_sidebar_finalize;
   gobject_class->set_property = gtk_places_sidebar_set_property;
   gobject_class->get_property = gtk_places_sidebar_get_property;
 
diff --git a/gtk/gtksidebarrow.c b/gtk/gtksidebarrow.c
index 65a69f5..26bce9b 100644
--- a/gtk/gtksidebarrow.c
+++ b/gtk/gtksidebarrow.c
@@ -30,7 +30,7 @@
 #include "gtkselection.h"
 
 #ifdef HAVE_CLOUDPROVIDERS
-#include <cloudproviders/cloudprovideraccount.h>
+#include <cloudproviders/cloudprovidersaccount.h>
 #endif
 
 struct _GtkSidebarRow
@@ -52,7 +52,7 @@ struct _GtkSidebarRow
   GDrive *drive;
   GVolume *volume;
   GMount *mount;
-  GObject *cloud_provider;
+  GObject *cloud_provider_account;
   gboolean placeholder;
   GtkPlacesSidebar *sidebar;
   GtkWidget *revealer;
@@ -76,13 +76,58 @@ enum
   PROP_DRIVE,
   PROP_VOLUME,
   PROP_MOUNT,
-  PROP_CLOUD_PROVIDER,
+  PROP_CLOUD_PROVIDER_ACCOUNT,
   PROP_PLACEHOLDER,
   LAST_PROP
 };
 
 static GParamSpec *properties [LAST_PROP];
 
+#ifdef HAVE_CLOUDPROVIDERS
+
+static void
+cloud_row_update (GtkSidebarRow *self)
+{
+  CloudProvidersAccount *account;
+  GIcon *end_icon;
+  gint provider_status;
+
+  account = CLOUD_PROVIDERS_ACCOUNT (self->cloud_provider_account);
+  provider_status = cloud_providers_account_get_status (account);
+  switch (provider_status)
+    {
+      case CLOUD_PROVIDERS_ACCOUNT_STATUS_IDLE:
+        end_icon = NULL;
+        break;
+
+      case CLOUD_PROVIDERS_ACCOUNT_STATUS_SYNCING:
+        end_icon = g_themed_icon_new ("emblem-synchronizing-symbolic");
+        break;
+
+      case CLOUD_PROVIDERS_ACCOUNT_STATUS_ERROR:
+        end_icon = g_themed_icon_new ("dialog-warning-symbolic");
+        break;
+
+      default:
+        return;
+    }
+
+  g_object_set (self,
+                "label", cloud_providers_account_get_name (account),
+                NULL);
+  g_object_set (self,
+                "tooltip", cloud_providers_account_get_status_details (account),
+                NULL);
+  g_object_set (self,
+                "end-icon", end_icon,
+                NULL);
+
+  if (end_icon != NULL)
+    g_object_unref (end_icon);
+}
+
+#endif
+
 static void
 gtk_sidebar_row_get_property (GObject    *object,
                               guint       prop_id,
@@ -145,8 +190,8 @@ gtk_sidebar_row_get_property (GObject    *object,
       g_value_set_object (value, self->mount);
       break;
 
-    case PROP_CLOUD_PROVIDER:
-      g_value_set_object (value, self->cloud_provider);
+    case PROP_CLOUD_PROVIDER_ACCOUNT:
+      g_value_set_object (value, self->cloud_provider_account);
       break;
 
     case PROP_PLACEHOLDER:
@@ -265,9 +310,22 @@ gtk_sidebar_row_set_property (GObject      *object,
       g_set_object (&self->mount, g_value_get_object (value));
       break;
 
-    case PROP_CLOUD_PROVIDER:
+    case PROP_CLOUD_PROVIDER_ACCOUNT:
 #ifdef HAVE_CLOUDPROVIDERS
-      g_set_object (&self->cloud_provider, g_value_get_object (value));
+      if (self->cloud_provider_account != NULL)
+        g_signal_handlers_disconnect_by_data (self->cloud_provider_account, self);
+
+      self->cloud_provider_account = g_value_dup_object (value);
+
+      if (self->cloud_provider_account != NULL)
+        {
+          g_signal_connect_swapped (self->cloud_provider_account, "notify::name",
+                                    G_CALLBACK (cloud_row_update), self);
+          g_signal_connect_swapped (self->cloud_provider_account, "notify::status",
+                                    G_CALLBACK (cloud_row_update), self);
+          g_signal_connect_swapped (self->cloud_provider_account, "notify::status-details",
+                                    G_CALLBACK (cloud_row_update), self);
+        }
 #endif
       break;
 
@@ -291,7 +349,7 @@ gtk_sidebar_row_set_property (GObject      *object,
             g_clear_object (&self->drive);
             g_clear_object (&self->volume);
             g_clear_object (&self->mount);
-            g_clear_object (&self->cloud_provider);
+            g_clear_object (&self->cloud_provider_account);
 
             gtk_container_foreach (GTK_CONTAINER (self),
                                    (GtkCallback) gtk_widget_destroy,
@@ -398,7 +456,11 @@ gtk_sidebar_row_finalize (GObject *object)
   g_clear_object (&self->drive);
   g_clear_object (&self->volume);
   g_clear_object (&self->mount);
-  g_clear_object (&self->cloud_provider);
+#ifdef HAVE_CLOUDPROVIDERS
+  if (self->cloud_provider_account != NULL)
+    g_signal_handlers_disconnect_by_data (self->cloud_provider_account, self);
+  g_clear_object (&self->cloud_provider_account);
+#endif
 
   G_OBJECT_CLASS (gtk_sidebar_row_parent_class)->finalize (object);
 }
@@ -530,10 +592,10 @@ gtk_sidebar_row_class_init (GtkSidebarRowClass *klass)
                           G_PARAM_CONSTRUCT_ONLY |
                           G_PARAM_STATIC_STRINGS));
 
-  properties [PROP_CLOUD_PROVIDER] =
-    g_param_spec_object ("cloud-provider",
-                         "CloudProviderAccount",
-                         "CloudProviderAccount",
+  properties [PROP_CLOUD_PROVIDER_ACCOUNT] =
+    g_param_spec_object ("cloud-provider-account",
+                         "CloudProvidersAccount",
+                         "CloudProvidersAccount",
                          G_TYPE_OBJECT,
                          (G_PARAM_READWRITE |
                           G_PARAM_STATIC_STRINGS));
@@ -579,7 +641,7 @@ gtk_sidebar_row_clone (GtkSidebarRow *self)
                       "drive", self->drive,
                       "volume", self->volume,
                       "mount", self->mount,
-                      "cloud-provider", self->cloud_provider,
+                      "cloud-provider-account", self->cloud_provider_account,
                       NULL);
 }
 
diff --git a/meson.build b/meson.build
index fc5bf96..1288caa 100644
--- a/meson.build
+++ b/meson.build
@@ -38,7 +38,7 @@ mirclient_req      = '>= 0.22.0'
 mircookie_req      = '>= 0.17.0'
 graphene_req       = '>= 1.5.1'
 epoxy_req          = '>= 1.4'
-cloudproviders_req = '>= 0.2.0'
+cloudproviders_req = '>= 0.2.5'
 xkbcommon_req      = '>= 0.2.0'
 
 gnome = import('gnome')


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