From 6519e850ef0c803e796d9c1059b06499e35505d6 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Tue, 28 May 2024 00:06:50 +0800 Subject: [PATCH] support makerworld.com --- src/libslic3r/Utils.hpp | 19 ++++++++ src/slic3r/GUI/Downloader.cpp | 31 ++++++------- src/slic3r/GUI/GUI_App.cpp | 76 ++++++-------------------------- src/slic3r/GUI/GUI_App.hpp | 2 - src/slic3r/GUI/InstanceCheck.cpp | 2 +- src/slic3r/GUI/Preferences.cpp | 8 +++- 6 files changed, 53 insertions(+), 85 deletions(-) diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 43daedb5bb..8a7d2467a2 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -220,6 +221,24 @@ extern bool is_shapes_dir(const std::string& dir); //BBS: add json support extern bool is_json_file(const std::string& path); +// Orca: custom protocal support utils +inline bool is_orca_open(const std::string& url) { return boost::starts_with(url, "orcaslicer://open"); } +inline bool is_prusaslicer_open(const std::string& url) { return boost::starts_with(url, "prusaslicer://open"); } +inline bool is_bambustudio_open(const std::string& url) { return boost::starts_with(url, "bambustudio://open"); } +inline bool is_cura_open(const std::string& url) { return boost::starts_with(url, "cura://open"); } +inline bool is_supported_open_protocol(const std::string& url) { return is_orca_open(url) || is_prusaslicer_open(url) || is_bambustudio_open(url) || is_cura_open(url); } +inline bool is_printables_link(const std::string& url) { + const std::regex url_regex("(http|https)://printables.com", std::regex_constants::icase); + return std::regex_match(url, url_regex); +} +inline bool is_makerworld_link(const std::string& url) { + const std::regex url_regex("(http|https)://makerworld.com", std::regex_constants::icase); + return std::regex_match(url, url_regex); +} +inline bool is_thingiverse_link(const std::string& url) { + const std::regex url_regex("(http|https)://www.thingiverse.com", std::regex_constants::icase); + return std::regex_match(url, url_regex); +} // File path / name / extension splitting utilities, working with UTF-8, // to be published to Perl. namespace PerlUtils { diff --git a/src/slic3r/GUI/Downloader.cpp b/src/slic3r/GUI/Downloader.cpp index 10b3b6cbe5..b0ea22c3ce 100644 --- a/src/slic3r/GUI/Downloader.cpp +++ b/src/slic3r/GUI/Downloader.cpp @@ -148,7 +148,7 @@ void Downloader::start_download(const std::string& full_url) // Orca: Replace PS workaround for "mysterious slash" with a more dynamic approach // Windows seems to have fixed the issue and this provides backwards compatability for those it still affects - boost::regex re(R"(^(orcaslicer|prusaslicer):\/\/open[\/]?\?file=)", boost::regbase::icase); + boost::regex re(R"(^(orcaslicer|prusaslicer|bambustudio|cura):\/\/open[\/]?\?file=)", boost::regbase::icase); boost::smatch results; if (!boost::regex_search(full_url, results, re)) { @@ -161,23 +161,18 @@ void Downloader::start_download(const std::string& full_url) } size_t id = get_next_id(); std::string escaped_url = FileGet::escape_url(full_url.substr(results.length())); - // Orca:: any website that supports orcaslicer://open/?file= can be downloaded - - // if (!boost::starts_with(escaped_url, "https://") || !FileGet::is_subdomain(escaped_url, "printables.com")) { - // std::string msg = format(_L("Download won't start. Download URL doesn't point to https://printables.com : %1%"), escaped_url); - // BOOST_LOG_TRIVIAL(error) << msg; - // NotificationManager* ntf_mngr = wxGetApp().notification_manager(); - // ntf_mngr->push_notification(NotificationType::CustomNotification, NotificationManager::NotificationLevel::ErrorNotificationLevel, - // "Download failed. Download URL doesn't point to https://printables.com."); - // return; - // } - - std::string text(escaped_url); - m_downloads.emplace_back(std::make_unique(id, std::move(escaped_url), this, m_dest_folder)); - NotificationManager* ntf_mngr = wxGetApp().notification_manager(); - ntf_mngr->push_download_URL_progress_notification(id, m_downloads.back()->get_filename(), std::bind(&Downloader::user_action_callback, this, std::placeholders::_1, std::placeholders::_2)); - m_downloads.back()->start(); - BOOST_LOG_TRIVIAL(debug) << "started download"; + if (is_bambustudio_open(full_url) || (is_orca_open(full_url) && is_makerworld_link(full_url))) + plater->request_model_download(escaped_url); + else { + std::string text(escaped_url); + m_downloads.emplace_back(std::make_unique(id, std::move(escaped_url), this, m_dest_folder)); + NotificationManager* ntf_mngr = wxGetApp().notification_manager(); + ntf_mngr->push_download_URL_progress_notification(id, m_downloads.back()->get_filename(), + std::bind(&Downloader::user_action_callback, this, std::placeholders::_1, + std::placeholders::_2)); + m_downloads.back()->start(); + } + BOOST_LOG_TRIVIAL(debug) << "started download"; } void Downloader::on_progress(wxCommandEvent& event) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index befd26dc89..2d34c4d13d 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -804,63 +804,39 @@ void GUI_App::post_init() m_open_method = "double_click"; bool switch_to_3d = false; - if (!this->init_params->input_files.empty()) { + if (!this->init_params->input_files.empty()) { BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", init with input files, size %1%, input_gcode %2%") %this->init_params->input_files.size() %this->init_params->input_gcode; - - - - if (this->init_params->input_files.size() == 1 && - (boost::starts_with(this->init_params->input_files.front(), "orcaslicer://open") || - boost::starts_with(this->init_params->input_files.front(), "prusaslicer://open"))) { - - if (boost::starts_with(this->init_params->input_files.front(), "orcaslicer://open")|| - boost::starts_with(this->init_params->input_files.front(), "prusaslicer://open")) { - switch_to_3d = true; - start_download(this->init_params->input_files.front()); - } else if (vector input_str_arr = split_str(this->init_params->input_files.front(), "orcaslicer://open/?file="); input_str_arr.size() > 1) { - std::string download_origin_url; - for (auto input_str : input_str_arr) { - if (!input_str.empty()) - download_origin_url = input_str; - } - - std::string download_file_url = url_decode(download_origin_url); - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << download_file_url; - if (!download_file_url.empty() && - (boost::starts_with(download_file_url, "http://") || boost::starts_with(download_file_url, "https://"))) { - request_model_download(download_file_url); - } - } - m_open_method = "makerworld"; - } - else { + const auto first_url = this->init_params->input_files.front(); + if (this->init_params->input_files.size() == 1 && is_supported_open_protocol(first_url)) { + switch_to_3d = true; + start_download(first_url); + m_open_method = "url"; + } else { switch_to_3d = true; if (this->init_params->input_gcode) { mainframe->select_tab(size_t(MainFrame::tp3DEditor)); plater_->select_view_3D("3D"); this->plater()->load_gcode(from_u8(this->init_params->input_files.front())); m_open_method = "gcode"; - } - else { + } else { mainframe->select_tab(size_t(MainFrame::tp3DEditor)); plater_->select_view_3D("3D"); wxArrayString input_files; - for (auto & file : this->init_params->input_files) { + for (auto& file : this->init_params->input_files) { input_files.push_back(wxString::FromUTF8(file)); } this->plater()->set_project_filename(_L("Untitled")); this->plater()->load_files(input_files); try { if (!input_files.empty()) { - std::string file_path = input_files.front().ToStdString(); + std::string file_path = input_files.front().ToStdString(); std::filesystem::path path(file_path); m_open_method = "file_" + path.extension().string(); } - } - catch (...) { + } catch (...) { BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ", file path exception!"; m_open_method = "file"; } @@ -2630,10 +2606,6 @@ bool GUI_App::on_init_inner() #endif this->post_init(); - if (!m_download_file_url.empty()) { - request_model_download(m_download_file_url); - m_download_file_url = ""; - } update_publish_status(); } @@ -5861,32 +5833,9 @@ void GUI_App::OSXStoreOpenFiles(const wxArrayString &fileNames) void GUI_App::MacOpenURL(const wxString& url) { - BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << "get mac url " << url; - if (url.empty()) return; - - if (boost::starts_with(url, "orcasliceropen://")) { - auto input_str_arr = split_str(url.ToStdString(), "orcasliceropen://"); - - std::string download_origin_url; - for (auto input_str : input_str_arr) { - if (!input_str.empty()) download_origin_url = input_str; - } - - std::string download_file_url = url_decode(download_origin_url); - BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << download_file_url; - if (!download_file_url.empty() && (boost::starts_with(download_file_url, "http://") || boost::starts_with(download_file_url, "https://"))) { - - if (m_post_initialized) { - request_model_download(download_file_url); - } - else { - m_download_file_url = download_file_url; - } - } - } else if (boost::starts_with(url, "orcaslicer://")) - start_download(boost::nowide::narrow(url)); + start_download(boost::nowide::narrow(url)); } // wxWidgets override to get an event on open files. @@ -6685,6 +6634,7 @@ void GUI_App::start_download(std::string url) } m_downloader->init(dest_folder); m_downloader->start_download(url); + } bool is_support_filament(int extruder_id) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 7def51e40b..5817a47ebb 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -236,8 +236,6 @@ private: bool m_opengl_initialized{ false }; #endif -//import model from mall - wxString m_download_file_url; //#ifdef _WIN32 wxColour m_color_label_modified; diff --git a/src/slic3r/GUI/InstanceCheck.cpp b/src/slic3r/GUI/InstanceCheck.cpp index a2f38d8e8f..360a952c1b 100644 --- a/src/slic3r/GUI/InstanceCheck.cpp +++ b/src/slic3r/GUI/InstanceCheck.cpp @@ -501,7 +501,7 @@ void OtherInstanceMessageHandler::handle_message(const std::string& message) std::vector paths; std::vector downloads; - boost::regex re(R"(^(orcaslicer|prusaslicer):\/\/open[\/]?\?file=)", boost::regbase::icase); + boost::regex re(R"(^(orcaslicer|prusaslicer|cura|bambustudio):\/\/open[\/]?\?file=)", boost::regbase::icase); boost::smatch results; // Skip the first argument, it is the path to the slicer executable. diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index f6b7996557..7ce8a7353f 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -1075,8 +1075,13 @@ wxWindow* PreferencesDialog::create_general_page() wxGetApp().check_url_association(L"prusaslicer", reg_bin); auto associate_url_prusaslicer = create_item_button(_L("Current association: ") + reg_bin, _L("Associate prusaslicer://"), page, reg_bin.empty() ? _L("Not associated to any application") : reg_bin, - _L("Associate OrcaSlicer with prusaslicer:// links so that Orca can open PrusaSlicer links from Printable.com"), + _L("Associate OrcaSlicer with prusaslicer:// links so that Orca can open models from Printable.com"), []() { wxGetApp().associate_url(L"prusaslicer"); }); + wxGetApp().check_url_association(L"bambustudio", reg_bin); + auto associate_url_bambustudio = create_item_button(_L("Current association: ") + reg_bin, _L("Associate bambustudio://"), page, + reg_bin.empty() ? _L("Not associated to any application") : reg_bin, + _L("Associate OrcaSlicer with bambustudio:// links so that Orca can open models from makerworld.com"), + []() { wxGetApp().associate_url(L"bambustudio"); }); #endif // auto title_modelmall = create_item_title(_L("Online Models"), page, _L("Online Models")); @@ -1143,6 +1148,7 @@ wxWindow* PreferencesDialog::create_general_page() #endif // _WIN32 #if !defined(__APPLE__) sizer_page->Add(associate_url_prusaslicer, 0, wxTOP | wxEXPAND, FromDIP(20)); + sizer_page->Add(associate_url_bambustudio, 0, wxTOP | wxEXPAND, FromDIP(20)); #endif // auto item_title_modelmall = sizer_page->Add(title_modelmall, 0, wxTOP | wxEXPAND, FromDIP(20)); // auto item_item_modelmall = sizer_page->Add(item_modelmall, 0, wxTOP, FromDIP(3));