next region list fix from chris g; more tweaks to port matrix/ioselector; remove spurious _y_position from audio_region_view
git-svn-id: svn://localhost/ardour2/branches/3.0@3844 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
a9021cdd1d
commit
6129057f86
@ -442,13 +442,13 @@ AudioRegionView::setup_fade_handle_positions()
|
||||
double const handle_height = 5;
|
||||
|
||||
if (fade_in_handle) {
|
||||
fade_in_handle->property_y1() = _y_position + handle_pos;
|
||||
fade_in_handle->property_y2() = _y_position + handle_pos + handle_height;
|
||||
fade_in_handle->property_y1() = handle_pos;
|
||||
fade_in_handle->property_y2() = handle_pos + handle_height;
|
||||
}
|
||||
|
||||
if (fade_out_handle) {
|
||||
fade_out_handle->property_y1() = _y_position + handle_pos;
|
||||
fade_out_handle->property_y2() = _y_position + handle_pos + handle_height;
|
||||
fade_out_handle->property_y1() = handle_pos;
|
||||
fade_out_handle->property_y2() = handle_pos + handle_height;
|
||||
}
|
||||
}
|
||||
|
||||
@ -506,7 +506,7 @@ AudioRegionView::manage_zero_line ()
|
||||
}
|
||||
|
||||
if (_height >= 100) {
|
||||
double const wave_midpoint = _y_position + (_height - NAME_HIGHLIGHT_SIZE) / 2.0;
|
||||
double const wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0;
|
||||
zero_line->property_y1() = wave_midpoint;
|
||||
zero_line->property_y2() = wave_midpoint;
|
||||
zero_line->show();
|
||||
@ -587,16 +587,16 @@ AudioRegionView::reset_fade_in_shape_width (nframes_t width)
|
||||
|
||||
for (pi = 0, pc = 0; pc < npoints; ++pc) {
|
||||
(*points)[pi].set_x(1 + (pc * xdelta));
|
||||
(*points)[pi++].set_y(_y_position + 2 + (h - (curve[pc] * h)));
|
||||
(*points)[pi++].set_y(2 + (h - (curve[pc] * h)));
|
||||
}
|
||||
|
||||
/* fold back */
|
||||
|
||||
(*points)[pi].set_x(pwidth);
|
||||
(*points)[pi++].set_y(_y_position + 2);
|
||||
(*points)[pi++].set_y(2);
|
||||
|
||||
(*points)[pi].set_x(1);
|
||||
(*points)[pi++].set_y(_y_position + 2);
|
||||
(*points)[pi++].set_y(2);
|
||||
|
||||
/* connect the dots ... */
|
||||
|
||||
@ -673,16 +673,16 @@ AudioRegionView::reset_fade_out_shape_width (nframes_t width)
|
||||
|
||||
for (pi = 0, pc = 0; pc < npoints; ++pc) {
|
||||
(*points)[pi].set_x(_pixel_width - 1 - pwidth + (pc*xdelta));
|
||||
(*points)[pi++].set_y(_y_position + 2 + (h - (curve[pc] * h)));
|
||||
(*points)[pi++].set_y(2 + (h - (curve[pc] * h)));
|
||||
}
|
||||
|
||||
/* fold back */
|
||||
|
||||
(*points)[pi].set_x(_pixel_width);
|
||||
(*points)[pi++].set_y(_y_position + h);
|
||||
(*points)[pi++].set_y(h);
|
||||
|
||||
(*points)[pi].set_x(_pixel_width);
|
||||
(*points)[pi++].set_y(_y_position + 2);
|
||||
(*points)[pi++].set_y(2);
|
||||
|
||||
/* connect the dots ... */
|
||||
|
||||
|
@ -135,7 +135,6 @@ class AudioRegionView : public RegionView
|
||||
AudioRegionGainLine * gain_line;
|
||||
|
||||
double _amplitude_above_axis;
|
||||
double _y_position;
|
||||
|
||||
uint32_t _flags;
|
||||
uint32_t fade_color;
|
||||
|
@ -660,10 +660,10 @@ Editor::Editor ()
|
||||
region_list_display.append_column (_("M"), region_list_columns.muted);
|
||||
region_list_display.append_column (_("O"), region_list_columns.opaque);
|
||||
region_list_display.append_column (_("Used"), region_list_columns.used);
|
||||
region_list_display.append_column (_("Path to parent file"), region_list_columns.path);
|
||||
region_list_display.append_column (_("Path"), region_list_columns.path);
|
||||
region_list_display.set_headers_visible (true);
|
||||
region_list_display.set_grid_lines (TREE_VIEW_GRID_LINES_BOTH);
|
||||
|
||||
|
||||
CellRendererText* region_name_cell = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0));
|
||||
region_name_cell->property_editable() = true;
|
||||
region_name_cell->signal_edited().connect (mem_fun (*this, &Editor::region_name_edit));
|
||||
@ -699,7 +699,8 @@ Editor::Editor ()
|
||||
region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
|
||||
// region_list_display.signal_popup_menu().connect (bind (mem_fun (*this, &Editor::show_region_list_display_context_menu), 1, 0));
|
||||
|
||||
ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (mem_fun(*this, &Editor::redisplay_regions));
|
||||
//ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (mem_fun(*this, &Editor::redisplay_regions));
|
||||
ARDOUR_UI::instance()->secondary_clock.mode_changed.connect (mem_fun(*this, &Editor::update_all_region_rows));
|
||||
ARDOUR::Region::RegionPropertyChanged.connect (mem_fun(*this, &Editor::update_region_row));
|
||||
|
||||
named_selection_scroller.add (named_selection_display);
|
||||
|
@ -1108,6 +1108,8 @@ class Editor : public PublicEditor
|
||||
void populate_row (boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::Row const &);
|
||||
void update_region_row (boost::shared_ptr<ARDOUR::Region>);
|
||||
bool update_region_subrows (boost::shared_ptr<ARDOUR::Region>, Gtk::TreeModel::Row const &, int);
|
||||
void update_all_region_rows ();
|
||||
void update_all_region_subrows (Gtk::TreeModel::Row const &, int);
|
||||
bool no_region_list_redisplay;
|
||||
void insert_into_tmp_regionlist(boost::shared_ptr<ARDOUR::Region>);
|
||||
|
||||
|
@ -360,6 +360,7 @@ Editor::update_region_row (boost::shared_ptr<Region> region)
|
||||
if (!region || !session) {
|
||||
return;
|
||||
}
|
||||
|
||||
TreeModel::iterator i;
|
||||
TreeModel::Children rows = region_list_model->children();
|
||||
|
||||
@ -403,16 +404,61 @@ Editor::update_region_subrows (boost::shared_ptr<Region> region, TreeModel::Row
|
||||
}
|
||||
|
||||
if (!(*i).children().empty()) {
|
||||
|
||||
if (update_region_subrows(region, (*i), level + 1)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
Editor::update_all_region_rows ()
|
||||
{
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
TreeModel::iterator i;
|
||||
TreeModel::Children rows = region_list_model->children();
|
||||
|
||||
for (i = rows.begin(); i != rows.end(); ++i) {
|
||||
|
||||
boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
|
||||
|
||||
cerr << "level 1 : Updating " << region->name() << "\n";
|
||||
|
||||
if (!region->automatic()) {
|
||||
populate_row(region, (*i));
|
||||
}
|
||||
|
||||
if (!(*i).children().empty()) {
|
||||
update_all_region_subrows((*i), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::update_all_region_subrows (TreeModel::Row const &parent_row, int level)
|
||||
{
|
||||
TreeModel::iterator i;
|
||||
TreeModel::Children subrows = (*parent_row).children();
|
||||
|
||||
for (i = subrows.begin(); i != subrows.end(); ++i) {
|
||||
|
||||
boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
|
||||
|
||||
cerr << "level " << level << " : Updating " << region->name() << "\n";
|
||||
|
||||
if (!region->automatic()) {
|
||||
populate_row(region, (*i));
|
||||
}
|
||||
|
||||
if (!(*i).children().empty()) {
|
||||
update_all_region_subrows((*i), level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Editor::populate_row (boost::shared_ptr<Region> region, TreeModel::Row const &row)
|
||||
|
@ -210,6 +210,7 @@ IOSelectorWindow::IOSelectorWindow (
|
||||
: ArdourDialog ("I/O selector"),
|
||||
_selector (session, io, !for_input),
|
||||
add_button (_("Add Port")),
|
||||
disconnect_button (_("Disconnect All")),
|
||||
ok_button (can_cancel ? _("OK"): _("Close")),
|
||||
cancel_button (_("Cancel")),
|
||||
rescan_button (_("Rescan"))
|
||||
@ -218,7 +219,9 @@ IOSelectorWindow::IOSelectorWindow (
|
||||
add_events (Gdk::KEY_PRESS_MASK | Gdk::KEY_RELEASE_MASK);
|
||||
set_name ("IOSelectorWindow2");
|
||||
|
||||
// io->name_changed.connect (mem_fun(*this, &IOSelectorWindow::io_name_changed));
|
||||
disconnect_button.set_name ("IOSelectorButton");
|
||||
disconnect_button.set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::DISCONNECT, Gtk::ICON_SIZE_BUTTON)));
|
||||
get_action_area()->pack_start (disconnect_button, false, false);
|
||||
|
||||
if (_selector.maximum_rows() > _selector.n_rows()) {
|
||||
add_button.set_name ("IOSelectorButton");
|
||||
@ -254,6 +257,10 @@ IOSelectorWindow::IOSelectorWindow (
|
||||
get_vbox()->set_spacing (8);
|
||||
get_vbox()->pack_start (_selector);
|
||||
|
||||
suggestion.set_alignment (0.5, 0.5);
|
||||
suggestion_box.pack_start (suggestion, true, true);
|
||||
get_vbox()->pack_start (suggestion_box);
|
||||
|
||||
ok_button.signal_clicked().connect (mem_fun(*this, &IOSelectorWindow::accept));
|
||||
cancel_button.signal_clicked().connect (mem_fun(*this, &IOSelectorWindow::cancel));
|
||||
rescan_button.signal_clicked().connect (mem_fun(*this, &IOSelectorWindow::rescan));
|
||||
@ -262,10 +269,15 @@ IOSelectorWindow::IOSelectorWindow (
|
||||
|
||||
io_name_changed (this);
|
||||
ports_changed (IOChange (0), this);
|
||||
|
||||
leave_scroller ((GdkEventCrossing*) 0);
|
||||
|
||||
show_all ();
|
||||
|
||||
signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), this));
|
||||
|
||||
_selector.scrolled_window().add_events (Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
|
||||
_selector.scrolled_window().signal_enter_notify_event().connect (mem_fun (*this, &IOSelectorWindow::enter_scroller));
|
||||
_selector.scrolled_window().signal_leave_notify_event().connect (mem_fun (*this, &IOSelectorWindow::leave_scroller));
|
||||
}
|
||||
|
||||
IOSelectorWindow::~IOSelectorWindow()
|
||||
@ -273,6 +285,22 @@ IOSelectorWindow::~IOSelectorWindow()
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
IOSelectorWindow::enter_scroller (GdkEventCrossing* ignored)
|
||||
{
|
||||
cerr << "IN\n";
|
||||
suggestion.set_text (_("Click to connect. Ctrl-click to disconnect. Shift-click for cross-connect"));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
IOSelectorWindow::leave_scroller (GdkEventCrossing* ignored)
|
||||
{
|
||||
cerr << "OUT\n";
|
||||
suggestion.set_text (_("Right-click on individual port names for per-port operations"));
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
IOSelectorWindow::ports_changed (ARDOUR::IOChange change, void *src)
|
||||
{
|
||||
|
@ -61,16 +61,22 @@ class IOSelectorWindow : public ArdourDialog
|
||||
/* overall operation buttons */
|
||||
|
||||
Gtk::Button add_button;
|
||||
Gtk::Button disconnect_button;
|
||||
Gtk::Button ok_button;
|
||||
Gtk::Button cancel_button;
|
||||
Gtk::Button rescan_button;
|
||||
|
||||
Gtk::HBox suggestion_box;
|
||||
Gtk::Label suggestion;
|
||||
|
||||
void rescan ();
|
||||
void cancel ();
|
||||
void accept ();
|
||||
|
||||
void ports_changed (ARDOUR::IOChange change, void *src);
|
||||
void io_name_changed (void *src);
|
||||
bool enter_scroller (GdkEventCrossing*);
|
||||
bool leave_scroller (GdkEventCrossing*);
|
||||
};
|
||||
|
||||
|
||||
|
@ -171,7 +171,7 @@ PortGroupUI::port_checkbutton_toggled (CheckButton* b, int r, int c)
|
||||
void
|
||||
PortGroupUI::setup_visibility ()
|
||||
{
|
||||
if (_port_group.visible) {
|
||||
if (!_port_group.ports.empty() && _port_group.visible) {
|
||||
_table_box.show ();
|
||||
} else {
|
||||
_table_box.hide ();
|
||||
@ -374,25 +374,30 @@ PortMatrix::PortMatrix (ARDOUR::Session& session, ARDOUR::DataType type, bool of
|
||||
: _offer_inputs (offer_inputs), _port_group_list (session, type, offer_inputs, mask), _type (type),
|
||||
_column_labels (_port_group_list)
|
||||
{
|
||||
_row_labels_vbox[0] = _row_labels_vbox[1] = 0;
|
||||
_side_vbox_pad[0] = _side_vbox_pad[1] = 0;
|
||||
_row_labels_vbox = 0;
|
||||
_side_vbox_pad = 0;
|
||||
|
||||
_visibility_checkbutton_box.pack_start (*(manage (new Label (_("Connections displayed: ")))), false, false, 10);
|
||||
pack_start (_visibility_checkbutton_box, false, false);
|
||||
|
||||
_side_vbox[0].pack_start (*manage (new Label ("")));
|
||||
_overall_hbox.pack_start (_side_vbox[0], false, false);
|
||||
_scrolled_window.set_policy (POLICY_ALWAYS, POLICY_NEVER);
|
||||
_side_vbox.pack_start (*manage (new Label ("")));
|
||||
_scrolled_window.set_policy (POLICY_ALWAYS, POLICY_AUTOMATIC);
|
||||
_scrolled_window.set_shadow_type (SHADOW_NONE);
|
||||
VBox* b = new VBox;
|
||||
VBox* b = manage (new VBox);
|
||||
b->pack_start (_column_labels, false, false);
|
||||
b->pack_start (_port_group_hbox, false, false);
|
||||
Alignment* a = new Alignment (0, 1, 0, 0);
|
||||
a->add (*manage (b));
|
||||
_scrolled_window.add (*manage (a));
|
||||
_overall_hbox.pack_start (_scrolled_window);
|
||||
_side_vbox[1].pack_start (*manage (new Label ("")));
|
||||
// _overall_hbox.pack_start (_side_vbox[1]);
|
||||
Alignment* a = manage (new Alignment (0, 1, 0, 0));
|
||||
a->add (*b);
|
||||
_scrolled_window.add (*a);
|
||||
|
||||
if (offer_inputs) {
|
||||
_overall_hbox.pack_start (_side_vbox, false, false, 10);
|
||||
_overall_hbox.pack_start (_scrolled_window, true, true);
|
||||
} else {
|
||||
_overall_hbox.pack_start (_scrolled_window, true, true, 10);
|
||||
_overall_hbox.pack_start (_side_vbox, false, false);
|
||||
}
|
||||
|
||||
pack_start (_overall_hbox);
|
||||
|
||||
_port_group_hbox.signal_size_allocate().connect (sigc::hide (sigc::mem_fun (*this, &IOSelector::setup_dimensions)));
|
||||
@ -407,25 +412,22 @@ PortMatrix::~PortMatrix ()
|
||||
void
|
||||
PortMatrix::clear ()
|
||||
{
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
|
||||
for (std::vector<EventBox*>::iterator j = _row_labels[i].begin(); j != _row_labels[i].end(); ++j) {
|
||||
delete *j;
|
||||
}
|
||||
_row_labels[i].clear ();
|
||||
|
||||
if (_row_labels_vbox[i]) {
|
||||
_side_vbox[i].remove (*_row_labels_vbox[i]);
|
||||
}
|
||||
delete _row_labels_vbox[i];
|
||||
_row_labels_vbox[i] = 0;
|
||||
|
||||
if (_side_vbox_pad[i]) {
|
||||
_side_vbox[i].remove (*_side_vbox_pad[i]);
|
||||
}
|
||||
delete _side_vbox_pad[i];
|
||||
_side_vbox_pad[i] = 0;
|
||||
for (std::vector<EventBox*>::iterator j = _row_labels.begin(); j != _row_labels.end(); ++j) {
|
||||
delete *j;
|
||||
}
|
||||
_row_labels.clear ();
|
||||
|
||||
if (_row_labels_vbox) {
|
||||
_side_vbox.remove (*_row_labels_vbox);
|
||||
}
|
||||
delete _row_labels_vbox;
|
||||
_row_labels_vbox = 0;
|
||||
|
||||
if (_side_vbox_pad) {
|
||||
_side_vbox.remove (*_side_vbox_pad);
|
||||
}
|
||||
delete _side_vbox_pad;
|
||||
_side_vbox_pad = 0;
|
||||
|
||||
for (std::vector<PortGroupUI*>::iterator i = _port_group_ui.begin(); i != _port_group_ui.end(); ++i) {
|
||||
_port_group_hbox.remove ((*i)->get_table());
|
||||
@ -462,21 +464,24 @@ PortMatrix::setup_dimensions ()
|
||||
|
||||
/* Scrolled window */
|
||||
/* XXX: really shouldn't set a minimum horizontal size here, but if we don't
|
||||
the window starts up very small */
|
||||
the window starts up very small.
|
||||
The constant value in the set_size_request() computation will control
|
||||
how big the scrolled window will be if we fill the port matrix will a gajillion
|
||||
ports.
|
||||
*/
|
||||
|
||||
_scrolled_window.set_size_request (
|
||||
std::min (_column_labels.get_width(), 640),
|
||||
std::min (_column_labels.get_width(), 400),
|
||||
_column_labels.get_height() + port_group_tables_height + scrollbar_height + 16
|
||||
);
|
||||
|
||||
/* Row labels */
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (std::vector<EventBox*>::iterator j = _row_labels[i].begin(); j != _row_labels[i].end(); ++j) {
|
||||
(*j)->get_child()->set_size_request (-1, unit_size.second);
|
||||
}
|
||||
|
||||
if (_side_vbox_pad[i]) {
|
||||
_side_vbox_pad[i]->set_size_request (-1, scrollbar_height + unit_size.second / 4);
|
||||
}
|
||||
for (std::vector<EventBox*>::iterator j = _row_labels.begin(); j != _row_labels.end(); ++j) {
|
||||
(*j)->get_child()->set_size_request (-1, unit_size.second);
|
||||
}
|
||||
|
||||
if (_side_vbox_pad) {
|
||||
_side_vbox_pad->set_size_request (-1, scrollbar_height + unit_size.second / 4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -490,35 +495,35 @@ PortMatrix::setup ()
|
||||
int const rows = n_rows ();
|
||||
|
||||
/* Row labels */
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
_row_labels_vbox[i] = new VBox;
|
||||
int const run_rows = std::max (1, rows);
|
||||
for (int j = 0; j < run_rows; ++j) {
|
||||
|
||||
/* embolden the port/channel name */
|
||||
_row_labels_vbox = new VBox;
|
||||
int const run_rows = std::max (1, rows);
|
||||
|
||||
string s = "<b>";
|
||||
s += row_name (j);
|
||||
s += "</b>";
|
||||
|
||||
Label* label = manage (new Label (s));
|
||||
EventBox* b = manage (new EventBox);
|
||||
|
||||
label->set_use_markup (true);
|
||||
|
||||
b->set_events (Gdk::BUTTON_PRESS_MASK);
|
||||
b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &IOSelector::row_label_button_pressed), j));
|
||||
b->add (*label);
|
||||
|
||||
_row_labels[i].push_back (b);
|
||||
_row_labels_vbox[i]->pack_start (*b, false, false);
|
||||
}
|
||||
|
||||
_side_vbox[i].pack_start (*_row_labels_vbox[i], false, false);
|
||||
_side_vbox_pad[i] = new Label ("");
|
||||
_side_vbox[i].pack_start (*_side_vbox_pad[i], false, false);
|
||||
for (int j = 0; j < run_rows; ++j) {
|
||||
|
||||
/* embolden the port/channel name */
|
||||
|
||||
string s = "<b>";
|
||||
s += row_name (j);
|
||||
s += "</b>";
|
||||
|
||||
Label* label = manage (new Label (s));
|
||||
EventBox* b = manage (new EventBox);
|
||||
|
||||
label->set_use_markup (true);
|
||||
|
||||
b->set_events (Gdk::BUTTON_PRESS_MASK);
|
||||
b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &IOSelector::row_label_button_pressed), j));
|
||||
b->add (*label);
|
||||
|
||||
_row_labels.push_back (b);
|
||||
_row_labels_vbox->pack_start (*b, false, false);
|
||||
}
|
||||
|
||||
_side_vbox.pack_start (*_row_labels_vbox, false, false);
|
||||
_side_vbox_pad = new Label ("");
|
||||
_side_vbox.pack_start (*_side_vbox_pad, false, false);
|
||||
|
||||
/* Checkbutton tables and visibility checkbuttons */
|
||||
for (PortGroupList::iterator i = _port_group_list.begin(); i != _port_group_list.end(); ++i) {
|
||||
|
||||
|
@ -174,6 +174,8 @@ class PortMatrix : public Gtk::VBox {
|
||||
virtual void remove_row (int) = 0;
|
||||
virtual std::string row_descriptor () const = 0;
|
||||
|
||||
Gtk::Widget& scrolled_window() { return _scrolled_window; }
|
||||
|
||||
protected:
|
||||
|
||||
bool _offer_inputs;
|
||||
@ -182,14 +184,14 @@ class PortMatrix : public Gtk::VBox {
|
||||
PortGroupList _port_group_list;
|
||||
ARDOUR::DataType _type;
|
||||
std::vector<PortGroupUI*> _port_group_ui;
|
||||
std::vector<Gtk::EventBox*> _row_labels[2];
|
||||
Gtk::VBox* _row_labels_vbox[2];
|
||||
std::vector<Gtk::EventBox*> _row_labels;
|
||||
Gtk::VBox* _row_labels_vbox;
|
||||
RotatedLabelSet _column_labels;
|
||||
Gtk::HBox _overall_hbox;
|
||||
Gtk::VBox _side_vbox[2];
|
||||
Gtk::VBox _side_vbox;
|
||||
Gtk::HBox _port_group_hbox;
|
||||
Gtk::ScrolledWindow _scrolled_window;
|
||||
Gtk::Label* _side_vbox_pad[2];
|
||||
Gtk::Label* _side_vbox_pad;
|
||||
Gtk::HBox _visibility_checkbutton_box;
|
||||
|
||||
void setup ();
|
||||
|
Loading…
Reference in New Issue
Block a user