Commit 74989e98 authored by Murray Cumming's avatar Murray Cumming
Browse files

C++11: Use a to_utype() template method instead of static_cast<int>.

As suggested in Item 10 of
Effective Modern C++ by Scott Meyers.
parent 2bafe10c
......@@ -348,7 +348,7 @@ void AppWindow::init_menus()
m_action_menu_developer_usermode =
m_refActionGroup_Developer->add_action_radio_integer("usermode",
sigc::mem_fun(*this, &AppWindow::on_menu_developer_usermode),
static_cast<int>(AppState::userlevels::OPERATOR) );
Utils::to_utype(AppState::userlevels::OPERATOR) );
action = m_refActionGroup_Developer->add_action("database-preferences",
sigc::mem_fun(*m_pFrame, &Frame_Glom::on_menu_developer_database_preferences) );
......@@ -524,7 +524,7 @@ void AppWindow::on_menu_developer_usermode(int parameter)
if(!m_pFrame)
return;
const bool developer = parameter == static_cast<int>(AppState::userlevels::DEVELOPER);
const bool developer = parameter == Utils::to_utype(AppState::userlevels::DEVELOPER);
bool changed = false;
if(developer)
......@@ -570,7 +570,7 @@ static bool hostname_is_localhost(const Glib::ustring& hostname)
void AppWindow::ui_warning_load_failed(int failure_code)
{
if(failure_code == static_cast<int>(Document::LoadFailureCodes::NOT_FOUND))
if(failure_code == Utils::to_utype(Document::LoadFailureCodes::NOT_FOUND))
{
//TODO: Put this in the generic bakery code.
ui_warning(_("Open Failed"),
......@@ -580,7 +580,7 @@ void AppWindow::ui_warning_load_failed(int failure_code)
//but the initial/welcome dialog doesn't yet update its list when the
//recent history changes.
}
else if(failure_code == static_cast<int>(Document::load_failure_codes::FILE_VERSION_TOO_NEW))
else if(failure_code == Utils::to_utype(Document::load_failure_codes::FILE_VERSION_TOO_NEW))
{
ui_warning(_("Open Failed"),
_("The document could not be opened because it was created or modified by a newer version of Glom."));
......@@ -837,7 +837,7 @@ bool AppWindow::check_document_hosting_mode_is_supported(Document* document)
default:
{
//on_document_load() should have checked for this already, informing the user.
std::cerr << G_STRFUNC << ": Unhandled hosting mode: " << static_cast<int>(document->get_hosting_mode()) << std::endl;
std::cerr << G_STRFUNC << ": Unhandled hosting mode: " << Utils::to_utype(document->get_hosting_mode()) << std::endl;
g_assert_not_reached();
break;
}
......@@ -1328,7 +1328,7 @@ bool AppWindow::offer_new_or_existing()
#endif
case Dialog_ExistingOrNew::Action::NONE:
default:
std::cerr << G_STRFUNC << ": Unhandled action: " << static_cast<int>(dialog->get_action()) << std::endl;
std::cerr << G_STRFUNC << ": Unhandled action: " << Utils::to_utype(dialog->get_action()) << std::endl;
g_assert_not_reached();
break;
}
......
......@@ -19,6 +19,7 @@
#include "config.h"
#include <glom/bakery/appwindow_withdoc.h>
#include <glom/bakery/dialog_offersave.h>
#include <libglom/utils.h>
#include <giomm/file.h>
#include <algorithm>
#include <glibmm/i18n-lib.h>
......@@ -150,7 +151,7 @@ bool AppWindow_WithDoc::open_document(const Glib::ustring& file_uri)
ui_warning_load_failed(failure_code);
//Make sure that non-existant files are removed from the history list:
if(failure_code == static_cast<int>(Document::LoadFailureCodes::NOT_FOUND))
if(failure_code == Glom::Utils::to_utype(Document::LoadFailureCodes::NOT_FOUND))
document_history_remove(file_uri);
//re-initialize document.
......
......@@ -20,6 +20,7 @@
#include <gtkmm/box.h>
#include <glom/bakery/dialog_offersave.h>
#include <glom/appwindow.h>
#include <libglom/utils.h>
#include <glibmm/convert.h>
#include <glibmm/i18n-lib.h>
......@@ -52,9 +53,9 @@ Dialog_OfferSave::Dialog_OfferSave(const Glib::ustring& file_uri)
set_secondary_text(get_confirmation_message(file_uri));
add_button(_("Discard"), static_cast<int>(enumButtons::Discard));
auto cancel_button = add_button(_("_Cancel"), static_cast<int>(enumButtons::Cancel));
add_button(_("_Save"), static_cast<int>(enumButtons::Save));
add_button(_("Discard"), Glom::Utils::to_utype(enumButtons::Discard));
auto cancel_button = add_button(_("_Cancel"), Glom::Utils::to_utype(enumButtons::Cancel));
add_button(_("_Save"), Glom::Utils::to_utype(enumButtons::Save));
// Otherwise Discard has focus initially which seems inconvenient:
cancel_button->grab_focus();
......
......@@ -32,13 +32,13 @@ namespace Glom
Box_WithButtons::Box_WithButtons()
: Gtk::Box(Gtk::ORIENTATION_VERTICAL),
m_Box_Buttons(Gtk::ORIENTATION_HORIZONTAL, static_cast<int>(UiUtils::DefaultSpacings::SMALL)),
m_Box_Buttons(Gtk::ORIENTATION_HORIZONTAL, Utils::to_utype(UiUtils::DefaultSpacings::SMALL)),
m_Button_Cancel(_("_Cancel"))
{
//m_pDocument = nullptr;
//set_border_width(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
set_spacing(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
//set_border_width(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
set_spacing(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
//Connect signals:
m_Button_Cancel.signal_clicked().connect(sigc::mem_fun(*this, &Box_WithButtons::on_Button_Cancel));
......@@ -46,13 +46,13 @@ Box_WithButtons::Box_WithButtons()
Box_WithButtons::Box_WithButtons(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& /* builder */)
: Gtk::Box(cobject),
m_Box_Buttons(Gtk::ORIENTATION_HORIZONTAL, static_cast<int>(UiUtils::DefaultSpacings::SMALL)),
m_Box_Buttons(Gtk::ORIENTATION_HORIZONTAL, Utils::to_utype(UiUtils::DefaultSpacings::SMALL)),
m_Button_Cancel(_("_Cancel"))
{
//m_pDocument = nullptr;
//set_border_width(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
set_spacing(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
//set_border_width(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
set_spacing(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
//Connect signals:
m_Button_Cancel.signal_clicked().connect(sigc::mem_fun(*this, &Box_WithButtons::on_Button_Cancel));
......@@ -60,7 +60,7 @@ Box_WithButtons::Box_WithButtons(BaseObjectType* cobject, const Glib::RefPtr<Gtk
Box_WithButtons::Box_WithButtons(BaseObjectType* cobject)
: Gtk::Box(cobject),
m_Box_Buttons(Gtk::ORIENTATION_HORIZONTAL, static_cast<int>(UiUtils::DefaultSpacings::SMALL)),
m_Box_Buttons(Gtk::ORIENTATION_HORIZONTAL, Utils::to_utype(UiUtils::DefaultSpacings::SMALL)),
m_Button_Cancel(_("_Cancel"))
{
}
......
......@@ -29,7 +29,7 @@ namespace Glom
FileChooser_Export::FileChooser_Export()
: Gtk::FileChooserDialog(_("Export to File"), Gtk::FILE_CHOOSER_ACTION_SAVE),
m_extra_widget(Gtk::ORIENTATION_HORIZONTAL, static_cast<int>(UiUtils::DefaultSpacings::SMALL)),
m_extra_widget(Gtk::ORIENTATION_HORIZONTAL, Utils::to_utype(UiUtils::DefaultSpacings::SMALL)),
#ifndef GLOM_ENABLE_CLIENT_ONLY
m_button_format(_("Define Data _Format"), true /* use mnenomic */),
m_pDialogLayout(nullptr),
......
......@@ -75,7 +75,7 @@ Frame_Glom::Frame_Glom(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
: PlaceHolder(cobject, builder),
m_pLabel_Table_DataMode(nullptr),
m_pLabel_Table_FindMode(nullptr),
m_Box_RecordsCount(Gtk::ORIENTATION_HORIZONTAL, static_cast<int>(UiUtils::DefaultSpacings::SMALL)),
m_Box_RecordsCount(Gtk::ORIENTATION_HORIZONTAL, Utils::to_utype(UiUtils::DefaultSpacings::SMALL)),
m_Button_FindAll(_("Find All")),
m_stack_mode(nullptr),
m_pBox_Tables(nullptr),
......@@ -107,7 +107,7 @@ Frame_Glom::Frame_Glom(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>
//QuickFind widgets:
//We don't use Glade for these, so it easier to modify them for the Maemo port.
m_pBox_QuickFind = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, static_cast<int>(UiUtils::DefaultSpacings::SMALL)));
m_pBox_QuickFind = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, Utils::to_utype(UiUtils::DefaultSpacings::SMALL)));
Gtk::Label* label = Gtk::manage(new Gtk::Label(_("Quick _search:"), true));
m_pBox_QuickFind->pack_start(*label, Gtk::PACK_SHRINK);
......
......@@ -506,7 +506,7 @@ int main(int argc, char* argv[])
const auto started = connection_pool->startup( sigc::ptr_fun(&on_startup_progress) );
if(started != Glom::ConnectionPool::Backend::StartupErrors::NONE)
{
std::cerr << G_STRFUNC << ": connection_pool->startup(): result=" << static_cast<int>(started) << std::endl;
std::cerr << G_STRFUNC << ": connection_pool->startup(): result=" << Glom::Utils::to_utype(started) << std::endl;
cleanup();
}
g_assert(started == Glom::ConnectionPool::Backend::StartupErrors::NONE);
......
......@@ -185,7 +185,7 @@ void ConnectionPool::setup_from_document(const Document* document)
default:
//on_document_load() should have checked for this already, informing the user.
std::cerr << G_STRFUNC << ": Unhandled hosting mode: " << static_cast<int>(document->get_hosting_mode()) << std::endl;
std::cerr << G_STRFUNC << ": Unhandled hosting mode: " << Utils::to_utype(document->get_hosting_mode()) << std::endl;
g_assert_not_reached();
break;
}
......
......@@ -557,7 +557,7 @@ Glib::ustring Field::get_sql_type() const
if(strType == "unknowntype")
{
std::cerr << G_STRFUNC << ": returning unknowntype for field name=" << get_name() << ", glom_type=" << static_cast<int>(get_glom_type()) << ", gda_type=" << (int)m_field_info->get_g_type() << std::endl;
std::cerr << G_STRFUNC << ": returning unknowntype for field name=" << get_name() << ", glom_type=" << Utils::to_utype(get_glom_type()) << ", gda_type=" << (int)m_field_info->get_g_type() << std::endl;
}
return strType;
......@@ -617,7 +617,7 @@ GType Field::get_gda_type_for_glom_type(Field::glom_field_type glom_type)
if(ideal_gda_type == G_TYPE_NONE)
{
std::cerr << G_STRFUNC << ": Returning G_TYPE_NONE for glom_type=" << static_cast<int>(glom_type) << std::endl;
std::cerr << G_STRFUNC << ": Returning G_TYPE_NONE for glom_type=" << Utils::to_utype(glom_type) << std::endl;
}
//std::cout << "debug: " << G_STRFUNC << ": returning: " << g_type_name(ideal_gda_type) << std::endl;
......
......@@ -22,6 +22,7 @@
#include <iostream> //For debug output
#include <libgda/gda-util.h> // For gda_g_type_to_string
#include <libglom/connectionpool.h>
#include <libglom/utils.h>
namespace Glom
{
......@@ -68,7 +69,7 @@ FieldTypes::FieldTypes(const Glib::RefPtr<Gnome::Gda::Connection>& gda_connectio
for(int i = 0; i < rows; ++i)
{
const auto value_name = data_model_tables->get_value_at(static_cast<int>(GlomGdaDataModelTypesColumns::NAME), i);
const auto value_name = data_model_tables->get_value_at(Utils::to_utype(GlomGdaDataModelTypesColumns::NAME), i);
//Get the types's string representation:
Glib::ustring schema_type_string;
......@@ -77,7 +78,7 @@ FieldTypes::FieldTypes(const Glib::RefPtr<Gnome::Gda::Connection>& gda_connectio
if(!schema_type_string.empty())
{
const auto value_gdatype = data_model_tables->get_value_at(static_cast<int>(GlomGdaDataModelTypesColumns::GTYPE), i);
const auto value_gdatype = data_model_tables->get_value_at(Utils::to_utype(GlomGdaDataModelTypesColumns::GTYPE), i);
if(value_gdatype.get_value_type() == G_TYPE_STRING)
{
auto type_string = value_gdatype.get_string();
......
......@@ -577,12 +577,12 @@ Glib::ustring Conversions::get_text_for_gda_value(Field::glom_field_type glom_ty
//- UI-visible strings, but images should never be shown as text in the UI.
//- Values in SQL queries, but we only do that for clauses (where/sort/order)
// which should never use image values.
std::cerr << G_STRFUNC << ": Unexpected enumType::IMAGE field type: " << static_cast<int>(glom_type) << std::endl;
std::cerr << G_STRFUNC << ": Unexpected enumType::IMAGE field type: " << Utils::to_utype(glom_type) << std::endl;
return Glib::ustring();
}
else
{
std::cerr << G_STRFUNC << ": Unexpected glom field type: " << static_cast<int>(glom_type) << std::endl;
std::cerr << G_STRFUNC << ": Unexpected glom field type: " << Utils::to_utype(glom_type) << std::endl;
return value.to_string();
}
}
......@@ -695,7 +695,7 @@ Gnome::Gda::Value Conversions::parse_value(Field::glom_field_type glom_type, con
{
//This function is only used for :
//- UI-visible strings, but images should never be entered as text in the UI.
std::cerr << G_STRFUNC << ": Unexpected enumType::IMAGE field type: " << static_cast<int>(glom_type) << std::endl;
std::cerr << G_STRFUNC << ": Unexpected enumType::IMAGE field type: " << Utils::to_utype(glom_type) << std::endl;
return Gnome::Gda::Value();
}
......
......@@ -907,7 +907,7 @@ type_vec_fields get_fields_for_table_from_database(const Glib::ustring& table_na
Glib::RefPtr<Gnome::Gda::Column> field_info = Gnome::Gda::Column::create();
//Get the field name:
const auto value_name = data_model_fields->get_value_at(static_cast<int>(GlomGdaDataModelFieldColumns::NAME), row);
const auto value_name = data_model_fields->get_value_at(Utils::to_utype(GlomGdaDataModelFieldColumns::NAME), row);
if(value_name.get_value_type() == G_TYPE_STRING)
{
if(value_name.get_string().empty())
......@@ -920,7 +920,7 @@ type_vec_fields get_fields_for_table_from_database(const Glib::ustring& table_na
}
//Get the field type:
const auto value_fieldtype = data_model_fields->get_value_at(static_cast<int>(GlomGdaDataModelFieldColumns::GTYPE), row);
const auto value_fieldtype = data_model_fields->get_value_at(Utils::to_utype(GlomGdaDataModelFieldColumns::GTYPE), row);
if(value_fieldtype.get_value_type() == G_TYPE_STRING)
{
const auto type_string = value_fieldtype.get_string();
......@@ -931,12 +931,12 @@ type_vec_fields get_fields_for_table_from_database(const Glib::ustring& table_na
//Get the default value:
const Gnome::Gda::Value value_defaultvalue =
data_model_fields->get_value_at(static_cast<int>(GlomGdaDataModelFieldColumns::DEFAULTVALUE), row);
data_model_fields->get_value_at(Utils::to_utype(GlomGdaDataModelFieldColumns::DEFAULTVALUE), row);
if(value_defaultvalue.get_value_type() == G_TYPE_STRING)
field_info->set_default_value(value_defaultvalue);
//Get whether it can be null:
const auto value_notnull = data_model_fields->get_value_at(static_cast<int>(GlomGdaDataModelFieldColumns::NOTNULL), row);
const auto value_notnull = data_model_fields->get_value_at(Utils::to_utype(GlomGdaDataModelFieldColumns::NOTNULL), row);
if(value_notnull.get_value_type() == G_TYPE_BOOLEAN)
field_info->set_allow_null(value_notnull.get_boolean());
......
......@@ -18,6 +18,7 @@
#include "config.h"
#include <libglom/document/bakery/document.h>
#include <libglom/utils.h>
#include <giomm/file.h>
#include <iostream>
#include <glibmm/i18n-lib.h>
......@@ -115,7 +116,7 @@ bool Document::get_modified() const
bool Document::load(int& failure_code)
{
//Initialize the output parameter:
failure_code = static_cast<int>(LoadFailureCodes::NONE);
failure_code = Glom::Utils::to_utype(LoadFailureCodes::NONE);
auto bTest = read_from_disk(failure_code);
if(bTest)
......@@ -204,7 +205,7 @@ bool Document::save_before()
bool Document::read_from_disk(int& failure_code)
{
failure_code = static_cast<int>(LoadFailureCodes::NONE);
failure_code = Glom::Utils::to_utype(LoadFailureCodes::NONE);
m_strContents.erase();
......@@ -227,7 +228,7 @@ bool Document::read_from_disk(int& failure_code)
if(ex.code() == Gio::Error::NOT_FOUND)
failure_code = static_cast<int>(LoadFailureCodes::NOT_FOUND);
failure_code = Glom::Utils::to_utype(LoadFailureCodes::NOT_FOUND);
// std::cout << " File not found: " << m_file_uri << std::endl;
// If the operation was not successful, print the error and abort
......
......@@ -2558,7 +2558,7 @@ bool Document::load_after(int& failure_code)
if(m_document_format_version > get_latest_known_document_format_version())
{
std::cerr << G_STRFUNC << ": Loading failed because format_version=" << m_document_format_version << ", but latest known format version is " << get_latest_known_document_format_version() << std::endl;
failure_code = static_cast<int>(load_failure_codes::FILE_VERSION_TOO_NEW);
failure_code = Utils::to_utype(load_failure_codes::FILE_VERSION_TOO_NEW);
return false;
}
......
......@@ -28,7 +28,7 @@ private:
TestWindow::TestWindow()
: m_box(Gtk::ORIENTATION_VERTICAL, static_cast<int>(Glom::UiUtils::DefaultSpacings::SMALL)),
: m_box(Gtk::ORIENTATION_VERTICAL, Utils::to_utype(Glom::UiUtils::DefaultSpacings::SMALL)),
m_button_start("Start"),
m_button_stop("Stop"),
m_avahi_publisher(nullptr)
......
......@@ -255,6 +255,13 @@ bool script_check_for_pygtk2(const Glib::ustring& script);
*/
bool get_resource_exists(const std::string& resource_path);
template<typename E>
constexpr typename std::underlying_type<E>::type
to_utype(E enumerator) noexcept
{
return static_cast<typename std::underlying_type<E>::type>(enumerator);
}
} //namespace Utils
} //namespace Glom
......
......@@ -39,8 +39,8 @@ Box_Data_Calendar_Related::Box_Data_Calendar_Related()
set_size_request(400, -1); //An arbitrary default.
m_Frame.add(m_calendar);
m_calendar.set_margin_start(static_cast<int>(UiUtils::DefaultSpacings::LARGE));
m_calendar.set_margin_top(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
m_calendar.set_margin_start(Utils::to_utype(UiUtils::DefaultSpacings::LARGE));
m_calendar.set_margin_top(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
m_calendar.show();
//m_calendar.set_show_details();
......@@ -101,8 +101,8 @@ bool Box_Data_Calendar_Related::init_db_details(const Glib::ustring& parent_tabl
m_Label.set_markup(UiUtils::bold_message(title));
m_Label.show();
m_calendar.set_margin_start(static_cast<int>(UiUtils::DefaultSpacings::LARGE));
m_calendar.set_margin_top(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
m_calendar.set_margin_start(Utils::to_utype(UiUtils::DefaultSpacings::LARGE));
m_calendar.set_margin_top(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
}
else
{
......
......@@ -40,7 +40,7 @@ namespace Glom
{
Box_Data_Details::Box_Data_Details(bool bWithNavButtons /* = true */)
: m_hbox_content(Gtk::ORIENTATION_HORIZONTAL, static_cast<int>(UiUtils::DefaultSpacings::SMALL)),
: m_hbox_content(Gtk::ORIENTATION_HORIZONTAL, Utils::to_utype(UiUtils::DefaultSpacings::SMALL)),
m_show_toolbar(false),
m_hbox_buttons(Gtk::ORIENTATION_HORIZONTAL),
m_Button_New(_("_Add"), true),
......@@ -58,19 +58,19 @@ Box_Data_Details::Box_Data_Details(bool bWithNavButtons /* = true */)
m_layout_name = "details";
m_hbox_buttons.set_layout(Gtk::BUTTONBOX_END);
m_hbox_buttons.set_spacing(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
m_hbox_buttons.set_spacing(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
add_view(&m_FlowTable); //Allow this to access the document too.
m_FlowTable.set_lines(1); //Sub-groups will have multiple columns (by default, there is one sub-group, with 2 columns).
m_FlowTable.set_horizontal_spacing(static_cast<int>(UiUtils::DefaultSpacings::SMALL)); //The default anyway.
m_FlowTable.set_vertical_spacing(static_cast<int>(UiUtils::DefaultSpacings::SMALL)); //The default anyway.
m_FlowTable.set_horizontal_spacing(Utils::to_utype(UiUtils::DefaultSpacings::SMALL)); //The default anyway.
m_FlowTable.set_vertical_spacing(Utils::to_utype(UiUtils::DefaultSpacings::SMALL)); //The default anyway.
//m_strHint = _("When you change the data in a field the database is updated immediately.\n Click [New] to add a new record.\n Leave automatic ID fields empty - they will be filled for you.");
//m_ScrolledWindow.set_border_width(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
//m_ScrolledWindow.set_border_width(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
// Allow vertical scrolling, but never scroll horizontally:
m_ScrolledWindow.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
......
......@@ -102,8 +102,8 @@ bool Box_Data_List_Related::init_db_details(const Glib::ustring& parent_table, b
if(!(m_Frame.get_label_widget()))
m_Frame.set_label_widget(m_Label);
m_AddDel.set_margin_start(static_cast<int>(UiUtils::DefaultSpacings::LARGE));
m_AddDel.set_margin_top(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
m_AddDel.set_margin_start(Utils::to_utype(UiUtils::DefaultSpacings::LARGE));
m_AddDel.set_margin_top(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
}
else
......
......@@ -43,8 +43,8 @@ Box_Data_Portal::Box_Data_Portal()
m_Label.show();
//The AddDel or Calendar is added to this:
//They must use child.set_margin_start(static_cast<int>(UiUtils::DefaultSpacings::LARGE)) and
//child.set_margin_top(static_cast<int>(UiUtils::DefaultSpacings::SMALL));
//They must use child.set_margin_start(Utils::to_utype(UiUtils::DefaultSpacings::LARGE)) and
//child.set_margin_top(Utils::to_utype(UiUtils::DefaultSpacings::SMALL));
add(m_Frame);
m_layout_name = "list_portal"; //Replaced by derived classes.
......
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