Commit 6dd8aabe authored by Dan Winship's avatar Dan Winship

Probably the very last new config dialog ever. (Ha ha). From Anna, based

	* mail-config.glade: Probably the very last new config dialog
	ever. (Ha ha). From Anna, based on a story by me.

	* mail-account-gui.c: New code for the new mail-config.glade. This
	abstracts out all of the common code between the account editor
	and the druid. It also handles the spiffy new provider-specific
	config stuff.

	FIXME: The code to check if a service is ok or not is no longer
	there... waiting until the online/offline stuff from the shell
	appears.

	* mail-account-editor.c, mail-config-druid.c: These are much
	smaller now, since most of the interesting bits moved to
	mail-account-gui.c

	* mail-accounts.c: Add an enabled/disabled column/button to
	replace the checkbox that used to be in the editor, because it
	really makes more sense to have it out here. This looks ugly.
	Probably ought to ETable it...
	(load_accounts): Fill in the enabled column.
	(mail_select, mail_unselect): toggle the sensitivity and name of
	the Enable/Disable button appropriately
	(mail_able): Handle the enable/disable button.

	* mail-config.c: Remove reply-to from MailConfigIdentity since it
	didn't belong there (and wasn't being saved anyway).
	(mail_config_check_service): Simplify this a bit. This really
	needs to pop up a dialog with a "connecting..." message and a
	cancel button.

svn path=/trunk/; revision=8971
parent 0b8af6dc
2001-03-27 Dan Winship <danw@ximian.com>
* mail-config.glade: Probably the very last new config dialog
ever. (Ha ha). From Anna, based on a story by me.
* mail-account-gui.c: New code for the new mail-config.glade. This
abstracts out all of the common code between the account editor
and the druid. It also handles the spiffy new provider-specific
config stuff.
FIXME: The code to check if a service is ok or not is no longer
there... waiting until the online/offline stuff from the shell
appears.
* mail-account-editor.c, mail-config-druid.c: These are much
smaller now, since most of the interesting bits moved to
mail-account-gui.c
* mail-accounts.c: Add an enabled/disabled column/button to
replace the checkbox that used to be in the editor, because it
really makes more sense to have it out here. This looks ugly.
Probably ought to ETable it...
(load_accounts): Fill in the enabled column.
(mail_select, mail_unselect): toggle the sensitivity and name of
the Enable/Disable button appropriately
(mail_able): Handle the enable/disable button.
* mail-config.c: Remove reply-to from MailConfigIdentity since it
didn't belong there (and wasn't being saved anyway).
(mail_config_check_service): Simplify this a bit. This really
needs to pop up a dialog with a "connecting..." message and a
cancel button.
* mail-ops.c (uid_cachename_hack): Kludge, copied+modified from
mail_config_folder_to_cachename to deal with the different
behavior of the URL code now. Will go away when the keep-on-server
code moves.
(get_folderinfo_get): Only pass "subscribed_only" to
camel_store_get_folder_info if the store supports subscriptions...
* mail-local.c (local_provider): Update this to reflect the
CamelProvider structure change
2001-03-26 Jeffrey Stedfast <fejj@ximian.com>
* mail-callbacks.c (transfer_msg): Add "vtrash" as an allowed mail
......
......@@ -55,6 +55,8 @@ evolution_mail_SOURCES = \
mail-accounts.h \
mail-account-editor.c \
mail-account-editor.h \
mail-account-gui.c \
mail-account-gui.h \
mail-autofilter.c \
mail-autofilter.h \
mail-callbacks.c \
......
This diff is collapsed.
......@@ -28,57 +28,20 @@ extern "C" {
#pragma }
#endif /* __cplusplus */
#include <gnome.h>
#include <glade/glade.h>
#include <camel.h>
#include "mail-config.h"
#include <libgnomeui/gnome-dialog.h>
#include "mail-account-gui.h"
#define MAIL_ACCOUNT_EDITOR_TYPE (mail_account_editor_get_type ())
#define MAIL_ACCOUNT_EDITOR(o) (GTK_CHECK_CAST ((o), MAIL_ACCOUNT_EDITOR_TYPE, MailAccountEditor))
#define MAIL_ACCOUNT_EDITOR_CLASS(k) (GTK_CHECK_CLASS_CAST((k), MAIL_ACCOUNT_EDITOR_TYPE, MailAccountEditorClass))
#define IS_MAIL_ACCOUNT_EDITOR(o) (GTK_CHECK_TYPE ((o), MAIL_ACCOUNT_EDITOR_TYPE))
#define IS_MAIL_ACCOUNT_EDITOR_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), MAIL_ACCOUNT_EDITOR_TYPE))
#define MAIL_IS_ACCOUNT_EDITOR(o) (GTK_CHECK_TYPE ((o), MAIL_ACCOUNT_EDITOR_TYPE))
#define MAIL_IS_ACCOUNT_EDITOR_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), MAIL_ACCOUNT_EDITOR_TYPE))
struct _MailAccountEditor {
GnomeDialog parent;
const MailConfigAccount *account;
GladeXML *gui;
/* Identity / General */
GtkEntry *account_name;
GtkEntry *name;
GtkEntry *email;
GtkEntry *reply_to;
GtkEntry *organization;
GnomeFileEntry *signature;
/* Source */
GtkWidget *source_type; /* this is generic because we don't know the widget-type */
GtkEntry *source_host;
GtkEntry *source_user;
GtkEntry *source_passwd;
GtkEntry *source_path;
GtkCheckButton *source_save_passwd;
GtkOptionMenu *source_auth;
GtkCheckButton *keep_on_server;
GtkCheckButton *source_auto_check;
GtkSpinButton *source_auto_timeout;
GtkCheckButton *source_enabled;
/* Transport */
GtkWidget *transport_type; /* Same here... */
GtkEntry *transport_host;
GtkOptionMenu *transport_auth;
GtkEntry *transport_user;
GtkEntry *transport_passwd;
GtkCheckButton *transport_save_passwd;
const CamelProvider *transport;
MailAccountGui *gui;
GtkNotebook *notebook;
};
typedef struct _MailAccountEditor MailAccountEditor;
......@@ -92,7 +55,7 @@ typedef struct {
GtkType mail_account_editor_get_type (void);
MailAccountEditor *mail_account_editor_new (const MailConfigAccount *account);
MailAccountEditor *mail_account_editor_new (MailConfigAccount *account);
#ifdef __cplusplus
}
......
This diff is collapsed.
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* Authors:
* Jeffrey Stedfast <fejj@ximian.com>
* Dan Winship <danw@ximian.com>
*
* Copyright 2001 Ximian, Inc. (www.ximian.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 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., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*
*/
#ifndef MAIL_ACCOUNT_GUI_H
#define MAIL_ACCOUNT_GUI_H
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#include <gtk/gtk.h>
#include <libgnomeui/gnome-file-entry.h>
#include <glade/glade-xml.h>
#include <camel/camel-provider.h>
#include "mail-config.h"
typedef struct {
GtkOptionMenu *type;
GtkEntry *hostname;
GtkEntry *username;
GtkEntry *path;
GtkToggleButton *use_ssl;
GtkOptionMenu *authtype;
GtkWidget *authitem;
GtkToggleButton *remember;
GtkButton *check_supported;
CamelProvider *provider;
} MailAccountGuiService;
typedef struct {
GtkWidget *top;
MailConfigAccount *account;
GladeXML *xml;
/* identity */
GtkEntry *full_name;
GtkEntry *email_address;
GtkEntry *organization;
GnomeFileEntry *signature;
/* incoming mail */
MailAccountGuiService source;
GtkToggleButton *source_auto_check;
GtkSpinButton *source_auto_check_min;
/* extra incoming config */
GHashTable *extra_config;
/* outgoing mail */
MailAccountGuiService transport;
GtkToggleButton *transport_needs_auth;
/* account management */
GtkEntry *account_name;
GtkToggleButton *default_account;
} MailAccountGui;
MailAccountGui *mail_account_gui_new (MailConfigAccount *account);
void mail_account_gui_setup (MailAccountGui *gui, GtkWidget *top);
gboolean mail_account_gui_save (MailAccountGui *gui);
void mail_account_gui_destroy (MailAccountGui *gui);
gboolean mail_account_gui_identity_complete (MailAccountGui *gui);
gboolean mail_account_gui_source_complete (MailAccountGui *gui);
gboolean mail_account_gui_transport_complete (MailAccountGui *gui);
gboolean mail_account_gui_management_complete (MailAccountGui *gui);
void mail_account_gui_build_extra_conf (MailAccountGui *gui, const char *url);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MAIL_ACCOUNT_GUI_H */
......@@ -102,7 +102,7 @@ load_accounts (MailAccountsDialog *dialog)
while (node) {
CamelURL *url;
gchar *text[2];
gchar *text[3];
account = node->data;
......@@ -110,17 +110,17 @@ load_accounts (MailAccountsDialog *dialog)
url = camel_url_new (account->source->url, NULL);
else
url = NULL;
text[0] = g_strdup (account->name);
text[1] = g_strdup_printf ("%s%s", url && url->protocol ? url->protocol : _("None"),
text[0] = (account->source && account->source->enabled) ? "+" : "";
text[1] = account->name;
text[2] = g_strdup_printf ("%s%s", url && url->protocol ? url->protocol : _("None"),
account->default_account ? _(" (default)") : "");
if (url)
camel_url_free (url);
gtk_clist_append (dialog->mail_accounts, text);
g_free (text[0]);
g_free (text[1]);
g_free (text[2]);
/* set the account on the row */
gtk_clist_set_row_data (dialog->mail_accounts, i, (gpointer) account);
......@@ -132,23 +132,31 @@ load_accounts (MailAccountsDialog *dialog)
gtk_clist_thaw (dialog->mail_accounts);
}
#ifdef ENABLE_NTTP
static void
load_news (MailAccountsDialog *dialog)
{
/* FIXME: implement */
;
}
#endif
/* mail callbacks */
static void
mail_select (GtkCList *clist, gint row, gint column, GdkEventButton *event, gpointer data)
{
MailAccountsDialog *dialog = data;
MailConfigAccount *account = gtk_clist_get_row_data (clist, row);
dialog->accounts_row = row;
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_edit), TRUE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_delete), TRUE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_default), TRUE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_able), TRUE);
if (account->source && account->source->enabled)
gtk_label_set_text (GTK_LABEL (GTK_BIN (dialog->mail_able)->child), _("Disable"));
else
gtk_label_set_text (GTK_LABEL (GTK_BIN (dialog->mail_able)->child), _("Enable"));
}
static void
......@@ -160,6 +168,7 @@ mail_unselect (GtkCList *clist, gint row, gint column, GdkEventButton *event, gp
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_edit), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_delete), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_default), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_able), FALSE);
}
static void
......@@ -197,7 +206,7 @@ mail_edit (GtkButton *button, gpointer data)
MailAccountsDialog *dialog = data;
if (dialog->accounts_row >= 0) {
const MailConfigAccount *account;
MailConfigAccount *account;
MailAccountEditor *editor;
account = gtk_clist_get_row_data (dialog->mail_accounts, dialog->accounts_row);
......@@ -259,6 +268,7 @@ mail_delete (GtkButton *button, gpointer data)
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_edit), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_delete), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_default), FALSE);
gtk_widget_set_sensitive (GTK_WIDGET (dialog->mail_able), FALSE);
}
}
}
......@@ -281,6 +291,24 @@ mail_default (GtkButton *button, gpointer data)
}
}
static void
mail_able (GtkButton *button, gpointer data)
{
MailAccountsDialog *dialog = data;
const MailConfigAccount *account;
if (dialog->accounts_row >= 0) {
int row;
row = dialog->accounts_row;
account = gtk_clist_get_row_data (dialog->mail_accounts, row);
account->source->enabled = !account->source->enabled;
mail_config_write ();
load_accounts (dialog);
gtk_clist_select_row (dialog->mail_accounts, row, 0);
}
}
#ifdef ENABLE_NNTP
/* news callbacks */
static void
......@@ -446,7 +474,7 @@ construct (MailAccountsDialog *dialog)
GladeXML *gui;
GtkWidget *notebook;
gui = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", "mail-accounts-dialog");
gui = glade_xml_new (EVOLUTION_GLADEDIR "/mail-config.glade", NULL);
dialog->gui = gui;
/* get our toplevel widget */
......@@ -480,6 +508,9 @@ construct (MailAccountsDialog *dialog)
dialog->mail_default = GTK_BUTTON (glade_xml_get_widget (gui, "cmdMailDefault"));
gtk_signal_connect (GTK_OBJECT (dialog->mail_default), "clicked",
GTK_SIGNAL_FUNC (mail_default), dialog);
dialog->mail_able = GTK_BUTTON (glade_xml_get_widget (gui, "cmdMailAble"));
gtk_signal_connect (GTK_OBJECT (dialog->mail_able), "clicked",
GTK_SIGNAL_FUNC (mail_able), dialog);
#if defined (ENABLE_NNTP)
dialog->news_accounts = GTK_CLIST (glade_xml_get_widget (gui, "clistAccounts"));
......
......@@ -54,6 +54,7 @@ struct _MailAccountsDialog {
GtkButton *mail_edit;
GtkButton *mail_delete;
GtkButton *mail_default;
GtkButton *mail_able;
const GSList *news;
gint news_row;
......
This diff is collapsed.
......@@ -32,74 +32,24 @@ extern "C" {
#include <glade/glade.h>
#include <camel.h>
#include "shell/Evolution.h"
#include "mail-account-gui.h"
#define MAIL_CONFIG_DRUID_TYPE (mail_config_druid_get_type ())
#define MAIL_CONFIG_DRUID(o) (GTK_CHECK_CAST ((o), MAIL_CONFIG_DRUID_TYPE, MailConfigDruid))
#define MAIL_CONFIG_DRUID_CLASS(k) (GTK_CHECK_CLASS_CAST((k), MAIL_CONFIG_DRUID_TYPE, MailConfigDruidClass))
#define IS_MAIL_CONFIG_DRUID(o) (GTK_CHECK_TYPE ((o), MAIL_CONFIG_DRUID_TYPE))
#define IS_MAIL_CONFIG_DRUID_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), MAIL_CONFIG_DRUID_TYPE))
#define MAIL_IS_CONFIG_DRUID(o) (GTK_CHECK_TYPE ((o), MAIL_CONFIG_DRUID_TYPE))
#define MAIL_IS_CONFIG_DRUID_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), MAIL_CONFIG_DRUID_TYPE))
struct _MailConfigDruid {
typedef struct {
GtkWindow parent;
GNOME_Evolution_Shell shell;
GladeXML *gui;
GList *providers;
GnomeDruid *druid;
/* account management */
GtkWidget *account_text;
GtkEntry *account_name;
GtkCheckButton *default_account;
/* identity */
GtkWidget *identity_text;
GtkEntry *full_name;
GtkEntry *email_address;
GtkEntry *organization;
GnomeFileEntry *signature;
/* incoming mail */
GtkWidget *incoming_text;
GtkOptionMenu *incoming_type;
GtkEntry *incoming_hostname;
GtkEntry *incoming_username;
GtkEntry *incoming_path;
GtkCheckButton *incoming_keep_mail;
GtkCheckButton *incoming_auto_check;
GtkSpinButton *incoming_auto_check_min;
GtkCheckButton *incoming_check_settings;
/* source authentication */
gboolean have_source_auth_page;
GtkWidget *source_auth_text;
GtkOptionMenu *source_auth_type;
GtkEntry *source_password;
GtkCheckButton *save_source_password;
/* outgoing mail */
GtkWidget *outgoing_text;
GtkOptionMenu *outgoing_type;
GtkEntry *outgoing_hostname;
GtkCheckButton *outgoing_requires_auth;
GtkCheckButton *outgoing_check_settings;
/* transport authentication */
gboolean have_transport_auth_page;
GtkWidget *transport_auth_text;
GtkOptionMenu *transport_auth_type;
GtkEntry *transport_username;
GtkEntry *transport_password;
GtkCheckButton *save_transport_password;
const CamelProvider *source_provider;
const CamelProvider *transport_provider;
};
MailAccountGui *gui;
typedef struct _MailConfigDruid MailConfigDruid;
GNOME_Evolution_Shell shell;
gboolean identity_copied;
CamelProvider *last_source;
} MailConfigDruid;
typedef struct {
GtkWindowClass parent_class;
......@@ -115,13 +65,8 @@ MailConfigDruid *mail_config_druid_new (GNOME_Evolution_Shell shell);
char *mail_config_druid_get_account_name (MailConfigDruid *druid);
gboolean mail_config_druid_get_default_account (MailConfigDruid *druid);
char *mail_config_druid_get_full_name (MailConfigDruid *druid);
char *mail_config_druid_get_email_address (MailConfigDruid *druid);
char *mail_config_druid_get_reply_to (MailConfigDruid *druid);
char *mail_config_druid_get_organization (MailConfigDruid *druid);
char *mail_config_druid_get_sigfile (MailConfigDruid *druid);
char *mail_config_druid_get_source_url (MailConfigDruid *druid);
gboolean mail_config_druid_get_keep_mail_on_server (MailConfigDruid *druid);
gboolean mail_config_druid_get_save_source_password (MailConfigDruid *druid);
gboolean mail_config_druid_get_auto_check (MailConfigDruid *druid);
......
......@@ -69,7 +69,6 @@ identity_copy (const MailConfigIdentity *id)
new = g_new0 (MailConfigIdentity, 1);
new->name = g_strdup (id->name);
new->address = g_strdup (id->address);
new->reply_to = g_strdup (id->reply_to);
new->organization = g_strdup (id->organization);
new->signature = g_strdup (id->signature);
......@@ -84,7 +83,6 @@ identity_destroy (MailConfigIdentity *id)
g_free (id->name);
g_free (id->address);
g_free (id->reply_to);
g_free (id->organization);
g_free (id->signature);
......@@ -238,9 +236,6 @@ config_read (void)
path = g_strdup_printf ("identity_name_%d", i);
id->name = gnome_config_get_string (path);
g_free (path);
path = g_strdup_printf ("identity_replyto_%d", i);
id->reply_to = gnome_config_get_string (path);
g_free (path);
path = g_strdup_printf ("identity_address_%d", i);
id->address = gnome_config_get_string (path);
g_free (path);
......@@ -309,6 +304,7 @@ config_read (void)
}
gnome_config_pop_prefix ();
#ifdef ENABLE_NNTP
/* News */
str = g_strdup_printf ("=%s/config/News=/Sources/", evolution_dir);
gnome_config_push_prefix (str);
......@@ -328,6 +324,7 @@ config_read (void)
config->news = g_slist_append (config->news, n);
}
gnome_config_pop_prefix ();
#endif
/* Format */
str = g_strdup_printf ("=%s/config/Mail=/Format/send_html",
......@@ -472,6 +469,7 @@ mail_config_write (void)
}
gnome_config_pop_prefix ();
#ifdef ENABLE_NNTP
/* News */
str = g_strdup_printf ("=%s/config/News=/Sources/", evolution_dir);
gnome_config_push_prefix (str);
......@@ -490,6 +488,7 @@ mail_config_write (void)
g_free (path);
}
gnome_config_pop_prefix ();
#endif
gnome_config_sync ();
}
......@@ -880,9 +879,8 @@ mail_config_folder_to_cachename (CamelFolder *folder, const char *prefix)
struct _check_msg {
struct _mail_msg msg;
char *url;
const char *url;
CamelProviderType type;
gboolean connect;
GList **authtypes;
gboolean *success;
};
......@@ -891,66 +889,49 @@ static void check_service_check(struct _mail_msg *mm)
{
struct _check_msg *m = (struct _check_msg *)mm;
CamelService *service = NULL;
if (m->authtypes) {
service = camel_session_get_service (session, m->url, m->type, &mm->ex);
if (!service)
return;
if (m->connect)
*m->authtypes = camel_service_query_auth_types (service, &mm->ex);
else
*m->authtypes = g_list_copy (service->provider->authtypes);
} else if (m->connect) {
service = camel_session_get_service_connected (session, m->url, m->type, &mm->ex);
}
if (service)
camel_object_unref (CAMEL_OBJECT (service));
*m->success = !camel_exception_is_set(&mm->ex);
}
service = camel_session_get_service (session, m->url, m->type, &mm->ex);
if (!service)
return;
static void check_service_free(struct _mail_msg *mm)
{
struct _check_msg *m = (struct _check_msg *)mm;
if (m->authtypes)
*m->authtypes = camel_service_query_auth_types (service, &mm->ex);
else
camel_service_connect (service, &mm->ex);
g_free(m->url);
camel_object_unref (CAMEL_OBJECT (service));
*m->success = !camel_exception_is_set(&mm->ex);
}
static struct _mail_msg_op check_service_op = {
NULL,
check_service_check,
NULL,
check_service_free
NULL
};
/**
* mail_config_check_service:
* @url: service url
* @type: provider type
* @connect: whether or not the check service should connect
* @authtypes: list of auth types gathered by this method
*
* Checks the service for validity. If @connect is TRUE then a
* connection with the server is attempted and if successful will fill
* in the @authtypes list. If @connect is FALSE then @authtypes will
* be generated without a connection and thus will not necessarily
* reflect what the server supports.
* @authtypes: set to list of supported authtypes on return if non-%NULL.
*
* Returns TRUE on success or FALSE on error.
* Checks the service for validity. If @authtypes is non-%NULL, it will
* be filled in with a list of supported authtypes.
*
* Return value: %TRUE on success or %FALSE on error.
**/
gboolean
mail_config_check_service (CamelURL *url, CamelProviderType type, gboolean connect, GList **authtypes)
mail_config_check_service (const char *url, CamelProviderType type, GList **authtypes)
{
gboolean ret = FALSE;
struct _check_msg *m;
int id;
m = mail_msg_new(&check_service_op, NULL, sizeof(*m));
m->url = camel_url_to_string(url, TRUE);
m->url = url;
m->type = type;
m->connect = connect;
m->authtypes = authtypes;
m->success = &ret;
......
This diff is collapsed.
......@@ -34,7 +34,6 @@ extern "C" {
typedef struct {
gchar *name;
gchar *address;
gchar *reply_to;
gchar *organization;
gchar *signature;
} MailConfigIdentity;
......@@ -44,9 +43,8 @@ typedef struct {
gboolean keep_on_server;
gboolean auto_check;
gint auto_check_time;
gboolean enabled;
gboolean save_passwd;
gboolean enabled;
} MailConfigService;
typedef struct {
......@@ -132,7 +130,7 @@ GSList *mail_config_get_sources (void);
/* static utility functions */
char *mail_config_folder_to_cachename (CamelFolder *folder, const char *prefix);
gboolean mail_config_check_service (CamelURL *url, CamelProviderType type, gboolean connect, GList **authtypes);
gboolean mail_config_check_service (const char *url, CamelProviderType type, GList **authtypes);
#ifdef __cplusplus
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment