mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:17:44 +00:00
WindowServer: Fix various const-correctness issues
This commit is contained in:
parent
dbcf2f2dd4
commit
025bdcf34c
9 changed files with 59 additions and 57 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -820,7 +820,7 @@ bool Compositor::set_wallpaper_mode(DeprecatedString const& mode)
|
||||||
return succeeded;
|
return succeeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compositor::set_wallpaper(RefPtr<Gfx::Bitmap> bitmap)
|
bool Compositor::set_wallpaper(RefPtr<Gfx::Bitmap const> bitmap)
|
||||||
{
|
{
|
||||||
if (!bitmap)
|
if (!bitmap)
|
||||||
m_wallpaper = nullptr;
|
m_wallpaper = nullptr;
|
||||||
|
@ -869,11 +869,12 @@ void Compositor::update_wallpaper_bitmap()
|
||||||
// If the screen size is equal to the wallpaper size, we don't actually need to scale it
|
// If the screen size is equal to the wallpaper size, we don't actually need to scale it
|
||||||
screen_data.m_wallpaper_bitmap = m_wallpaper;
|
screen_data.m_wallpaper_bitmap = m_wallpaper;
|
||||||
} else {
|
} else {
|
||||||
if (!screen_data.m_wallpaper_bitmap)
|
auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, screen.size(), screen.scale_factor()).release_value_but_fixme_should_propagate_errors();
|
||||||
screen_data.m_wallpaper_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, screen.size(), screen.scale_factor()).release_value_but_fixme_should_propagate_errors();
|
|
||||||
|
|
||||||
Gfx::Painter painter(*screen_data.m_wallpaper_bitmap);
|
Gfx::Painter painter(*bitmap);
|
||||||
painter.draw_scaled_bitmap(screen_data.m_wallpaper_bitmap->rect(), *m_wallpaper, m_wallpaper->rect());
|
painter.draw_scaled_bitmap(bitmap->rect(), *m_wallpaper, m_wallpaper->rect());
|
||||||
|
|
||||||
|
screen_data.m_wallpaper_bitmap = move(bitmap);
|
||||||
}
|
}
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -36,7 +36,7 @@ struct CompositorScreenData {
|
||||||
RefPtr<Gfx::Bitmap> m_front_bitmap;
|
RefPtr<Gfx::Bitmap> m_front_bitmap;
|
||||||
RefPtr<Gfx::Bitmap> m_back_bitmap;
|
RefPtr<Gfx::Bitmap> m_back_bitmap;
|
||||||
RefPtr<Gfx::Bitmap> m_temp_bitmap;
|
RefPtr<Gfx::Bitmap> m_temp_bitmap;
|
||||||
RefPtr<Gfx::Bitmap> m_wallpaper_bitmap;
|
RefPtr<Gfx::Bitmap const> m_wallpaper_bitmap;
|
||||||
OwnPtr<Gfx::Painter> m_back_painter;
|
OwnPtr<Gfx::Painter> m_back_painter;
|
||||||
OwnPtr<Gfx::Painter> m_front_painter;
|
OwnPtr<Gfx::Painter> m_front_painter;
|
||||||
OwnPtr<Gfx::Painter> m_temp_painter;
|
OwnPtr<Gfx::Painter> m_temp_painter;
|
||||||
|
@ -107,8 +107,8 @@ public:
|
||||||
|
|
||||||
bool set_wallpaper_mode(DeprecatedString const& mode);
|
bool set_wallpaper_mode(DeprecatedString const& mode);
|
||||||
|
|
||||||
bool set_wallpaper(RefPtr<Gfx::Bitmap>);
|
bool set_wallpaper(RefPtr<Gfx::Bitmap const>);
|
||||||
RefPtr<Gfx::Bitmap> wallpaper_bitmap() const { return m_wallpaper; }
|
RefPtr<Gfx::Bitmap const> wallpaper_bitmap() const { return m_wallpaper; }
|
||||||
|
|
||||||
void invalidate_cursor(bool = false);
|
void invalidate_cursor(bool = false);
|
||||||
Gfx::IntRect current_cursor_rect() const;
|
Gfx::IntRect current_cursor_rect() const;
|
||||||
|
@ -231,7 +231,7 @@ private:
|
||||||
Gfx::DisjointIntRectSet m_transparent_wallpaper_rects;
|
Gfx::DisjointIntRectSet m_transparent_wallpaper_rects;
|
||||||
|
|
||||||
WallpaperMode m_wallpaper_mode { WallpaperMode::Unchecked };
|
WallpaperMode m_wallpaper_mode { WallpaperMode::Unchecked };
|
||||||
RefPtr<Gfx::Bitmap> m_wallpaper;
|
RefPtr<Gfx::Bitmap const> m_wallpaper;
|
||||||
|
|
||||||
Cursor const* m_current_cursor { nullptr };
|
Cursor const* m_current_cursor { nullptr };
|
||||||
Screen* m_current_cursor_screen { nullptr };
|
Screen* m_current_cursor_screen { nullptr };
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
namespace WindowServer {
|
namespace WindowServer {
|
||||||
|
|
||||||
Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor, Gfx::CursorParams const& cursor_params)
|
Cursor::Cursor(NonnullRefPtr<Gfx::Bitmap const>&& bitmap, int scale_factor, Gfx::CursorParams const& cursor_params)
|
||||||
: m_params(cursor_params.constrained(*bitmap))
|
: m_params(cursor_params.constrained(*bitmap))
|
||||||
, m_rect(bitmap->rect())
|
, m_rect(bitmap->rect())
|
||||||
{
|
{
|
||||||
|
@ -27,13 +27,13 @@ void Cursor::update_rect_if_animated()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<Cursor> Cursor::create(NonnullRefPtr<Gfx::Bitmap>&& bitmap, int scale_factor)
|
NonnullRefPtr<Cursor const> Cursor::create(NonnullRefPtr<Gfx::Bitmap const>&& bitmap, int scale_factor)
|
||||||
{
|
{
|
||||||
auto hotspot = bitmap->rect().center();
|
auto hotspot = bitmap->rect().center();
|
||||||
return adopt_ref(*new Cursor(move(bitmap), scale_factor, Gfx::CursorParams(hotspot)));
|
return adopt_ref(*new Cursor(move(bitmap), scale_factor, Gfx::CursorParams(hotspot)));
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Cursor> Cursor::create(StringView filename, StringView default_filename)
|
RefPtr<Cursor const> Cursor::create(StringView filename, StringView default_filename)
|
||||||
{
|
{
|
||||||
auto cursor = adopt_ref(*new Cursor());
|
auto cursor = adopt_ref(*new Cursor());
|
||||||
if (cursor->load(filename, default_filename))
|
if (cursor->load(filename, default_filename))
|
||||||
|
@ -72,7 +72,7 @@ bool Cursor::load(StringView filename, StringView default_filename)
|
||||||
return did_load_any;
|
return did_load_any;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Cursor> Cursor::create(Gfx::StandardCursor standard_cursor)
|
RefPtr<Cursor const> Cursor::create(Gfx::StandardCursor standard_cursor)
|
||||||
{
|
{
|
||||||
switch (standard_cursor) {
|
switch (standard_cursor) {
|
||||||
case Gfx::StandardCursor::None:
|
case Gfx::StandardCursor::None:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -15,9 +15,9 @@ namespace WindowServer {
|
||||||
|
|
||||||
class Cursor : public RefCounted<Cursor> {
|
class Cursor : public RefCounted<Cursor> {
|
||||||
public:
|
public:
|
||||||
static RefPtr<Cursor> create(StringView, StringView);
|
static RefPtr<Cursor const> create(StringView, StringView);
|
||||||
static NonnullRefPtr<Cursor> create(NonnullRefPtr<Gfx::Bitmap>&&, int);
|
static NonnullRefPtr<Cursor const> create(NonnullRefPtr<Gfx::Bitmap const>&&, int);
|
||||||
static RefPtr<Cursor> create(Gfx::StandardCursor);
|
static RefPtr<Cursor const> create(Gfx::StandardCursor);
|
||||||
~Cursor() = default;
|
~Cursor() = default;
|
||||||
|
|
||||||
Gfx::CursorParams const& params() const { return m_params; }
|
Gfx::CursorParams const& params() const { return m_params; }
|
||||||
|
@ -47,12 +47,12 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Cursor() = default;
|
Cursor() = default;
|
||||||
Cursor(NonnullRefPtr<Gfx::Bitmap>&&, int, Gfx::CursorParams const&);
|
Cursor(NonnullRefPtr<Gfx::Bitmap const>&&, int, Gfx::CursorParams const&);
|
||||||
|
|
||||||
bool load(StringView, StringView);
|
bool load(StringView, StringView);
|
||||||
void update_rect_if_animated();
|
void update_rect_if_animated();
|
||||||
|
|
||||||
HashMap<int, NonnullRefPtr<Gfx::Bitmap>> m_bitmaps;
|
HashMap<int, NonnullRefPtr<Gfx::Bitmap const>> m_bitmaps;
|
||||||
Gfx::CursorParams m_params;
|
Gfx::CursorParams m_params;
|
||||||
Gfx::IntRect m_rect;
|
Gfx::IntRect m_rect;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -80,7 +80,7 @@ private:
|
||||||
DeprecatedString m_text;
|
DeprecatedString m_text;
|
||||||
DeprecatedString m_shortcut_text;
|
DeprecatedString m_shortcut_text;
|
||||||
Gfx::IntRect m_rect;
|
Gfx::IntRect m_rect;
|
||||||
RefPtr<Gfx::Bitmap> m_icon;
|
RefPtr<Gfx::Bitmap const> m_icon;
|
||||||
int m_submenu_id { -1 };
|
int m_submenu_id { -1 };
|
||||||
bool m_exclusive { false };
|
bool m_exclusive { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, the SerenityOS developers.
|
* Copyright (c) 2021, the SerenityOS developers.
|
||||||
|
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -165,7 +166,7 @@ private:
|
||||||
Gfx::Font const& font();
|
Gfx::Font const& font();
|
||||||
void update_rect();
|
void update_rect();
|
||||||
|
|
||||||
RefPtr<Gfx::Bitmap> m_bitmap;
|
RefPtr<Gfx::Bitmap const> m_bitmap;
|
||||||
DeprecatedString m_text;
|
DeprecatedString m_text;
|
||||||
Gfx::IntRect m_label_rect;
|
Gfx::IntRect m_label_rect;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -279,13 +279,13 @@ public:
|
||||||
void set_base_size(Gfx::IntSize size) { m_base_size = size; }
|
void set_base_size(Gfx::IntSize size) { m_base_size = size; }
|
||||||
|
|
||||||
Gfx::Bitmap const& icon() const { return *m_icon; }
|
Gfx::Bitmap const& icon() const { return *m_icon; }
|
||||||
void set_icon(NonnullRefPtr<Gfx::Bitmap>&& icon) { m_icon = move(icon); }
|
void set_icon(NonnullRefPtr<Gfx::Bitmap const>&& icon) { m_icon = move(icon); }
|
||||||
|
|
||||||
void set_default_icon();
|
void set_default_icon();
|
||||||
|
|
||||||
Cursor const* cursor() const { return (m_cursor_override ? m_cursor_override : m_cursor).ptr(); }
|
Cursor const* cursor() const { return (m_cursor_override ? m_cursor_override : m_cursor).ptr(); }
|
||||||
void set_cursor(RefPtr<Cursor> cursor) { m_cursor = move(cursor); }
|
void set_cursor(RefPtr<Cursor const> cursor) { m_cursor = move(cursor); }
|
||||||
void set_cursor_override(RefPtr<Cursor> cursor) { m_cursor_override = move(cursor); }
|
void set_cursor_override(RefPtr<Cursor const> cursor) { m_cursor_override = move(cursor); }
|
||||||
void remove_cursor_override() { m_cursor_override = nullptr; }
|
void remove_cursor_override() { m_cursor_override = nullptr; }
|
||||||
|
|
||||||
void request_update(Gfx::IntRect const&, bool ignore_occlusion = false);
|
void request_update(Gfx::IntRect const&, bool ignore_occlusion = false);
|
||||||
|
@ -445,9 +445,9 @@ private:
|
||||||
Gfx::IntSize m_size_increment;
|
Gfx::IntSize m_size_increment;
|
||||||
Gfx::IntSize m_base_size;
|
Gfx::IntSize m_base_size;
|
||||||
Gfx::IntSize m_minimum_size { 0, 0 };
|
Gfx::IntSize m_minimum_size { 0, 0 };
|
||||||
NonnullRefPtr<Gfx::Bitmap> m_icon;
|
NonnullRefPtr<Gfx::Bitmap const> m_icon;
|
||||||
RefPtr<Cursor> m_cursor;
|
RefPtr<Cursor const> m_cursor;
|
||||||
RefPtr<Cursor> m_cursor_override;
|
RefPtr<Cursor const> m_cursor_override;
|
||||||
WindowFrame m_frame;
|
WindowFrame m_frame;
|
||||||
Gfx::DisjointIntRectSet m_pending_paint_rects;
|
Gfx::DisjointIntRectSet m_pending_paint_rects;
|
||||||
Gfx::IntRect m_rect_in_applet_area;
|
Gfx::IntRect m_rect_in_applet_area;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -35,7 +35,7 @@ WindowManager& WindowManager::the()
|
||||||
return *s_the;
|
return *s_the;
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowManager::WindowManager(Gfx::PaletteImpl const& palette)
|
WindowManager::WindowManager(Gfx::PaletteImpl& palette)
|
||||||
: m_switcher(WindowSwitcher::construct())
|
: m_switcher(WindowSwitcher::construct())
|
||||||
, m_keymap_switcher(KeymapSwitcher::construct())
|
, m_keymap_switcher(KeymapSwitcher::construct())
|
||||||
, m_palette(palette)
|
, m_palette(palette)
|
||||||
|
@ -2242,7 +2242,7 @@ void WindowManager::apply_cursor_theme(DeprecatedString const& theme_name)
|
||||||
auto cursor_theme_config = cursor_theme_config_or_error.release_value();
|
auto cursor_theme_config = cursor_theme_config_or_error.release_value();
|
||||||
|
|
||||||
auto* current_cursor = Compositor::the().current_cursor();
|
auto* current_cursor = Compositor::the().current_cursor();
|
||||||
auto reload_cursor = [&](RefPtr<Cursor>& cursor, DeprecatedString const& name) {
|
auto reload_cursor = [&](RefPtr<Cursor const>& cursor, DeprecatedString const& name) {
|
||||||
bool is_current_cursor = current_cursor && current_cursor == cursor.ptr();
|
bool is_current_cursor = current_cursor && current_cursor == cursor.ptr();
|
||||||
|
|
||||||
static auto const s_default_cursor_path = "/res/cursor-themes/Default/arrow.x2y2.png"sv;
|
static auto const s_default_cursor_path = "/res/cursor-themes/Default/arrow.x2y2.png"sv;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -339,7 +339,7 @@ public:
|
||||||
u8 last_processed_buttons() { return m_last_processed_buttons; }
|
u8 last_processed_buttons() { return m_last_processed_buttons; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit WindowManager(Gfx::PaletteImpl const&);
|
explicit WindowManager(Gfx::PaletteImpl&);
|
||||||
|
|
||||||
void notify_new_active_window(Window&);
|
void notify_new_active_window(Window&);
|
||||||
void notify_previous_active_window(Window&);
|
void notify_previous_active_window(Window&);
|
||||||
|
@ -371,25 +371,25 @@ private:
|
||||||
|
|
||||||
[[nodiscard]] static WindowStack& get_rendering_window_stacks(WindowStack*&);
|
[[nodiscard]] static WindowStack& get_rendering_window_stacks(WindowStack*&);
|
||||||
|
|
||||||
RefPtr<Cursor> m_hidden_cursor;
|
RefPtr<Cursor const> m_hidden_cursor;
|
||||||
RefPtr<Cursor> m_arrow_cursor;
|
RefPtr<Cursor const> m_arrow_cursor;
|
||||||
RefPtr<Cursor> m_hand_cursor;
|
RefPtr<Cursor const> m_hand_cursor;
|
||||||
RefPtr<Cursor> m_help_cursor;
|
RefPtr<Cursor const> m_help_cursor;
|
||||||
RefPtr<Cursor> m_resize_horizontally_cursor;
|
RefPtr<Cursor const> m_resize_horizontally_cursor;
|
||||||
RefPtr<Cursor> m_resize_vertically_cursor;
|
RefPtr<Cursor const> m_resize_vertically_cursor;
|
||||||
RefPtr<Cursor> m_resize_diagonally_tlbr_cursor;
|
RefPtr<Cursor const> m_resize_diagonally_tlbr_cursor;
|
||||||
RefPtr<Cursor> m_resize_diagonally_bltr_cursor;
|
RefPtr<Cursor const> m_resize_diagonally_bltr_cursor;
|
||||||
RefPtr<Cursor> m_resize_column_cursor;
|
RefPtr<Cursor const> m_resize_column_cursor;
|
||||||
RefPtr<Cursor> m_resize_row_cursor;
|
RefPtr<Cursor const> m_resize_row_cursor;
|
||||||
RefPtr<Cursor> m_i_beam_cursor;
|
RefPtr<Cursor const> m_i_beam_cursor;
|
||||||
RefPtr<Cursor> m_disallowed_cursor;
|
RefPtr<Cursor const> m_disallowed_cursor;
|
||||||
RefPtr<Cursor> m_move_cursor;
|
RefPtr<Cursor const> m_move_cursor;
|
||||||
RefPtr<Cursor> m_drag_cursor;
|
RefPtr<Cursor const> m_drag_cursor;
|
||||||
RefPtr<Cursor> m_drag_copy_cursor;
|
RefPtr<Cursor const> m_drag_copy_cursor;
|
||||||
RefPtr<Cursor> m_wait_cursor;
|
RefPtr<Cursor const> m_wait_cursor;
|
||||||
RefPtr<Cursor> m_crosshair_cursor;
|
RefPtr<Cursor const> m_crosshair_cursor;
|
||||||
RefPtr<Cursor> m_eyedropper_cursor;
|
RefPtr<Cursor const> m_eyedropper_cursor;
|
||||||
RefPtr<Cursor> m_zoom_cursor;
|
RefPtr<Cursor const> m_zoom_cursor;
|
||||||
int m_cursor_highlight_radius { 0 };
|
int m_cursor_highlight_radius { 0 };
|
||||||
Gfx::Color m_cursor_highlight_color;
|
Gfx::Color m_cursor_highlight_color;
|
||||||
bool m_cursor_highlight_enabled { false };
|
bool m_cursor_highlight_enabled { false };
|
||||||
|
@ -477,7 +477,7 @@ private:
|
||||||
DeprecatedString m_dnd_text;
|
DeprecatedString m_dnd_text;
|
||||||
bool m_dnd_accepts_drag { false };
|
bool m_dnd_accepts_drag { false };
|
||||||
|
|
||||||
RefPtr<Core::MimeData> m_dnd_mime_data;
|
RefPtr<Core::MimeData const> m_dnd_mime_data;
|
||||||
|
|
||||||
WindowStack* m_switching_to_window_stack { nullptr };
|
WindowStack* m_switching_to_window_stack { nullptr };
|
||||||
Vector<WeakPtr<Window>, 4> m_carry_window_to_new_stack;
|
Vector<WeakPtr<Window>, 4> m_carry_window_to_new_stack;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue