...
 
Commits (4)
......@@ -129,6 +129,7 @@ moody_sources = [
'src/gui-week.c',
'src/gui-resource.c',
'src/password.c',
'src/settings.c',
'src/utils.c',
]
......
......@@ -21,6 +21,9 @@
struct _GuiPassDialog
{
HdyDialog parent_instance;
MoodSettings *settings;
GtkButton *accept;
GtkButton *cancel;
GtkEntry *user_entry;
......@@ -31,23 +34,18 @@ struct _GuiPassDialog
G_DEFINE_TYPE (GuiPassDialog, gui_pass_dialog, HDY_TYPE_DIALOG)
// not perfect, but I don't want to start creating properties
// and getters and setters for something that works equally well
static pass_cb pass_changed_cb = NULL;
static gpointer pass_changed_cb_data;
GuiPassDialog *
gui_pass_dialog_new (GtkWindow *window,
const gchar *current_username,
pass_cb cb,
gpointer user_data)
gui_pass_dialog_new (GtkWindow *window,
MoodSettings *settings)
{
pass_changed_cb = cb;
pass_changed_cb_data = user_data;
GuiPassDialog *self = g_object_new (HDY_TYPE_GUI_PASS_DIALOG,
"use-header-bar", 1,
NULL);
self->settings = settings;
g_autofree const gchar *current_username;
g_object_get (self->settings, "username", &current_username, NULL);
// prefill the username
gtk_entry_set_text (self->user_entry, current_username);
......@@ -74,14 +72,9 @@ dialog_close_cb (GuiPassDialog *self, gint response)
case GTK_RESPONSE_CANCEL:
break;
case GTK_RESPONSE_ACCEPT:
{
const gchar *username = gtk_entry_get_text (self->user_entry);
const gchar *password = gtk_entry_get_text (self->pass_entry);
if (pass_changed_cb)
pass_changed_cb (pass_changed_cb_data, username, password);
else
g_warn_if_reached ();
}
g_object_set (self->settings,
"username", gtk_entry_get_text (self->user_entry),
"password", gtk_entry_get_text (self->pass_entry), NULL);
break;
default:
g_assert (0);
......
......@@ -18,14 +18,14 @@
#pragma once
#include "settings.h"
#include <gtk/gtk.h>
#define HANDY_USE_UNSTABLE_API
#include <handy.h>
typedef void (*pass_cb) (gpointer user_data, const gchar *username, const gchar *password);
#define HDY_TYPE_GUI_PASS_DIALOG (gui_pass_dialog_get_type())
G_DECLARE_FINAL_TYPE (GuiPassDialog, gui_pass_dialog, HDY, GUI_PASS_DIALOG, HdyDialog)
GuiPassDialog *gui_pass_dialog_new (GtkWindow *win, const gchar *current_username, pass_cb cb, gpointer user_data);
GuiPassDialog *gui_pass_dialog_new (GtkWindow *win, MoodSettings *settings);
......@@ -20,8 +20,8 @@
#include "gui-pass-dialog.h"
#include "gui-course.h"
#include "data-struct.h"
#include "settings.h"
#include "moodle-provider.h"
#include "password.h"
#include "config.h"
#include <glib/gi18n.h>
......@@ -32,7 +32,9 @@ struct _GuiWindow
{
GtkApplicationWindow parent_instance;
GSettings *settings;
MoodSettings *settings;
struct Course* courses;
guint course_count;
HdyLeaflet *header_box;
HdyLeaflet *content_box;
......@@ -41,8 +43,6 @@ struct _GuiWindow
//GtkToggleButton *search_button;
GtkStackSidebar *sidebar;
GtkStack *stack;
struct Course* courses;
guint course_count;
//HdySearchBar *search_bar;
//GtkEntry *search_entry;
HdyHeaderGroup *header_group;
......@@ -55,39 +55,31 @@ G_DEFINE_TYPE (GuiWindow, gui_window, GTK_TYPE_APPLICATION_WINDOW)
static void update_moodle_index (GuiWindow *self);
static void
initialize_moodle_provider (GuiWindow *self)
initialize_moodle_provider (MoodSettings *settings)
{
gchar *username, *password;
username = g_settings_get_string (self->settings, "username");
if (!moodle_password_get (username, &password))
g_error ("Could not get password\n");
g_autofree const gchar *username, *password;
g_object_get (settings, "username", &username,
"password", &password, NULL);
moodle_provider_init (MOODLE_MODE_ONLINE, username, password);
}
static void
pass_changed_cb (gpointer ptr, const gchar *username, const gchar *password)
pass_changed_cb (gpointer ptr)
{
GuiWindow *self = HDY_GUI_WINDOW (ptr);
g_settings_set_string (self->settings, "username", username);
if (!moodle_password_set (username, password)) {
g_warning ("Could not set password\n");
}
GuiWindow *self = ptr;
moodle_provider_disconnect ();
initialize_moodle_provider (self);
initialize_moodle_provider (self->settings);
update_moodle_index (self);
}
static void
activate_ask_pass (GSimpleAction *simple,
GVariant *parameter,
gpointer ptr)
gpointer self_ptr)
{
GuiWindow *self = ptr;
const gchar *current_username = g_settings_get_string (self->settings, "username");
self->dialog = gui_pass_dialog_new (GTK_WINDOW (self), current_username, pass_changed_cb, ptr);
GuiWindow *self = self_ptr;
self->dialog = gui_pass_dialog_new (GTK_WINDOW (self), self->settings);
gtk_widget_show (GTK_WIDGET (self->dialog));
}
......@@ -149,7 +141,7 @@ gui_window_key_pressed_cb (GtkWidget *sender,
if (self->course_count > 1) { // that's a little hackish, but works well enough
const gchar *name = gtk_stack_get_visible_child_name (self->stack);
for (guint i=0; i<self->course_count; i++) {
if (!g_strcmp0 (name, self->courses[i].name)) {
if (g_strcmp0 (name, self->courses[i].name != 0)) {
if (i > 0) { // we don't go before the first element
const gchar *target_name = self->courses[i-1].name;
gtk_stack_set_visible_child_name (self->stack, target_name);
......@@ -228,7 +220,9 @@ update_courses (GuiWindow *self)
self->courses[i].name);
}
// ellipsize the labels
// ellipsize the labels, this is a workaround.
// See https://source.puri.sm/Librem5/libhandy/issues/118 for the bug report
// and https://gitlab.gnugen.ch/afontain/moodle/issues/20
GtkWidget *scrolled_win = gtk_bin_get_child (GTK_BIN (self->sidebar));
GtkWidget *viewport = gtk_bin_get_child (GTK_BIN (scrolled_win));
GtkWidget *label_list = gtk_bin_get_child (GTK_BIN (viewport));
......@@ -289,6 +283,7 @@ gui_window_new (GtkApplication *application)
return g_object_new (HDY_TYPE_GUI_WINDOW, "application", application, NULL);
}
static void
gui_window_finalize (GObject *object)
{
......@@ -297,6 +292,7 @@ gui_window_finalize (GObject *object)
G_OBJECT_CLASS (gui_window_parent_class)->finalize (object);
}
static void
gui_window_class_init (GuiWindowClass *class)
{
......@@ -324,7 +320,6 @@ gui_window_class_init (GuiWindowClass *class)
}
static void
update_moodle_index (GuiWindow *self)
{
......@@ -350,9 +345,10 @@ gui_window_init (GuiWindow *self)
self->dialog = NULL;
gtk_widget_init_template (GTK_WIDGET (self));
self->settings = g_settings_new (APP_NAME);
self->settings = mood_settings_new ();
initialize_moodle_provider (self);
g_signal_connect_swapped (self->settings, "notify::password",
G_CALLBACK (pass_changed_cb), self);
const GActionEntry entries[] = {
{ "ask-pass", activate_ask_pass },
......@@ -362,8 +358,8 @@ gui_window_init (GuiWindow *self)
entries, G_N_ELEMENTS (entries),
self);
initialize_moodle_provider (self->settings);
hdy_leaflet_set_visible_child_name (self->content_box, "content");
update_header_bar (self);
update_moodle_index (self);
}
......@@ -199,21 +199,23 @@ moodle_downloaded_file_cb (GInputStream *is,
const char *header = soup_message_headers_get_one (headers, "Content-Disposition");
g_autofree char *real_filename = NULL, *name = NULL;
if (sscanf (header, "inline;" " filename=\"%m[^\"]\"", &name) == 1
|| sscanf (header, "attachment;"" filename=\"%m[^\"]\"", &name) == 1) {
if (sscanf (header, "inline;" " filename=\"%m[^\"]\"", &name) != 1
&& sscanf (header, "attachment;"" filename=\"%m[^\"]\"", &name) != 1) {
g_warning ("could not read header '%s' to get the filename\n", header);
} else { // we could get the file name
real_filename = get_resource_filename (RESOURCE_FILE, 0, name);
g_autofree gchar *path1 = g_filename_from_uri (real_filename, NULL, NULL);
g_autofree gchar *path2 = g_filename_from_uri (filename_looked_for, NULL, NULL);
if (g_strcmp0 (path1, path2)) { // paths are different: make a symlink!
if (g_strcmp0 (path1, path2) != 0) { // paths are different: make a symlink!
g_autoptr (GFile) link_file = g_file_new_for_uri (filename_looked_for);
g_file_make_symbolic_link (link_file, name, NULL, NULL);
// name is the name without the path: we want to make a relative link, so that's perfect
}
} else {
g_warning ("could not read header '%s'\n", header);
}
write_g_input_stream_to_file (is, real_filename ?: filename_looked_for);
......
/*
* Copyright 2019, Antoine Fontaine <antoine.fontaine@epfl.ch>
* I release this program under GNU GPLv3+.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#include "settings.h"
#include "password.h"
#include "config.h"
enum {
PROP_0,
PROP_SETTING_USERNAME,
PROP_SETTING_PASSWORD,
PROP_SETTING_USE_CACHE,
N_SETTINGS
};
GParamSpec *mood_settings_properties[N_SETTINGS] = { NULL, };
struct _MoodSettings
{
GObject parent_instance;
const gchar *username;
gboolean use_cache;
};
G_DEFINE_TYPE (MoodSettings, mood_settings, G_TYPE_OBJECT)
MoodSettings *
mood_settings_new (void)
{
return g_object_new (MOOD_TYPE_SETTINGS, NULL);
}
static void
mood_settings_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
MoodSettings *self = MOOD_MOOD_SETTINGS (object);
switch (property_id) {
case PROP_SETTING_USERNAME:
self->username = g_strdup(g_value_get_string (value));
break;
case PROP_SETTING_PASSWORD:
moodle_password_set (self->username, g_value_get_string (value));
break;
case PROP_SETTING_USE_CACHE:
self->use_cache = g_value_get_boolean (value);
break;
default:
// We don't have any other property...
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void
mood_settings_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
MoodSettings *self = MOOD_MOOD_SETTINGS (object);
switch (property_id) {
case PROP_SETTING_USERNAME:
if (!self->username)
g_warning ("That read isn't going well\n");
g_value_set_string (value, self->username);
break;
case PROP_SETTING_PASSWORD: {
gchar *password;
if (!moodle_password_get (self->username, &password))
g_error ("impossible to get saved password\n");
g_value_set_string (value, password);
break;
}
case PROP_SETTING_USE_CACHE:
g_value_set_boolean (value, self->use_cache);
break;
default:
// We don't have any other property...
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
break;
}
}
static void
mood_settings_class_init (MoodSettingsClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
//object_class->finalize = &mood_settings_finalize;
mood_settings_properties[PROP_SETTING_USERNAME] =
g_param_spec_string ("username", "username",
"The username we use to connect to moodle. At EPFL, this is your gaspard account.",
NULL,
G_PARAM_WRITABLE|G_PARAM_READABLE);
mood_settings_properties[PROP_SETTING_PASSWORD] =
g_param_spec_string ("password", "password",
"Your account's password",
NULL,
G_PARAM_WRITABLE|G_PARAM_READABLE);
mood_settings_properties[PROP_SETTING_USE_CACHE] =
g_param_spec_boolean ("use_cache", "use_cache",
"Whether to save to disk the responses the moodle provider gets",
TRUE,
G_PARAM_WRITABLE|G_PARAM_READABLE);
object_class->set_property = &mood_settings_set_property;
object_class->get_property = &mood_settings_get_property;
g_object_class_install_properties (object_class,
N_SETTINGS,
mood_settings_properties);
}
static void
mood_settings_init (MoodSettings *self)
{
//self->settings = g_settings_new (APP_NAME);
GSettings *settings = g_settings_new (APP_NAME);
self->username = NULL;
self->use_cache = -1;
g_settings_bind (settings, "username",
self, "username",
G_SETTINGS_BIND_DEFAULT);
g_settings_bind (settings, "use-cache",
self, "use-cache",
G_SETTINGS_BIND_DEFAULT);
}
\ No newline at end of file
/*
* Copyright 2019, Antoine Fontaine <antoine.fontaine@epfl.ch>
* I release this program under GNU GPLv3+.
*
* 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 <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define MOOD_TYPE_SETTINGS (mood_settings_get_type())
G_DECLARE_FINAL_TYPE (MoodSettings, mood_settings, MOOD, MOOD_SETTINGS, GObject)
MoodSettings *mood_settings_new (void);
G_END_DECLS