aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy-gtk
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2010-08-24 22:09:24 +0800
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2010-08-25 17:45:13 +0800
commit8f678a31a63eccb4fc086a8caddb37b1a0e7de91 (patch)
tree7ed83e9d7b40548d21aaa1c5afae75315dc647df /libempathy-gtk
parent4b08cbd1605f1671a9d90ffa7f3a3a1776e5a61a (diff)
downloadgsoc2013-empathy-8f678a31a63eccb4fc086a8caddb37b1a0e7de91.tar
gsoc2013-empathy-8f678a31a63eccb4fc086a8caddb37b1a0e7de91.tar.gz
gsoc2013-empathy-8f678a31a63eccb4fc086a8caddb37b1a0e7de91.tar.bz2
gsoc2013-empathy-8f678a31a63eccb4fc086a8caddb37b1a0e7de91.tar.lz
gsoc2013-empathy-8f678a31a63eccb4fc086a8caddb37b1a0e7de91.tar.xz
gsoc2013-empathy-8f678a31a63eccb4fc086a8caddb37b1a0e7de91.tar.zst
gsoc2013-empathy-8f678a31a63eccb4fc086a8caddb37b1a0e7de91.zip
add empathy-irc-network-chooser-dialog
Some of the code has been copied from empathy-account-widget-irc.c.
Diffstat (limited to 'libempathy-gtk')
-rw-r--r--libempathy-gtk/Makefile.am2
-rw-r--r--libempathy-gtk/empathy-irc-network-chooser-dialog.c487
-rw-r--r--libempathy-gtk/empathy-irc-network-chooser-dialog.h70
3 files changed, 559 insertions, 0 deletions
diff --git a/libempathy-gtk/Makefile.am b/libempathy-gtk/Makefile.am
index 15e187c07..d81b97253 100644
--- a/libempathy-gtk/Makefile.am
+++ b/libempathy-gtk/Makefile.am
@@ -64,6 +64,7 @@ libempathy_gtk_handwritten_source = \
empathy-individual-view.c \
empathy-individual-widget.c \
empathy-irc-network-chooser.c \
+ empathy-irc-network-chooser-dialog.c \
empathy-irc-network-dialog.c \
empathy-kludge-label.c \
empathy-log-window.c \
@@ -125,6 +126,7 @@ libempathy_gtk_headers = \
empathy-individual-view.h \
empathy-individual-widget.h \
empathy-irc-network-chooser.h \
+ empathy-irc-network-chooser-dialog.h \
empathy-irc-network-dialog.h \
empathy-kludge-label.h \
empathy-log-window.h \
diff --git a/libempathy-gtk/empathy-irc-network-chooser-dialog.c b/libempathy-gtk/empathy-irc-network-chooser-dialog.c
new file mode 100644
index 000000000..e4f6146bc
--- /dev/null
+++ b/libempathy-gtk/empathy-irc-network-chooser-dialog.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2007-2008 Guillaume Desmottes
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#include <libempathy/empathy-utils.h>
+#include <libempathy/empathy-irc-network-manager.h>
+
+#include "empathy-irc-network-dialog.h"
+#include "empathy-ui-utils.h"
+
+#define DEBUG_FLAG EMPATHY_DEBUG_ACCOUNT | EMPATHY_DEBUG_IRC
+#include <libempathy/empathy-debug.h>
+
+#include "empathy-irc-network-chooser-dialog.h"
+
+#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyIrcNetworkChooserDialog)
+
+enum {
+ PROP_SETTINGS = 1,
+ PROP_NETWORK
+};
+
+typedef struct {
+ EmpathyAccountSettings *settings;
+ EmpathyIrcNetwork *network;
+
+ EmpathyIrcNetworkManager *network_manager;
+ gboolean changed;
+
+ GtkWidget *treeview;
+ GtkListStore *store;
+} EmpathyIrcNetworkChooserDialogPriv;
+
+enum {
+ COL_NETWORK_OBJ,
+ COL_NETWORK_NAME,
+};
+
+G_DEFINE_TYPE (EmpathyIrcNetworkChooserDialog, empathy_irc_network_chooser_dialog,
+ GTK_TYPE_DIALOG);
+
+static void
+empathy_irc_network_chooser_dialog_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (object);
+
+ switch (prop_id)
+ {
+ case PROP_SETTINGS:
+ priv->settings = g_value_dup_object (value);
+ break;
+ case PROP_NETWORK:
+ priv->network = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+empathy_irc_network_chooser_dialog_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (object);
+
+ switch (prop_id)
+ {
+ case PROP_SETTINGS:
+ g_value_set_object (value, priv->settings);
+ break;
+ case PROP_NETWORK:
+ g_value_set_object (value, priv->network);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static EmpathyIrcNetwork *
+dup_selected_network (EmpathyIrcNetworkChooserDialog *self,
+ GtkTreeIter *it)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ EmpathyIrcNetwork *network;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ GtkTreeModel *model;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview));
+ gtk_tree_selection_get_selected (selection, &model, &iter);
+
+ gtk_tree_model_get (model, &iter, COL_NETWORK_OBJ, &network, -1);
+ g_assert (network != NULL);
+
+ if (it != NULL)
+ *it = iter;
+
+ return network;
+}
+
+static void
+treeview_changed_cb (GtkTreeView *treeview,
+ EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ EmpathyIrcNetwork *network;
+
+ network = dup_selected_network (self, NULL);
+ if (network == priv->network)
+ {
+ g_object_unref (network);
+ return;
+ }
+
+ tp_clear_object (&priv->network);
+ /* Transfer the reference */
+ priv->network = network;
+
+ priv->changed = TRUE;
+}
+
+static void
+scroll_to_iter (EmpathyIrcNetworkChooserDialog *self,
+ GtkTreeIter *iter)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ GtkTreePath *path;
+
+ path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->store), iter);
+
+ if (path != NULL)
+ {
+ gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->treeview),
+ path, NULL, FALSE, 0, 0);
+
+ gtk_tree_path_free (path);
+ }
+}
+
+static void
+select_iter (EmpathyIrcNetworkChooserDialog *self,
+ GtkTreeIter *iter,
+ gboolean emulate_changed)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ GtkTreeSelection *selection;
+
+ /* Select the network */
+ selection = gtk_tree_view_get_selection (
+ GTK_TREE_VIEW (priv->treeview));
+
+ gtk_tree_selection_select_iter (selection, iter);
+
+ /* Scroll to the selected network */
+ scroll_to_iter (self, iter);
+
+ if (emulate_changed)
+ {
+ /* gtk_tree_selection_select_iter doesn't fire the 'cursor-changed' signal
+ * so we call the callback manually. */
+ treeview_changed_cb (GTK_TREE_VIEW (priv->treeview), self);
+ }
+}
+
+static void
+fill_store (EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ GSList *networks, *l;
+
+ networks = empathy_irc_network_manager_get_networks (
+ priv->network_manager);
+
+ for (l = networks; l != NULL; l = g_slist_next (l))
+ {
+ gchar *name;
+ EmpathyIrcNetwork *network = l->data;
+ GtkTreeIter iter;
+
+ g_object_get (network, "name", &name, NULL);
+
+ gtk_list_store_insert_with_values (priv->store, &iter, -1,
+ COL_NETWORK_OBJ, network,
+ COL_NETWORK_NAME, name,
+ -1);
+
+ if (network == priv->network)
+ select_iter (self, &iter, FALSE);
+
+ g_free (name);
+ g_object_unref (network);
+ }
+
+ g_slist_free (networks);
+}
+
+static void
+irc_network_dialog_destroy_cb (GtkWidget *widget,
+ EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ EmpathyIrcNetwork *network;
+ gchar *name;
+ GtkTreeIter iter;
+
+ network = dup_selected_network (self, &iter);
+
+ /* name could be changed */
+ g_object_get (network, "name", &name, NULL);
+ gtk_list_store_set (GTK_LIST_STORE (priv->store), &iter,
+ COL_NETWORK_NAME, name, -1);
+
+ scroll_to_iter (self, &iter);
+
+ priv->changed = TRUE;
+
+ g_object_unref (network);
+ g_free (name);
+}
+
+static void
+display_irc_network_dialog (EmpathyIrcNetworkChooserDialog *self,
+ EmpathyIrcNetwork *network)
+{
+ GtkWidget *dialog;
+
+ dialog = empathy_irc_network_dialog_show (network, NULL);
+
+ g_signal_connect (dialog, "destroy",
+ G_CALLBACK (irc_network_dialog_destroy_cb), self);
+}
+
+static void
+edit_network (EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetwork *network;
+
+ network = dup_selected_network (self, NULL);
+ display_irc_network_dialog (self, network);
+
+ g_object_unref (network);
+}
+
+static void
+add_network (EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ EmpathyIrcNetwork *network;
+ gchar *name;
+ GtkTreeIter iter;
+
+ network = empathy_irc_network_new (_("New Network"));
+ empathy_irc_network_manager_add (priv->network_manager, network);
+
+ g_object_get (network, "name", &name, NULL);
+
+ gtk_list_store_insert_with_values (priv->store, &iter, -1,
+ COL_NETWORK_OBJ, network,
+ COL_NETWORK_NAME, name,
+ -1);
+
+ select_iter (self, &iter, TRUE);
+
+ display_irc_network_dialog (self, network);
+
+ g_free (name);
+ g_object_unref (network);
+}
+
+static void
+remove_network (EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ EmpathyIrcNetwork *network;
+ GtkTreeIter iter;
+ gchar *name;
+
+ network = dup_selected_network (self, &iter);
+
+ g_object_get (network, "name", &name, NULL);
+ DEBUG ("Remove network %s", name);
+
+ gtk_list_store_remove (priv->store, &iter);
+ empathy_irc_network_manager_remove (priv->network_manager, network);
+
+ /* Select next network */
+ if (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store), &iter))
+ select_iter (self, &iter, TRUE);
+
+ g_free (name);
+ g_object_unref (network);
+}
+
+static void
+dialog_response_cb (GtkDialog *dialog,
+ gint response,
+ EmpathyIrcNetworkChooserDialog *self)
+{
+ if (response == GTK_RESPONSE_OK)
+ add_network (self);
+ else if (response == GTK_RESPONSE_APPLY)
+ edit_network (self);
+ else if (response == GTK_RESPONSE_REJECT)
+ remove_network (self);
+}
+
+static void
+empathy_irc_network_chooser_dialog_constructed (GObject *object)
+{
+ EmpathyIrcNetworkChooserDialog *self = (EmpathyIrcNetworkChooserDialog *) object;
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+ GtkDialog *dialog = GTK_DIALOG (self);
+ GtkCellRenderer *renderer;
+ GtkWidget *vbox;
+ GtkTreeViewColumn *column;
+ GtkWidget *scroll;
+
+ g_assert (priv->settings != NULL);
+
+ gtk_window_set_title (GTK_WINDOW (self), _("IRC Networks"));
+
+ /* Create store and treeview */
+ priv->store = gtk_list_store_new (2, G_TYPE_OBJECT, G_TYPE_STRING);
+
+ gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
+ COL_NETWORK_NAME,
+ GTK_SORT_ASCENDING);
+
+ priv->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->store));
+ gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->treeview), FALSE);
+ gtk_tree_view_set_enable_search (GTK_TREE_VIEW (priv->treeview), FALSE);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (column), renderer, TRUE);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (column),
+ renderer,
+ "text", COL_NETWORK_NAME,
+ NULL);
+
+ /* add the treeview in a GtkScrolledWindow */
+ vbox = gtk_dialog_get_content_area (dialog);
+
+ scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
+ GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+
+ gtk_container_add (GTK_CONTAINER (scroll), priv->treeview);
+ gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 6);
+
+ /* Add buttons */
+ gtk_dialog_add_buttons (dialog,
+ GTK_STOCK_ADD, GTK_RESPONSE_OK,
+ GTK_STOCK_EDIT, GTK_RESPONSE_APPLY,
+ GTK_STOCK_REMOVE, GTK_RESPONSE_REJECT,
+ GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+ NULL);
+
+ fill_store (self);
+
+ g_signal_connect (priv->treeview, "cursor-changed",
+ G_CALLBACK (treeview_changed_cb), self);
+
+ g_signal_connect (self, "response",
+ G_CALLBACK (dialog_response_cb), self);
+
+ /* Request a side ensuring to display at least some networks */
+ gtk_widget_set_size_request (GTK_WIDGET (self), -1, 300);
+}
+
+static void
+empathy_irc_network_chooser_dialog_dispose (GObject *object)
+{
+ EmpathyIrcNetworkManager *self = (EmpathyIrcNetworkManager *) object;
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+
+ tp_clear_object (&priv->settings);
+ tp_clear_object (&priv->network);
+ tp_clear_object (&priv->network_manager);
+ tp_clear_object (&priv->store);
+
+ if (G_OBJECT_CLASS (empathy_irc_network_chooser_dialog_parent_class)->dispose)
+ G_OBJECT_CLASS (empathy_irc_network_chooser_dialog_parent_class)->dispose (object);
+}
+
+static void
+empathy_irc_network_chooser_dialog_class_init (EmpathyIrcNetworkChooserDialogClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = empathy_irc_network_chooser_dialog_get_property;
+ object_class->set_property = empathy_irc_network_chooser_dialog_set_property;
+ object_class->constructed = empathy_irc_network_chooser_dialog_constructed;
+ object_class->dispose = empathy_irc_network_chooser_dialog_dispose;
+
+ g_object_class_install_property (object_class, PROP_SETTINGS,
+ g_param_spec_object ("settings",
+ "Settings",
+ "The EmpathyAccountSettings to show and edit",
+ EMPATHY_TYPE_ACCOUNT_SETTINGS,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, PROP_NETWORK,
+ g_param_spec_object ("network",
+ "Network",
+ "The EmpathyIrcNetwork selected in the treeview",
+ EMPATHY_TYPE_IRC_NETWORK,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_type_class_add_private (object_class,
+ sizeof (EmpathyIrcNetworkChooserDialogPriv));
+}
+
+static void
+empathy_irc_network_chooser_dialog_init (EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv;
+
+ priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, EmpathyIrcNetworkChooserDialogPriv);
+ self->priv = priv;
+
+ priv->network_manager = empathy_irc_network_manager_dup_default ();
+}
+
+GtkWidget *
+empathy_irc_network_chooser_dialog_new (EmpathyAccountSettings *settings,
+ EmpathyIrcNetwork *network)
+{
+ return g_object_new (EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG,
+ "settings", settings,
+ "network", network,
+ NULL);
+}
+
+EmpathyIrcNetwork *
+empathy_irc_network_chooser_dialog_get_network (
+ EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+
+ return priv->network;
+}
+
+gboolean
+empathy_irc_network_chooser_dialog_get_changed (
+ EmpathyIrcNetworkChooserDialog *self)
+{
+ EmpathyIrcNetworkChooserDialogPriv *priv = GET_PRIV (self);
+
+ return priv->changed;
+}
diff --git a/libempathy-gtk/empathy-irc-network-chooser-dialog.h b/libempathy-gtk/empathy-irc-network-chooser-dialog.h
new file mode 100644
index 000000000..1c9d3fabd
--- /dev/null
+++ b/libempathy-gtk/empathy-irc-network-chooser-dialog.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007-2008 Guillaume Desmottes
+ * Copyright (C) 2010 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors: Guillaume Desmottes <gdesmott@gnome.org>
+ */
+
+#ifndef __EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_H__
+#define __EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_H__
+
+#include <gtk/gtk.h>
+
+#include <libempathy/empathy-account-settings.h>
+#include <libempathy/empathy-irc-network.h>
+
+G_BEGIN_DECLS
+
+#define EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG (empathy_irc_network_chooser_dialog_get_type ())
+#define EMPATHY_IRC_NETWORK_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \
+ EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, EmpathyIrcNetworkChooserDialog))
+#define EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), \
+ EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, EmpathyIrcNetworkChooserDialogClass))
+#define EMPATHY_IS_IRC_NETWORK_CHOOSER_DIALOG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
+ EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG))
+#define EMPATHY_IS_IRC_NETWORK_CHOOSER_DIALOG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \
+ EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG))
+#define EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_GET_CLASS(o) ( \
+ G_TYPE_INSTANCE_GET_CLASS ((o), EMPATHY_TYPE_IRC_NETWORK_CHOOSER_DIALOG, \
+ EmpathyIrcNetworkChooserDialogClass))
+
+typedef struct {
+ GtkDialog parent;
+
+ /*<private>*/
+ gpointer priv;
+} EmpathyIrcNetworkChooserDialog;
+
+typedef struct {
+ GtkDialogClass parent_class;
+} EmpathyIrcNetworkChooserDialogClass;
+
+GType empathy_irc_network_chooser_dialog_get_type (void) G_GNUC_CONST;
+
+GtkWidget * empathy_irc_network_chooser_dialog_new (
+ EmpathyAccountSettings *settings,
+ EmpathyIrcNetwork *network);
+
+EmpathyIrcNetwork * empathy_irc_network_chooser_dialog_get_network (
+ EmpathyIrcNetworkChooserDialog *self);
+
+gboolean empathy_irc_network_chooser_dialog_get_changed (
+ EmpathyIrcNetworkChooserDialog *self);
+
+G_END_DECLS
+
+#endif /* __EMPATHY_IRC_NETWORK_CHOOSER_DIALOG_H__ */