blob: 499452481bd16ac123e5d67f97914297b5e2da09 [file] [log] [blame]
/*
* Copyright (C) 2015-2018 Savoir-faire Linux Inc.
* Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
*
* 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 3 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.
*/
#include "generalsettingsview.h"
// GTK+ related
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <glib.h>
// LRC
#include <person.h>
#include <categorizedhistorymodel.h>
#include <media/recordingmodel.h>
// Ring client
#include "utils/files.h"
#include "avatarmanipulation.h"
enum
{
PROP_RING_MAIN_WIN_PNT = 1,
};
struct _GeneralSettingsView
{
GtkScrolledWindow parent;
};
struct _GeneralSettingsViewClass
{
GtkScrolledWindowClass parent_class;
};
typedef struct _GeneralSettingsViewPrivate GeneralSettingsViewPrivate;
struct _GeneralSettingsViewPrivate
{
GSettings *settings;
/* Rint settings */
GtkWidget *checkbutton_autostart;
GtkWidget *checkbutton_showstatusicon;
GtkWidget *checkbutton_bringtofront;
GtkWidget *checkbutton_callnotifications;
GtkWidget *checkbutton_pendingnotifications;
GtkWidget *checkbutton_chatnotifications;
GtkWidget *checkbutton_chatdisplaylinks;
GtkWidget *checkbutton_searchentryplacescall;
GtkWidget *radiobutton_chatright;
GtkWidget *radiobutton_chatbottom;
GtkWidget *button_choose_downloads_directory;
/* history settings */
GtkWidget *adjustment_history_duration;
GtkWidget *button_clear_history;
/* ring main window pointer */
GtkWidget* ring_main_window_pnt;
};
G_DEFINE_TYPE_WITH_PRIVATE(GeneralSettingsView, general_settings_view, GTK_TYPE_SCROLLED_WINDOW);
#define GENERAL_SETTINGS_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GENERAL_SETTINGS_VIEW_TYPE, GeneralSettingsViewPrivate))
enum {
CLEAR_ALL_HISTORY,
UPDATE_DOWNLOAD_FOLDER,
LAST_SIGNAL
};
static guint general_settings_view_signals[LAST_SIGNAL] = { 0 };
static void
general_settings_view_dispose(GObject *object)
{
GeneralSettingsViewPrivate *priv = GENERAL_SETTINGS_VIEW_GET_PRIVATE(object);
g_clear_object(&priv->settings);
G_OBJECT_CLASS(general_settings_view_parent_class)->dispose(object);
}
static gboolean
clear_history_dialog(GeneralSettingsView *self)
{
gboolean response = FALSE;
GtkWidget *dialog = gtk_message_dialog_new(NULL,
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL,
_("This is a destructive operation. Are you sure you want to delete all of your chat and call history?"));
gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE);
/* get parent window so we can center on it */
GtkWidget *parent = gtk_widget_get_toplevel(GTK_WIDGET(self));
if (gtk_widget_is_toplevel(parent)) {
gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER_ON_PARENT);
}
switch (gtk_dialog_run(GTK_DIALOG(dialog))) {
case GTK_RESPONSE_OK:
response = TRUE;
break;
default:
response = FALSE;
break;
}
gtk_widget_destroy(dialog);
return response;
}
static void
clear_history(G_GNUC_UNUSED GtkWidget *button, GeneralSettingsView *self)
{
g_return_if_fail(IS_GENERAL_SETTINGS_VIEW(self));
if (clear_history_dialog(self) )
g_signal_emit(G_OBJECT(self), general_settings_view_signals[CLEAR_ALL_HISTORY], 0);
}
static void
update_downloads_button_label(GeneralSettingsView *self)
{
GeneralSettingsViewPrivate *priv = GENERAL_SETTINGS_VIEW_GET_PRIVATE(self);
// Get folder name
const gchar *folder_dirname = g_path_get_basename(g_variant_get_string(g_settings_get_value(priv->settings, "download-folder"), NULL));
gtk_button_set_label(GTK_BUTTON(priv->button_choose_downloads_directory), folder_dirname);
}
static void
change_prefered_directory (gchar * directory, GeneralSettingsView *self)
{
g_return_if_fail(IS_GENERAL_SETTINGS_VIEW(self));
GeneralSettingsViewPrivate *priv = GENERAL_SETTINGS_VIEW_GET_PRIVATE(self);
priv->settings = g_settings_new_full(get_ring_schema(), NULL, NULL);
g_settings_set_value(priv->settings, "download-folder", g_variant_new("s", directory));
update_downloads_button_label(self);
}
static void
choose_downloads_directory(GeneralSettingsView *self)
{
g_return_if_fail(IS_GENERAL_SETTINGS_VIEW(self));
GeneralSettingsViewPrivate *priv = GENERAL_SETTINGS_VIEW_GET_PRIVATE(self);
gint res;
gchar* filename = nullptr;
if (!priv->ring_main_window_pnt) {
g_debug("Internal error: NULL main window pointer in GeneralSettingsView.");
return;
}
GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Choose download folder"),
GTK_WINDOW(priv->ring_main_window_pnt),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
_("_Cancel"),
GTK_RESPONSE_CANCEL,
_("_Save"),
GTK_RESPONSE_ACCEPT,
NULL);
res = gtk_dialog_run (GTK_DIALOG(dialog));
if (res == GTK_RESPONSE_ACCEPT) {
auto chooser = GTK_FILE_CHOOSER(dialog);
filename = gtk_file_chooser_get_filename(chooser);
}
gtk_widget_destroy (dialog);
if (!filename) return;
// set download folder
change_prefered_directory(filename, self);
g_signal_emit(G_OBJECT(self), general_settings_view_signals[UPDATE_DOWNLOAD_FOLDER], 0, filename);
}
static void
general_settings_view_init(GeneralSettingsView *self)
{
gtk_widget_init_template(GTK_WIDGET(self));
GeneralSettingsViewPrivate *priv = GENERAL_SETTINGS_VIEW_GET_PRIVATE(self);
priv->settings = g_settings_new_full(get_ring_schema(), NULL, NULL);
/* bind client option to gsettings */
g_settings_bind(priv->settings, "start-on-login",
priv->checkbutton_autostart, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "show-status-icon",
priv->checkbutton_showstatusicon, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "bring-window-to-front",
priv->checkbutton_bringtofront, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "enable-call-notifications",
priv->checkbutton_callnotifications, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "enable-display-links",
priv->checkbutton_chatdisplaylinks, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "enable-pending-notifications",
priv->checkbutton_pendingnotifications, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "enable-chat-notifications",
priv->checkbutton_chatnotifications, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "search-entry-places-call",
priv->checkbutton_searchentryplacescall, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "chat-pane-horizontal",
priv->radiobutton_chatright, "active",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind(priv->settings, "chat-pane-horizontal",
priv->radiobutton_chatbottom, "active",
(GSettingsBindFlags) (G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN));
g_settings_bind(priv->settings, "history-limit",
priv->adjustment_history_duration, "value",
G_SETTINGS_BIND_DEFAULT);
/* Set-up download directory settings, default if none specified */
auto* download_directory_variant = g_settings_get_value(priv->settings, "download-folder");
char* download_directory_value;
g_variant_get(download_directory_variant, "&s", &download_directory_value);
std::string default_download_dir = {};
if (auto* directory = g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD))
default_download_dir = directory;
else
default_download_dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
auto current_value = std::string(download_directory_value);
if (current_value.empty()) {
g_settings_set_value(priv->settings, "download-folder", g_variant_new("s", default_download_dir.c_str()));
}
update_downloads_button_label(self);
/* clear history */
g_signal_connect(priv->button_clear_history, "clicked", G_CALLBACK(clear_history), self);
}
static void
general_settings_view_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GeneralSettingsView *self = GENERAL_SETTINGS_VIEW (object);
GeneralSettingsViewPrivate *priv = GENERAL_SETTINGS_VIEW_GET_PRIVATE(self);
if (property_id == PROP_RING_MAIN_WIN_PNT) {
GtkWidget *ring_main_window_pnt = (GtkWidget*) g_value_get_pointer(value);
if (!ring_main_window_pnt) {
g_debug("Internal error: NULL main window pointer passed to set_property");
return;
}
priv->ring_main_window_pnt = ring_main_window_pnt;
}
else {
// Invalid property id passed
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
general_settings_view_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GeneralSettingsView *self = GENERAL_SETTINGS_VIEW (object);
GeneralSettingsViewPrivate *priv = GENERAL_SETTINGS_VIEW_GET_PRIVATE(self);
if (property_id == PROP_RING_MAIN_WIN_PNT) {
g_value_set_pointer(value, priv->ring_main_window_pnt);
}
else {
// Invalid property id passed
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
general_settings_view_class_init(GeneralSettingsViewClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = general_settings_view_dispose;
gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
"/cx/ring/RingGnome/generalsettingsview.ui");
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, checkbutton_autostart);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, checkbutton_showstatusicon);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, checkbutton_bringtofront);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, checkbutton_callnotifications);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, checkbutton_chatdisplaylinks);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, checkbutton_pendingnotifications);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, checkbutton_chatnotifications);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, checkbutton_searchentryplacescall);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, radiobutton_chatright);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, radiobutton_chatbottom);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, adjustment_history_duration);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, button_clear_history);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), GeneralSettingsView, button_choose_downloads_directory);
general_settings_view_signals[CLEAR_ALL_HISTORY] = g_signal_new (
"clear-all-history",
G_TYPE_FROM_CLASS(klass),
(GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
0,
nullptr,
nullptr,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
general_settings_view_signals[UPDATE_DOWNLOAD_FOLDER] = g_signal_new("update-download-folder",
G_TYPE_FROM_CLASS(klass),
(GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
0,
nullptr,
nullptr,
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE,
1, G_TYPE_STRING);
/* Define class properties: e.g. pointer to main window, etc.*/
object_class->set_property = general_settings_view_set_property;
object_class->get_property = general_settings_view_get_property;
GParamFlags flags = (GParamFlags) (G_PARAM_READWRITE);
g_object_class_install_property (object_class, PROP_RING_MAIN_WIN_PNT,
g_param_spec_pointer ("ring_main_window_pnt",
"RingMainWindow pointer",
"Pointer to the Ring Main Window. This property is used by modal dialogs.",
flags));
}
GtkWidget *
general_settings_view_new(GtkWidget* ring_main_window_pointer)
{
gpointer view = g_object_new(GENERAL_SETTINGS_VIEW_TYPE, NULL);
// set_up ring main window pointer (needed by modal dialogs)
GValue val = G_VALUE_INIT;
g_value_init (&val, G_TYPE_POINTER);
g_value_set_pointer (&val, ring_main_window_pointer);
g_object_set_property (G_OBJECT (view), "ring_main_window_pnt", &val);
g_value_unset (&val);
GeneralSettingsViewPrivate *priv = GENERAL_SETTINGS_VIEW_GET_PRIVATE(GENERAL_SETTINGS_VIEW (view));
g_signal_connect_swapped(priv->button_choose_downloads_directory, "clicked", G_CALLBACK(choose_downloads_directory), view);
return (GtkWidget *)view;
}