495 lines
12 KiB
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
|
|
));
|
|
}
|