This repository has been archived on 2024-07-15. You can view files and clone it, but cannot push or open issues or pull requests.
hedera/vn/vn-login.c

495 lines
12 KiB
C

/*
* Copyright (C) 2012 - Juan Ferrer Toribio
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "vn-login.h"
#define LOGIN_UI _GUI_DIR"/login.glade"
#define IS_DEFINED(string) (string && g_strcmp0 (string, ""))
#define BUILDER_GET(obj, name) ((gpointer) gtk_builder_get_object (obj, name))
typedef struct
{
VnLogin * obj;
gchar * user;
gchar * pass;
DbConn * conn;
GThread * thread;
gboolean connected;
GError * error;
}
ConnectData;
void vn_login_cb_gui_logout (VnGui * gui, VnLogin * obj);
void vn_login_cb_gui_exit (VnGui * gui, VnLogin * obj);
G_DEFINE_TYPE (VnLogin, vn_login, G_TYPE_OBJECT);
/**
* vn_login_new:
*
* Creates a new Gui object.
*
* Return value: the created #VnLogin
**/
VnLogin * vn_login_new (const gchar * application_id)
{
return g_object_new (VN_TYPE_LOGIN, "application-id", application_id, NULL);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private
/*
* Frees the #ConnectData struct
*/
void connect_data_free (ConnectData * connect_data)
{
if (connect_data->error)
g_error_free (connect_data->error);
g_free (connect_data->user);
g_free (connect_data->pass);
g_object_unref (connect_data->conn);
g_object_unref (connect_data->obj);
g_thread_unref (connect_data->thread);
g_free (connect_data);
}
/*
* Shows the login window to the user.
*/
static void vn_login_show (VnLogin * obj)
{
gboolean autologin = FALSE;
if (!obj->window)
{
gchar * user;
gchar * pass;
GError * err = NULL;
GtkBuilder * builder = gtk_builder_new ();
if (gtk_builder_add_from_file (builder, LOGIN_UI, &err))
{
obj->window = BUILDER_GET (builder, "window");
obj->user = BUILDER_GET (builder, "user");
obj->pass = BUILDER_GET (builder, "password");
obj->remember = BUILDER_GET (builder, "remember");
obj->connect = BUILDER_GET (builder, "connect");
obj->settings_button = BUILDER_GET (builder, "settings");
obj->spinner = BUILDER_GET (builder, "spinner");
obj->settings_dialog = BUILDER_GET (builder, "settings-dialog");
obj->plugin = BUILDER_GET (builder, "plugin");
obj->host = BUILDER_GET (builder, "host");
obj->schema = BUILDER_GET (builder, "schema");
obj->ssl_ca = BUILDER_GET (builder, "ssl-ca");
gtk_builder_connect_signals (builder, obj);
user = g_settings_get_string (obj->settings, "user");
pass = g_settings_get_string (obj->settings, "pass");
if (user && g_strcmp0 (user, ""))
gtk_entry_set_text (obj->user, user);
if (pass && g_strcmp0 (pass, ""))
{
gchar * aux = pass;
pass = gvn_decode (aux);
gtk_entry_set_text (obj->pass, pass);
gtk_toggle_button_set_active (obj->remember, TRUE);
g_free (aux);
autologin = TRUE;
}
g_free (user);
g_free (pass);
}
else if (err)
{
g_warning ("VnLogin: %s", err->message);
g_clear_error (&err);
}
g_object_unref (builder);
}
gtk_widget_show_all (GTK_WIDGET (obj->window));
gtk_widget_grab_focus (GTK_WIDGET (obj->user));
if (autologin)
gtk_button_clicked (obj->connect);
}
/*
* Enables/disables the #GtkSpinner at login dialog.
*/
static void vn_login_set_loading (VnLogin * obj, gboolean loading)
{
gtk_widget_set_sensitive (GTK_WIDGET (obj->connect), !loading);
gtk_widget_set_sensitive (GTK_WIDGET (obj->settings_button), !loading);
gtk_widget_set_sensitive (GTK_WIDGET (obj->user), !loading);
gtk_widget_set_sensitive (GTK_WIDGET (obj->pass), !loading);
gtk_widget_set_sensitive (GTK_WIDGET (obj->remember), !loading);
if (loading)
{
gtk_widget_show (obj->spinner);
gtk_widget_hide (GTK_WIDGET (obj->connect));
}
else
{
gtk_widget_hide (obj->spinner);
gtk_widget_show (GTK_WIDGET (obj->connect));
}
}
/*
* Frees the GUI object.
*/
static void vn_login_free_gui (VnLogin * obj)
{
if (obj->gui)
{
g_object_disconnect (obj->gui
,"any_signal", vn_login_cb_gui_exit, obj
,"any_signal", vn_login_cb_gui_logout, obj
,NULL
);
g_clear_object (&obj->gui);
}
}
/*
* Shows the settings dialog.
*/
void vn_login_cb_settings_clicked (GtkButton * button, VnLogin * obj)
{
gchar * plugin = g_settings_get_string (obj->settings, "plugin");
gchar * host = g_settings_get_string (obj->settings, "host");
gchar * schema = g_settings_get_string (obj->settings, "schema");
gchar * ssl_ca = g_settings_get_string (obj->settings, "ssl-ca");
gtk_entry_set_text (obj->plugin, plugin);
gtk_entry_set_text (obj->host, host);
gtk_entry_set_text (obj->schema, schema);
gtk_entry_set_text (obj->ssl_ca, ssl_ca);
gtk_dialog_run (obj->settings_dialog);
g_free (plugin);
g_free (host);
g_free (schema);
g_free (ssl_ca);
}
/*
* Hides the settings dialog.
*/
void vn_login_cb_settings_cancel_clicked (GtkButton * button, VnLogin * obj)
{
gtk_widget_hide (GTK_WIDGET (obj->settings_dialog));
}
/*
* Hides the settings dialog when escape is pressed.
*/
void vn_login_settings_on_delete_event (GtkWidget * settings_dialog)
{
gtk_widget_hide (settings_dialog);
}
/*
* Applies the changes made on settings dialog.
*/
void vn_login_cb_settings_apply_clicked (GtkButton * button, VnLogin * obj)
{
const gchar * plugin = gtk_entry_get_text (obj->plugin);
const gchar * host = gtk_entry_get_text (obj->host);
const gchar * schema = gtk_entry_get_text (obj->schema);
const gchar * ssl_ca = gtk_entry_get_text (obj->ssl_ca);
g_settings_set_string (obj->settings, "plugin", plugin);
g_settings_set_string (obj->settings, "host", host);
g_settings_set_string (obj->settings, "schema", schema);
g_settings_set_string (obj->settings, "ssl-ca", ssl_ca);
gtk_widget_hide (GTK_WIDGET (obj->settings_dialog));
}
/*
* Shows the login dialog when user logout from GUI.
*/
void vn_login_cb_gui_logout (VnGui * gui, VnLogin * obj)
{
g_settings_set_string (obj->settings, "pass", "");
vn_login_free_gui (obj);
vn_login_show (obj);
}
/*
* Destroys the login dialog when user exits from GUI.
*/
void vn_login_cb_gui_exit (VnGui * gui, VnLogin * obj)
{
vn_login_free_gui (obj);
gtk_widget_destroy (GTK_WIDGET (obj->window));
}
/*
* Saves the login information and opens the main GUI.
*/
static gboolean vn_login_done (ConnectData * connect_data)
{
VnLogin * obj = connect_data->obj;
if (connect_data->connected)
{
const gchar * user;
user = gtk_entry_get_text (obj->user);
g_settings_set_string (obj->settings, "user", user);
if (gtk_toggle_button_get_active (obj->remember))
{
const gchar * pass = gtk_entry_get_text (obj->pass);
gchar * aux = gvn_encode (pass);
gtk_toggle_button_set_active (obj->remember, FALSE);
g_settings_set_string (obj->settings, "pass", aux);
g_free (aux);
}
gtk_entry_set_text (obj->pass, "");
gtk_widget_hide (GTK_WIDGET (obj->window));
obj->gui = vn_gui_new (obj->app, connect_data->conn);
g_object_connect (obj->gui
,"signal::logout", vn_login_cb_gui_logout, obj
,"signal::exit", vn_login_cb_gui_exit, obj
,NULL
);
vn_gui_open (obj->gui);
}
else
{
GtkWidget * dialog;
dialog = gtk_message_dialog_new (obj->window
,GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
,GTK_MESSAGE_ERROR
,GTK_BUTTONS_OK
,_("Login error")
);
gtk_window_set_title (GTK_WINDOW (dialog), _("Login error"));
if (connect_data->error)
{
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", connect_data->error->message);
if (connect_data->error->code == DB_CONN_ERROR_BAD_LOGIN)
gtk_entry_set_text (obj->pass, "");
}
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (GTK_WIDGET (dialog));
vn_login_show (obj);
}
vn_login_set_loading (obj, FALSE);
return G_SOURCE_REMOVE;
}
/*
* Thread function that tries to open the connection asynchronously.
*/
static void vn_login_thread (ConnectData * connect_data)
{
gchar * plugin;
gchar * host;
gchar * schema;
gchar * ssl_ca;
VnLogin * obj = connect_data->obj;
plugin = g_settings_get_string (obj->settings, "plugin");
host = g_settings_get_string (obj->settings, "host");
schema = g_settings_get_string (obj->settings, "schema");
ssl_ca = g_settings_get_string (obj->settings, "ssl-ca");
if (IS_DEFINED (plugin) && IS_DEFINED (host) && IS_DEFINED (schema))
{
if (db_conn_load_plugin (connect_data->conn, plugin, &connect_data->error))
{
if (IS_DEFINED (ssl_ca))
db_conn_set_ssl (connect_data->conn, ssl_ca);
connect_data->connected = db_conn_open (connect_data->conn
,host
,schema
,connect_data->user
,connect_data->pass
,&connect_data->error
);
}
}
else
connect_data->error = g_error_new (
VN_LOGIN_LOG_DOMAIN
,VN_LOGIN_ERR_BAD_SETTINGS
,_("Bad connection settings, please check it.")
);
g_free (plugin);
g_free (host);
g_free (schema);
g_free (ssl_ca);
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
(GSourceFunc) vn_login_done, connect_data, (GDestroyNotify) connect_data_free);
}
/*
* Opens the connection.
*/
void vn_login_cb_connect_clicked (GtkButton * button, VnLogin * obj)
{
ConnectData * connect_data;
vn_login_set_loading (obj, TRUE);
connect_data = g_new (ConnectData, 1);
connect_data->obj = g_object_ref (obj);
connect_data->user = g_strdup (gtk_entry_get_text (obj->user));
connect_data->pass = g_strdup (gtk_entry_get_text (obj->pass));
connect_data->conn = db_conn_new ();
connect_data->connected = FALSE;
connect_data->error = NULL;
connect_data->thread = g_thread_new ("vn-login",
(GThreadFunc) vn_login_thread, connect_data);
}
/*
* Closes the application when login window is destroyed.
*/
void vn_login_cb_destroyed (GtkWidget * window, VnLogin * obj)
{
obj->window = NULL;
gtk_main_quit ();
}
void vn_login_cb_pass_show (GtkEntry * entry, GtkEntryIconPosition * pos,
GdkEvent * event, VnLogin * obj)
{
gtk_entry_set_visibility (entry, TRUE);
}
void vn_login_cb_pass_hide (GtkEntry * entry, GtkEntryIconPosition * pos,
GdkEvent * event, VnLogin * obj)
{
gtk_entry_set_visibility (entry, FALSE);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public
/**
* vn_login_run:
* @obj: a #VnLogin
*
* Starts the main gui application.
**/
void vn_login_run (VnLogin * obj)
{
GApplication * app;
g_return_if_fail (VN_IS_LOGIN (obj));
app = G_APPLICATION (obj->app);
if (g_application_register (app, NULL, NULL)
&& !g_application_get_is_remote (app))
{
g_object_set (gtk_settings_get_default (), "gtk-button-images", TRUE, NULL);
vn_login_show (obj);
gtk_main ();
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties
enum
{
PROP_APPLICATION_ID = 1
};
static void vn_login_set_property (VnLogin * obj, guint id,
const GValue * value, GParamSpec * pspec)
{
switch (id)
{
case PROP_APPLICATION_ID:
{
const gchar * id = g_value_get_string (value);
obj->app = gtk_application_new (id, G_APPLICATION_FLAGS_NONE);
obj->settings = g_settings_new (id);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
}
}
static void vn_login_get_property (VnLogin * obj, guint id,
GValue * value, GParamSpec * pspec)
{
switch (id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Class
static void vn_login_init (VnLogin * obj)
{
obj->gui = NULL;
obj->window = NULL;
obj->settings = NULL;
obj->app = NULL;
}
static void vn_login_finalize (VnLogin * obj)
{
vn_login_free_gui (obj);
g_clear_object (&obj->settings);
g_clear_object (&obj->app);
G_OBJECT_CLASS (vn_login_parent_class)->finalize (G_OBJECT (obj));
}
static void vn_login_class_init (VnLoginClass * k)
{
GObjectClass * klass = G_OBJECT_CLASS (k);
klass->finalize = (GObjectFinalizeFunc) vn_login_finalize;
klass->set_property = (GObjectSetPropertyFunc) vn_login_set_property;
klass->get_property = (GObjectGetPropertyFunc) vn_login_get_property;
g_object_class_install_property (klass, PROP_APPLICATION_ID,
g_param_spec_string ("application-id"
,_("Application id")
,_("The application identifier")
,"app.default"
,G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY
));
}