gnome-control-center/panels/sharing/cc-sharing-panel.c
Thomas Wood f68f8e25f9 sharing: avoid conflicts with the sensitivity of the remote control options
Resolve the conflict between the GSettings bindings and the "Remote
Control" switch both attempting to set the sensitivity of the remote
control options by allowing the "Remote Control" switch to set the
sensitivity on the container of the other switches.

https://bugzilla.gnome.org/show_bug.cgi?id=703189
2013-06-28 13:58:17 +01:00

1060 lines
34 KiB
C

/*
* Copyright (C) 2013 Intel, Inc
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Author: Thomas Wood <thomas.wood@intel.com>
*
*/
#include "cc-sharing-panel.h"
#include "egg-list-box/egg-list-box.h"
#include "shell/cc-hostname-entry.h"
#include "cc-sharing-resources.h"
#include "vino-preferences.h"
#include "cc-remote-login.h"
#include "file-share-properties.h"
#include "cc-media-sharing.h"
#include <glib/gi18n.h>
#include <config.h>
#ifdef HAVE_BLUETOOTH
#include <bluetooth-killswitch.h>
#endif
CC_PANEL_REGISTER (CcSharingPanel, cc_sharing_panel)
#define PANEL_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), CC_TYPE_SHARING_PANEL, CcSharingPanelPrivate))
static GtkWidget *
_gtk_builder_get_widget (GtkBuilder *builder,
const gchar *name)
{
GtkWidget *w;
w = (GtkWidget*) gtk_builder_get_object (builder, name);
g_assert (w != NULL);
return w;
}
#define WID(y) _gtk_builder_get_widget (priv->builder, y)
#define VINO_SCHEMA_ID "org.gnome.Vino"
#define FILE_SHARING_SCHEMA_ID "org.gnome.desktop.file-sharing"
struct _CcSharingPanelPrivate
{
GtkBuilder *builder;
GtkWidget *master_switch;
GtkWidget *hostname_entry;
GtkWidget *bluetooth_sharing_dialog;
GtkWidget *media_sharing_dialog;
GtkWidget *personal_file_sharing_dialog;
GtkWidget *remote_login_dialog;
GCancellable *remote_login_cancellable;
GCancellable *hostname_cancellable;
GtkWidget *screen_sharing_dialog;
#ifdef HAVE_BLUETOOTH
BluetoothKillswitch *bluetooth_killswitch;
#endif
};
static void
cc_sharing_panel_master_switch_notify (GtkSwitch *gtkswitch,
GParamSpec *pspec,
CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
gboolean active;
active = gtk_switch_get_active (gtkswitch);
if (!active)
{
/* disable all services if the master switch is not active */
gtk_switch_set_active (GTK_SWITCH (WID ("remote-view-switch")), FALSE);
gtk_switch_set_active (GTK_SWITCH (WID ("remote-login-switch")), FALSE);
gtk_switch_set_active (GTK_SWITCH (WID ("share-public-folder-on-network-switch")),
FALSE);
gtk_switch_set_active (GTK_SWITCH (WID ("share-media-switch")), FALSE);
gtk_switch_set_active (GTK_SWITCH (WID ("share-public-folder-switch")),
FALSE);
}
gtk_widget_set_sensitive (WID ("main-list-box"), active);
}
static void
cc_sharing_panel_constructed (GObject *object)
{
CcSharingPanelPrivate *priv = CC_SHARING_PANEL (object)->priv;
G_OBJECT_CLASS (cc_sharing_panel_parent_class)->constructed (object);
/* add the master switch */
cc_shell_embed_widget_in_header (cc_panel_get_shell (CC_PANEL (object)),
priv->master_switch);
}
static void
cc_sharing_panel_dispose (GObject *object)
{
CcSharingPanelPrivate *priv = CC_SHARING_PANEL (object)->priv;
#ifdef HAVE_BLUETOOTH
g_clear_object (&priv->bluetooth_killswitch);
#endif
g_clear_object (&priv->builder);
if (priv->bluetooth_sharing_dialog)
{
gtk_widget_destroy (priv->bluetooth_sharing_dialog);
priv->bluetooth_sharing_dialog = NULL;
}
if (priv->media_sharing_dialog)
{
gtk_widget_destroy (priv->media_sharing_dialog);
priv->media_sharing_dialog = NULL;
}
if (priv->personal_file_sharing_dialog)
{
gtk_widget_destroy (priv->personal_file_sharing_dialog);
priv->personal_file_sharing_dialog = NULL;
}
if (priv->remote_login_cancellable)
{
g_cancellable_cancel (priv->remote_login_cancellable);
g_clear_object (&priv->remote_login_cancellable);
}
if (priv->hostname_cancellable)
{
g_cancellable_cancel (priv->hostname_cancellable);
g_clear_object (&priv->hostname_cancellable);
}
if (priv->remote_login_dialog)
{
gtk_widget_destroy (priv->remote_login_dialog);
priv->remote_login_dialog = NULL;
}
if (priv->screen_sharing_dialog)
{
gtk_widget_destroy (priv->screen_sharing_dialog);
priv->screen_sharing_dialog = NULL;
}
G_OBJECT_CLASS (cc_sharing_panel_parent_class)->dispose (object);
}
static const char *
cc_sharing_panel_get_help_uri (CcPanel *panel)
{
return "help:gnome-help/settings-sharing";
}
static void
cc_sharing_panel_class_init (CcSharingPanelClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
CcPanelClass *panel_class = CC_PANEL_CLASS (klass);
g_type_class_add_private (klass, sizeof (CcSharingPanelPrivate));
object_class->constructed = cc_sharing_panel_constructed;
object_class->dispose = cc_sharing_panel_dispose;
panel_class->get_help_uri = cc_sharing_panel_get_help_uri;
}
static void
cc_sharing_panel_run_dialog (CcSharingPanel *self,
const gchar *dialog_name)
{
CcSharingPanelPrivate *priv = self->priv;
GtkWidget *dialog, *parent;
dialog = WID (dialog_name);
parent = cc_shell_get_toplevel (cc_panel_get_shell (CC_PANEL (self)));
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (parent));
gtk_dialog_run (GTK_DIALOG (dialog));
}
static void
cc_sharing_panel_main_list_box_child_activated (EggListBox *listbox,
GtkWidget *widget,
CcSharingPanel *self)
{
gchar *widget_name, *found;
widget_name = g_strdup (gtk_buildable_get_name (GTK_BUILDABLE (widget)));
if (!widget_name)
return;
egg_list_box_select_child (listbox, NULL);
/* replace "button" with "dialog" */
found = g_strrstr (widget_name, "button");
if (!found)
goto out;
memcpy (found, "dialog", 6);
cc_sharing_panel_run_dialog (self, widget_name);
out:
g_free (widget_name);
}
static void
cc_sharing_panel_main_list_box_update_separator (GtkWidget **separator,
GtkWidget *child,
GtkWidget *before,
gpointer user_data)
{
if (before == NULL)
{
g_clear_object (separator);
return;
}
if (*separator != NULL)
return;
*separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
g_object_ref_sink (*separator);
}
static gboolean
cc_sharing_panel_switch_to_label_transform_func (GBinding *binding,
const GValue *source_value,
GValue *target_value,
CcSharingPanel *self)
{
gboolean active;
if (!G_VALUE_HOLDS_BOOLEAN (source_value))
return FALSE;
if (!G_VALUE_HOLDS_STRING (target_value))
return FALSE;
active = g_value_get_boolean (source_value);
if (active)
g_value_set_string (target_value, C_("service is enabled", "On"));
else
g_value_set_string (target_value, C_("service is disabled", "Off"));
/* ensure the master switch is active if one of the services is active */
if (active)
gtk_switch_set_active (GTK_SWITCH (self->priv->master_switch), TRUE);
return TRUE;
}
static void
cc_sharing_panel_bind_switch_to_label (CcSharingPanel *self,
GtkWidget *gtkswitch,
GtkWidget *label)
{
g_object_bind_property_full (gtkswitch, "active", label, "label",
G_BINDING_SYNC_CREATE,
(GBindingTransformFunc) cc_sharing_panel_switch_to_label_transform_func,
NULL, self, NULL);
}
static void
cc_sharing_panel_bind_switch_to_widgets (GtkWidget *gtkswitch,
GtkWidget *first_widget,
...)
{
va_list w;
GtkWidget *widget;
va_start (w, first_widget);
g_object_bind_property (gtkswitch, "active", first_widget,
"sensitive", G_BINDING_SYNC_CREATE);
while ((widget = va_arg (w, GtkWidget*)))
{
g_object_bind_property (gtkswitch, "active", widget,
"sensitive", G_BINDING_SYNC_CREATE);
}
va_end (w);
}
static gboolean
bluetooth_get_accept_files (GValue *value,
GVariant *variant,
gpointer user_data)
{
gboolean bonded;
bonded = g_str_equal (g_variant_get_string (variant, NULL), "bonded");
g_value_set_boolean (value, bonded);
return TRUE;
}
static GVariant *
bluetooth_set_accept_files (const GValue *value,
const GVariantType *type,
gpointer user_data)
{
if (g_value_get_boolean (value))
return g_variant_new_string ("bonded");
else
return g_variant_new_string ("always");
}
#ifdef HAVE_BLUETOOTH
static void
bluetooth_state_changed (CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
BluetoothKillswitchState killswitch_state;
killswitch_state = BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER;
if (priv->bluetooth_killswitch)
killswitch_state = bluetooth_killswitch_get_state (priv->bluetooth_killswitch);
if (killswitch_state == BLUETOOTH_KILLSWITCH_STATE_NO_ADAPTER)
gtk_widget_hide (WID ("bluetooth-sharing-button"));
else
gtk_widget_show (WID ("bluetooth-sharing-button"));
}
#endif
static void
cc_sharing_panel_setup_bluetooth_sharing_dialog (CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
GSettings *settings;
#ifdef HAVE_BLUETOOTH
priv->bluetooth_killswitch = bluetooth_killswitch_new ();
/* get the initial state */
bluetooth_state_changed (self);
g_signal_connect_swapped (priv->bluetooth_killswitch, "state-changed",
G_CALLBACK (bluetooth_state_changed), self);
#endif
cc_sharing_panel_bind_switch_to_label (self,
WID ("share-public-folder-switch"),
WID ("bluetooth-sharing-status-label"));
cc_sharing_panel_bind_switch_to_widgets (WID ("share-public-folder-switch"),
WID ("only-share-trusted-devices-box"),
NULL);
cc_sharing_panel_bind_switch_to_widgets (WID ("save-received-files-to-downloads-switch"),
WID ("receive-files-grid"),
NULL);
settings = g_settings_new (FILE_SHARING_SCHEMA_ID);
g_settings_bind (settings, "bluetooth-enabled",
WID ("share-public-folder-switch"), "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind (settings, "bluetooth-require-pairing",
WID ("only-share-trusted-devices-switch"), "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind (settings, "bluetooth-obexpush-enabled",
WID ("save-received-files-to-downloads-switch"), "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind_with_mapping (settings, "bluetooth-accept-files",
WID ("only-receive-from-trusted-devices-switch"),
"active",
G_SETTINGS_BIND_DEFAULT,
bluetooth_get_accept_files,
bluetooth_set_accept_files, NULL, NULL);
}
static void
cc_sharing_panel_add_folder (GtkWidget *button,
CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
GtkWidget *dialog;
GtkListStore *store;
gchar *folder;
dialog = gtk_file_chooser_dialog_new (_("Choose a Folder"),
GTK_WINDOW (gtk_widget_get_toplevel (button)),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
NULL);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_hide (dialog);
store = (GtkListStore *) gtk_builder_get_object (priv->builder,
"shared-folders-liststore");
folder = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
if (folder && !g_str_equal (folder, ""))
gtk_list_store_insert_with_values (store, NULL, -1, 0, folder, -1);
g_free (folder);
gtk_widget_destroy (dialog);
}
static void
cc_sharing_panel_remove_folder (GtkButton *button,
CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
GtkTreeSelection *selection;
GtkTreeIter iter;
GtkTreeModel *model;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("shared-folders-treeview")));
gtk_tree_selection_get_selected (selection, &model, &iter);
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
}
static void
cc_sharing_panel_selection_changed (GtkTreeSelection *selection,
CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
if (gtk_tree_selection_count_selected_rows (selection) > 0)
gtk_widget_set_sensitive (WID ("remove-button"), TRUE);
else
gtk_widget_set_sensitive (WID ("remove-button"), FALSE);
}
static void
cc_sharing_panel_media_sharing_dialog_response (GtkDialog *dialog,
gint reponse_id,
CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
GtkTreeModel *model;
GtkTreeIter iter;
gboolean valid;
GPtrArray *folders;
model = (GtkTreeModel *) gtk_builder_get_object (priv->builder,
"shared-folders-liststore");
valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter);
folders = g_ptr_array_new_with_free_func (g_free);
while (valid)
{
gchar *folder;
gtk_tree_model_get (model, &iter, 0, &folder, -1);
g_ptr_array_add (folders, folder);
valid = gtk_tree_model_iter_next (model, &iter);
}
g_ptr_array_add (folders, NULL);
cc_media_sharing_set_preferences (gtk_switch_get_active (GTK_SWITCH (WID ("share-media-switch"))),
(gchar **) folders->pdata);
g_ptr_array_free (folders, TRUE);
}
static void
cc_sharing_panel_setup_media_sharing_dialog (CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
gchar **folders, **list;
gboolean enabled;
GtkListStore *store;
char *path;
path = g_find_program_in_path ("rygel");
if (path == NULL)
{
gtk_widget_hide (WID ("media-sharing-button"));
return;
}
g_free (path);
cc_sharing_panel_bind_switch_to_label (self, WID ("share-media-switch"),
WID ("media-sharing-status-label"));
cc_sharing_panel_bind_switch_to_widgets (WID ("share-media-switch"),
WID ("shared-folders-box"),
NULL);
g_signal_connect (WID ("add-button"), "clicked",
G_CALLBACK (cc_sharing_panel_add_folder), self);
g_signal_connect (WID ("remove-button"), "clicked",
G_CALLBACK (cc_sharing_panel_remove_folder), self);
g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (WID ("shared-folders-treeview"))),
"changed", G_CALLBACK (cc_sharing_panel_selection_changed), self);
g_signal_connect (WID ("media-sharing-dialog"), "response",
G_CALLBACK (cc_sharing_panel_media_sharing_dialog_response),
self);
cc_media_sharing_get_preferences (&enabled, &folders);
gtk_switch_set_active (GTK_SWITCH (WID ("share-media-switch")), enabled);
list = folders;
store = (GtkListStore *) gtk_builder_get_object (priv->builder,
"shared-folders-liststore");
while (list && *list)
{
gtk_list_store_insert_with_values (store, NULL, -1, 0, *list, -1);
list++;
}
g_strfreev (folders);
}
static gboolean
cc_sharing_panel_label_activate_link (GtkLabel *label,
gchar *uri,
GtkMenu *menu)
{
gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
g_object_set_data_full (G_OBJECT (menu), "uri-text", g_strdup (uri), g_free);
return TRUE;
}
static void
copy_uri_to_clipboard (GtkMenuItem *item,
GtkMenu *menu)
{
GtkClipboard *clipboard;
const gchar *text;
text = g_object_get_data (G_OBJECT (menu), "uri-text");
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
gtk_clipboard_set_text (clipboard, text, -1);
}
static void
cc_sharing_panel_setup_label (GtkLabel *label,
const gchar *hostname)
{
gchar *text;
hostname = g_strdup (hostname);
text = g_strdup_printf (gtk_label_get_label (GTK_LABEL (label)), hostname, hostname);
gtk_label_set_label (GTK_LABEL (label), text);
g_free (text);
}
typedef struct
{
CcSharingPanel *panel;
GtkWidget *label;
} GetHostNameData;
static void
cc_sharing_panel_get_host_name_fqdn_done (GDBusConnection *connection,
GAsyncResult *res,
GetHostNameData *data)
{
GError *error = NULL;
GVariant *variant;
const gchar *fqdn;
variant = g_dbus_connection_call_finish (connection, res, &error);
if (variant == NULL)
{
/* Avahi service may not be available */
g_debug ("Error calling GetHostNameFqdn: %s", error->message);
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
gchar *hostname;
hostname = cc_hostname_entry_get_hostname (CC_HOSTNAME_ENTRY (data->panel->priv->hostname_entry));
cc_sharing_panel_setup_label (GTK_LABEL (data->label), hostname);
g_free (hostname);
}
g_free (data);
g_error_free (error);
return;
}
g_variant_get (variant, "(&s)", &fqdn);
cc_sharing_panel_setup_label (GTK_LABEL (data->label), fqdn);
g_variant_unref (variant);
g_object_unref (connection);
g_free (data);
}
static void
cc_sharing_panel_bus_ready (GObject *object,
GAsyncResult *res,
GetHostNameData *data)
{
GDBusConnection *connection;
GError *error = NULL;
connection = g_bus_get_finish (res, &error);
if (connection == NULL)
{
g_warning ("Could not connect to system bus: %s", error->message);
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
gchar *hostname;
hostname = cc_hostname_entry_get_hostname (CC_HOSTNAME_ENTRY (data->panel->priv->hostname_entry));
cc_sharing_panel_setup_label (GTK_LABEL (data->label), hostname);
g_free (hostname);
}
g_error_free (error);
g_free (data);
return;
}
g_dbus_connection_call (connection,
"org.freedesktop.Avahi",
"/",
"org.freedesktop.Avahi.Server",
"GetHostNameFqdn",
NULL,
(GVariantType*)"(s)",
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
(GAsyncReadyCallback) cc_sharing_panel_get_host_name_fqdn_done,
data);
}
static void
cc_sharing_panel_setup_label_with_hostname (CcSharingPanel *self,
GtkWidget *label)
{
GtkWidget *menu;
GtkWidget *menu_item;
GetHostNameData *get_hostname_data;
/* create the menu */
menu = gtk_menu_new ();
menu_item = gtk_menu_item_new_with_label (_("Copy"));
gtk_widget_show (menu_item);
g_signal_connect (menu_item, "activate", G_CALLBACK (copy_uri_to_clipboard),
menu);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
/* show the menu when the link is activated */
g_signal_connect (label, "activate-link",
G_CALLBACK (cc_sharing_panel_label_activate_link), menu);
/* destroy the menu when the label is destroyed */
g_signal_connect_swapped (label, "destroy", G_CALLBACK (gtk_widget_destroy),
menu);
/* set the hostname */
get_hostname_data = g_new (GetHostNameData, 1);
get_hostname_data->panel = self;
get_hostname_data->label = label;
g_bus_get (G_BUS_TYPE_SYSTEM, NULL,
(GAsyncReadyCallback) cc_sharing_panel_bus_ready,
get_hostname_data);
}
static gboolean
file_sharing_get_require_password (GValue *value,
GVariant *variant,
gpointer user_data)
{
if (g_str_equal (g_variant_get_string (variant, NULL), "always"))
g_value_set_boolean (value, TRUE);
else
g_value_set_boolean (value, FALSE);
return TRUE;
}
static GVariant *
file_sharing_set_require_password (const GValue *value,
const GVariantType *type,
gpointer user_data)
{
if (g_value_get_boolean (value))
return g_variant_new_string ("always");
else
return g_variant_new_string ("never");
}
static void
file_sharing_password_changed (GtkEntry *entry)
{
file_share_write_out_password (gtk_entry_get_text (entry));
}
static void
cc_sharing_panel_setup_personal_file_sharing_dialog (CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
GSettings *settings;
cc_sharing_panel_bind_switch_to_label (self,
WID ("share-public-folder-on-network-switch"),
WID ("personal-file-sharing-status-label"));
cc_sharing_panel_bind_switch_to_widgets (WID ("share-public-folder-on-network-switch"),
WID ("require-password-grid"),
NULL);
cc_sharing_panel_bind_switch_to_widgets (WID ("personal-file-sharing-require-password-switch"),
WID ("personal-file-sharing-password-entry"),
WID ("personal-file-sharing-password-label"),
NULL);
cc_sharing_panel_setup_label_with_hostname (self,
WID ("personal-file-sharing-label"));
/* the password cannot be read, so just make sure the entry is not empty */
gtk_entry_set_text (GTK_ENTRY (WID ("personal-file-sharing-password-entry")),
"password");
settings = g_settings_new (FILE_SHARING_SCHEMA_ID);
g_settings_bind (settings, "enabled",
WID ("share-public-folder-on-network-switch"), "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind_with_mapping (settings, "require-password",
WID ("personal-file-sharing-require-password-switch"),
"active",
G_SETTINGS_BIND_DEFAULT,
file_sharing_get_require_password,
file_sharing_set_require_password, NULL, NULL);
g_signal_connect (WID ("personal-file-sharing-password-entry"),
"notify::text", G_CALLBACK (file_sharing_password_changed),
NULL);
}
static void
remote_login_switch_activate (GtkSwitch *remote_login_switch,
GParamSpec *pspec,
CcSharingPanel *self)
{
cc_remote_login_set_enabled (self->priv->remote_login_cancellable, remote_login_switch);
}
static void
cc_sharing_panel_setup_remote_login_dialog (CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
cc_sharing_panel_bind_switch_to_label (self, WID ("remote-login-switch"),
WID ("remote-login-status-label"));
cc_sharing_panel_setup_label_with_hostname (self, WID ("remote-login-label"));
g_signal_connect (WID ("remote-login-switch"), "notify::active",
G_CALLBACK (remote_login_switch_activate), self);
gtk_widget_set_sensitive (WID ("remote-login-switch"), FALSE);
cc_remote_login_get_enabled (self->priv->remote_login_cancellable,
GTK_SWITCH (WID ("remote-login-switch")),
WID ("remote-login-button"));
}
static gboolean
cc_sharing_panel_check_schema_available (CcSharingPanel *self,
const gchar *schema_id)
{
const gchar * const* schema_list;
if (schema_id == NULL)
return FALSE;
schema_list = g_settings_list_schemas ();
while (*schema_list)
{
if (g_str_equal (*schema_list, schema_id))
return TRUE;
schema_list++;
}
return FALSE;
}
static void
screen_sharing_show_cb (GtkWidget *widget, CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("show-password-checkbutton")),
FALSE);
}
#define MAX_PASSWORD_SIZE 8
static void
screen_sharing_password_insert_text_cb (GtkEditable *editable,
gchar *new_text,
gint new_text_length,
gpointer position,
gpointer user_data)
{
int l, available_size;
l = gtk_entry_buffer_get_bytes (gtk_entry_get_buffer (GTK_ENTRY (editable)));
if (l + new_text_length <= MAX_PASSWORD_SIZE)
return;
g_signal_stop_emission_by_name (editable, "insert-text");
gtk_widget_error_bell (GTK_WIDGET (editable));
available_size = g_utf8_strlen (new_text, MAX_PASSWORD_SIZE - l);
if (available_size == 0)
return;
g_signal_handlers_block_by_func (editable,
(gpointer) screen_sharing_password_insert_text_cb,
user_data);
gtk_editable_insert_text (editable, new_text, available_size, position);
g_signal_handlers_unblock_by_func (editable,
(gpointer) screen_sharing_password_insert_text_cb,
user_data);
}
#undef MAX_PASSWORD_SIZE
static void
cc_sharing_panel_setup_screen_sharing_dialog (CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv;
GSettings *settings;
cc_sharing_panel_bind_switch_to_label (self, WID ("remote-view-switch"),
WID ("screen-sharing-status-label"));
cc_sharing_panel_bind_switch_to_widgets (WID ("remote-view-switch"),
WID ("remote-control-box"),
NULL);
cc_sharing_panel_bind_switch_to_widgets (WID ("remote-control-switch"),
WID ("remote-control-grid"),
NULL);
cc_sharing_panel_bind_switch_to_widgets (WID ("remote-control-require-password-switch"),
WID ("remote-control-password-entry"),
WID ("remote-control-password-label"),
NULL);
cc_sharing_panel_setup_label_with_hostname (self,
WID ("screen-sharing-label"));
/* settings bindings */
settings = g_settings_new (VINO_SCHEMA_ID);
g_settings_bind (settings, "enabled", WID ("remote-view-switch"), "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind (settings, "view-only", WID ("remote-control-switch"),
"active",
G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN);
g_settings_bind (settings, "prompt-enabled",
WID ("approve-all-connections-switch"), "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind_with_mapping (settings, "authentication-methods",
WID ("remote-control-require-password-switch"),
"active",
G_SETTINGS_BIND_DEFAULT,
vino_get_authtype, vino_set_authtype, NULL, NULL);
g_settings_bind_with_mapping (settings, "vnc-password",
WID ("remote-control-password-entry"),
"text",
G_SETTINGS_BIND_DEFAULT,
vino_get_password, vino_set_password, NULL, NULL);
g_object_bind_property (WID ("show-password-checkbutton"), "active",
WID ("remote-control-password-entry"), "visibility",
G_BINDING_SYNC_CREATE);
/* make sure the password entry is hidden by default */
g_signal_connect (priv->screen_sharing_dialog, "show",
G_CALLBACK (screen_sharing_show_cb), self);
/* accept at most 8 bytes in password entry */
g_signal_connect (WID ("remote-control-password-entry"), "insert-text",
G_CALLBACK (screen_sharing_password_insert_text_cb), self);
}
static void
cc_sharing_panel_init (CcSharingPanel *self)
{
CcSharingPanelPrivate *priv = self->priv = PANEL_PRIVATE (self);
GError *err = NULL;
gchar *objects[] = {
"sharing-panel",
"bluetooth-sharing-dialog",
"shared-folders-liststore",
"media-sharing-dialog",
"personal-file-sharing-dialog",
"remote-login-dialog",
"screen-sharing-dialog",
NULL };
g_resources_register (cc_sharing_get_resource ());
priv->builder = gtk_builder_new ();
gtk_builder_add_objects_from_resource (priv->builder,
"/org/gnome/control-center/sharing/sharing.ui",
objects, &err);
if (err)
g_error ("Error loading CcSharingPanel user interface: %s", err->message);
priv->hostname_entry = WID ("hostname-entry");
gtk_container_add (GTK_CONTAINER (self), WID ("sharing-panel"));
g_signal_connect (WID ("main-list-box"), "child-activated",
G_CALLBACK (cc_sharing_panel_main_list_box_child_activated), self);
priv->hostname_cancellable = g_cancellable_new ();
priv->bluetooth_sharing_dialog = WID ("bluetooth-sharing-dialog");
priv->media_sharing_dialog = WID ("media-sharing-dialog");
priv->personal_file_sharing_dialog = WID ("personal-file-sharing-dialog");
priv->remote_login_dialog = WID ("remote-login-dialog");
priv->remote_login_cancellable = g_cancellable_new ();
priv->screen_sharing_dialog = WID ("screen-sharing-dialog");
g_signal_connect (priv->bluetooth_sharing_dialog, "response",
G_CALLBACK (gtk_widget_hide), NULL);
g_signal_connect (priv->media_sharing_dialog, "response",
G_CALLBACK (gtk_widget_hide), NULL);
g_signal_connect (priv->personal_file_sharing_dialog, "response",
G_CALLBACK (gtk_widget_hide), NULL);
g_signal_connect (priv->remote_login_dialog, "response",
G_CALLBACK (gtk_widget_hide), NULL);
g_signal_connect (priv->screen_sharing_dialog, "response",
G_CALLBACK (gtk_widget_hide), NULL);
egg_list_box_set_activate_on_single_click (EGG_LIST_BOX (WID ("main-list-box")),
TRUE);
egg_list_box_set_separator_funcs (EGG_LIST_BOX (WID ("main-list-box")),
cc_sharing_panel_main_list_box_update_separator,
NULL, NULL);
/* create the master switch */
priv->master_switch = gtk_switch_new ();
gtk_widget_show (priv->master_switch);
/* start the panel in the disabled state */
gtk_switch_set_active (GTK_SWITCH (priv->master_switch), FALSE);
gtk_widget_set_sensitive (WID ("main-list-box"), FALSE);
g_signal_connect (priv->master_switch, "notify::active",
G_CALLBACK (cc_sharing_panel_master_switch_notify), self);
/* bluetooth */
if (cc_sharing_panel_check_schema_available (self, FILE_SHARING_SCHEMA_ID))
cc_sharing_panel_setup_bluetooth_sharing_dialog (self);
else
gtk_widget_hide (WID ("bluetooth-sharing-button"));
/* media sharing */
cc_sharing_panel_setup_media_sharing_dialog (self);
/* personal file sharing */
if (cc_sharing_panel_check_schema_available (self, FILE_SHARING_SCHEMA_ID))
cc_sharing_panel_setup_personal_file_sharing_dialog (self);
else
gtk_widget_hide (WID ("personal-file-sharing-button"));
/* remote login */
cc_sharing_panel_setup_remote_login_dialog (self);
/* screen sharing */
if (cc_sharing_panel_check_schema_available (self, VINO_SCHEMA_ID))
cc_sharing_panel_setup_screen_sharing_dialog (self);
else
gtk_widget_hide (WID ("screen-sharing-button"));
/* make sure the hostname entry isn't focused by default */
g_signal_connect_swapped (self, "map", G_CALLBACK (gtk_widget_grab_focus),
WID ("main-list-box"));
}
CcSharingPanel *
cc_sharing_panel_new (void)
{
return g_object_new (CC_TYPE_SHARING_PANEL, NULL);
}