1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-28 00:07:35 +00:00

Maps: Add MapsSettings with multiple tile providers options

This commit is contained in:
Bastiaan van der Plaat 2023-09-16 21:10:23 +02:00 committed by Andrew Kaster
parent 264782557e
commit aed25991e6
14 changed files with 379 additions and 15 deletions

View file

@ -7,6 +7,8 @@
#include "MapWidget.h"
#include <AK/URL.h>
#include <Applications/MapsSettings/Defaults.h>
#include <LibConfig/Client.h>
#include <LibDesktop/Launcher.h>
#include <LibGUI/Action.h>
#include <LibGUI/Application.h>
@ -51,7 +53,7 @@ double MapWidget::LatLng::distance_to(LatLng const& other) const
// MapWidget class
MapWidget::MapWidget(Options const& options)
: m_tile_layer_url(options.tile_layer_url)
: m_tile_provider(options.tile_provider)
, m_center(options.center)
, m_zoom(options.zoom)
, m_context_menu_enabled(options.context_menu_enabled)
@ -60,9 +62,13 @@ MapWidget::MapWidget(Options const& options)
, m_attribution_enabled(options.attribution_enabled)
{
m_request_client = Protocol::RequestClient::try_create().release_value_but_fixme_should_propagate_errors();
if (options.attribution_enabled)
add_panel({ options.attribution_text, Panel::Position::BottomRight, options.attribution_url, true });
if (options.attribution_enabled) {
auto attribution_text = options.attribution_text.value_or(MUST(String::from_deprecated_string(Config::read_string("Maps"sv, "MapWidget"sv, "TileProviderAttributionText"sv, Maps::default_tile_provider_attribution_text))));
URL attribution_url = options.attribution_url.value_or(URL(Config::read_string("Maps"sv, "MapWidget"sv, "TileProviderAttributionUrl"sv, Maps::default_tile_provider_attribution_url)));
add_panel({ attribution_text, Panel::Position::BottomRight, attribution_url, "attribution"_string });
}
m_marker_image = Gfx::Bitmap::load_from_file("/res/graphics/maps/marker-blue.png"sv).release_value_but_fixme_should_propagate_errors();
m_default_tile_provider = MUST(String::from_deprecated_string(Config::read_string("Maps"sv, "MapWidget"sv, "TileProviderUrlFormat"sv, Maps::default_tile_provider_url_format)));
}
void MapWidget::set_zoom(int zoom)
@ -72,6 +78,42 @@ void MapWidget::set_zoom(int zoom)
update();
}
void MapWidget::config_string_did_change(StringView domain, StringView group, StringView key, StringView value)
{
if (domain != "Maps" || group != "MapWidget")
return;
if (key == "TileProviderUrlFormat") {
// When config tile provider changes clear all active requests and loaded tiles
m_default_tile_provider = MUST(String::from_utf8(value));
m_first_image_loaded = false;
m_active_requests.clear();
m_tiles.clear();
update();
}
if (key == "TileProviderAttributionText") {
// Update attribution panel text when it exists
for (auto& panel : m_panels) {
if (panel.name == "attribution") {
panel.text = MUST(String::from_utf8(value));
return;
}
}
update();
}
if (key == "TileProviderAttributionUrl") {
// Update attribution panel url when it exists
for (auto& panel : m_panels) {
if (panel.name == "attribution") {
panel.url = URL(value);
return;
}
}
}
}
void MapWidget::doubleclick_event(GUI::MouseEvent& event)
{
int new_zoom = event.shift() ? m_zoom - 1 : m_zoom + 1;
@ -261,7 +303,7 @@ void MapWidget::process_tile_queue()
HashMap<DeprecatedString, DeprecatedString> headers;
headers.set("User-Agent", "SerenityOS Maps");
headers.set("Accept", "image/png");
URL url(MUST(String::formatted(m_tile_layer_url, tile_key.zoom, tile_key.x, tile_key.y)));
URL url(MUST(String::formatted(m_tile_provider.value_or(m_default_tile_provider), tile_key.zoom, tile_key.x, tile_key.y)));
auto request = m_request_client->start_request("GET", url, headers, {});
VERIFY(!request.is_null());

View file

@ -8,13 +8,15 @@
#pragma once
#include <AK/Queue.h>
#include <LibConfig/Listener.h>
#include <LibGUI/Frame.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Painter.h>
#include <LibProtocol/Request.h>
#include <LibProtocol/RequestClient.h>
class MapWidget : public GUI::Frame {
class MapWidget : public GUI::Frame
, public Config::Listener {
C_OBJECT(MapWidget);
public:
@ -26,15 +28,15 @@ public:
};
struct Options {
String tile_layer_url { "https://tile.openstreetmap.org/{}/{}/{}.png"_string };
Optional<String> tile_provider {};
LatLng center;
int zoom;
bool context_menu_enabled { true };
bool scale_enabled { true };
int scale_max_width { 100 };
bool attribution_enabled { true };
String attribution_text { "© OpenStreetMap contributors"_string };
URL attribution_url { "https://www.openstreetmap.org/copyright"sv };
Optional<String> attribution_text {};
Optional<URL> attribution_url {};
};
LatLng center() const { return m_center; }
@ -76,7 +78,7 @@ public:
String text;
Position position;
Optional<URL> url {};
bool persistent { false };
Optional<String> name {};
Gfx::IntRect rect { 0, 0, 0, 0 };
};
void add_panel(Panel const& panel)
@ -84,9 +86,9 @@ public:
m_panels.append(panel);
update();
}
void clear_panels()
void remove_panels_with_name(StringView name)
{
m_panels.remove_all_matching([](auto const& panel) { return !panel.persistent; });
m_panels.remove_all_matching([name](auto const& panel) { return panel.name == name; });
update();
}
@ -117,6 +119,7 @@ protected:
RefPtr<Protocol::RequestClient> request_client() const { return m_request_client; }
private:
virtual void config_string_did_change(StringView domain, StringView group, StringView key, StringView value) override;
virtual void doubleclick_event(GUI::MouseEvent&) override;
virtual void mousemove_event(GUI::MouseEvent&) override;
virtual void mousedown_event(GUI::MouseEvent&) override;
@ -154,7 +157,8 @@ private:
Vector<RefPtr<Protocol::Request>, TILES_DOWNLOAD_PARALLEL_MAX> m_active_requests;
Queue<TileKey, 32> m_tile_queue;
RefPtr<Gfx::Bitmap> m_marker_image;
String m_tile_layer_url;
Optional<String> m_tile_provider;
String m_default_tile_provider;
LatLng m_center;
int m_zoom {};
bool m_context_menu_enabled {};

View file

@ -73,5 +73,6 @@ void UsersMapWidget::add_users_to_map()
add_panel({ MUST(String::formatted("{} users are already registered", m_users.value().size())),
Panel::Position::TopRight,
{ { "https://github.com/SerenityOS/user-map" } } });
{ { "https://github.com/SerenityOS/user-map" } },
"users"_string });
}

View file

@ -24,7 +24,7 @@ public:
}
} else {
clear_markers();
clear_panels();
remove_panels_with_name("users"sv);
}
}

View file

@ -12,6 +12,7 @@
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Icon.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Process.h>
#include <LibGUI/ToolbarContainer.h>
#include <LibGUI/Window.h>
@ -19,16 +20,19 @@ static int constexpr MAP_ZOOM_DEFAULT = 3;
ErrorOr<int> serenity_main(Main::Arguments arguments)
{
TRY(Core::System::pledge("stdio recvfd sendfd rpath unix"));
TRY(Core::System::pledge("stdio recvfd sendfd rpath unix proc exec"));
auto app = TRY(GUI::Application::create(arguments));
TRY(Core::System::unveil("/bin/MapsSettings", "x"));
TRY(Core::System::unveil("/res", "r"));
TRY(Core::System::unveil("/tmp/session/%sid/portal/config", "rw"));
TRY(Core::System::unveil("/tmp/session/%sid/portal/launch", "rw"));
TRY(Core::System::unveil("/tmp/session/%sid/portal/request", "rw"));
TRY(Core::System::unveil(nullptr, nullptr));
Config::monitor_domain("Maps");
auto app_icon = TRY(GUI::Icon::try_create_default_icon("app-maps"sv));
auto window = GUI::Window::construct();
window->set_title("Maps");
@ -56,6 +60,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
// Main menu actions
auto file_menu = window->add_menu("&File"_string);
auto open_settings_action = GUI::Action::create("Maps &Settings", { Mod_Ctrl, Key_Comma }, TRY(Gfx::Bitmap::load_from_file("/res/icons/16x16/app-settings.png"sv)), [window](GUI::Action const&) {
GUI::Process::spawn_or_show_error(window, "/bin/MapsSettings"sv);
});
file_menu->add_action(open_settings_action);
file_menu->add_separator();
file_menu->add_action(GUI::CommonActions::make_quit_action([](auto&) { GUI::Application::the()->quit(); }));
auto view_menu = window->add_menu("&View"_string);
@ -89,6 +98,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
toolbar->add_action(zoom_in_action);
toolbar->add_action(zoom_out_action);
toolbar->add_action(reset_zoom_action);
toolbar->add_separator();
toolbar->add_action(open_settings_action);
window->show();