mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-07 15:07:31 -06:00
ENH: Open Prinables.com Links and Zip Archives (#3823)
* Enable ability to open `prusaslicer://` links * Add needed function to miniz * Import Zip Functionality Allows zip file to be drag and dropped or imported via the menu option Based on prusa3d/PrusaSlicer@ce38e57 and current master branch files * Update dialog style to match Orca * Ensure link is from printables * add toggle option in preferences doesn't actually control anything yet * Add Downloader classes As-is from PS master * Create Orca Styled Variant of Icons * Add Icons to ImGui * Use PS's Downloader impl for `prusaslicer://` links * Implement URL Registering on Windows * Implement prusaslicer:// link on macOS * Remove unnecessary class name qualifier in Plater.hpp * Add downloader desktop integration registration and undo * Revert Info.plist --------- Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
parent
0dbf610226
commit
a764d836e1
39 changed files with 3109 additions and 41 deletions
|
@ -7,6 +7,7 @@
|
|||
#include "slic3r/GUI/TaskManager.hpp"
|
||||
#include "format.hpp"
|
||||
#include "libslic3r_version.h"
|
||||
#include "Downloader.hpp"
|
||||
|
||||
// Localization headers: include libslic3r version first so everything in this file
|
||||
// uses the slic3r/GUI version (the macros will take precedence over the functions).
|
||||
|
@ -517,6 +518,7 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
|
|||
/* FT_MODEL */
|
||||
{"Supported files"sv, {".3mf"sv, ".stl"sv, ".oltp"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv}},
|
||||
#endif
|
||||
/* FT_ZIP */ { "ZIP files"sv, { ".zip"sv } },
|
||||
/* FT_PROJECT */ { "Project files"sv, { ".3mf"sv} },
|
||||
/* FT_GALLERY */ { "Known files"sv, { ".stl"sv, ".obj"sv } },
|
||||
|
||||
|
@ -816,18 +818,25 @@ void GUI_App::post_init()
|
|||
|
||||
|
||||
if (this->init_params->input_files.size() == 1 &&
|
||||
boost::starts_with(this->init_params->input_files.front(), "orcaslicer://open")) {
|
||||
auto input_str_arr = split_str(this->init_params->input_files.front(), "orcaslicer://open/?file=");
|
||||
(boost::starts_with(this->init_params->input_files.front(), "orcaslicer://open") ||
|
||||
boost::starts_with(this->init_params->input_files.front(), "prusaslicer://open"))) {
|
||||
|
||||
std::string download_origin_url;
|
||||
for (auto input_str:input_str_arr) {
|
||||
if (!input_str.empty()) download_origin_url = input_str;
|
||||
}
|
||||
if (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<string> 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_origin_url);
|
||||
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";
|
||||
}
|
||||
|
@ -1089,6 +1098,7 @@ GUI_App::GUI_App()
|
|||
, m_em_unit(10)
|
||||
, m_imgui(new ImGuiWrapper())
|
||||
, m_removable_drive_manager(std::make_unique<RemovableDriveManager>())
|
||||
, m_downloader(std::make_unique<Downloader>())
|
||||
, m_other_instance_message_handler(std::make_unique<OtherInstanceMessageHandler>())
|
||||
{
|
||||
//app config initializes early becasuse it is used in instance checking in OrcaSlicer.cpp
|
||||
|
@ -2361,6 +2371,10 @@ bool GUI_App::on_init_inner()
|
|||
associate_files(L"step");
|
||||
associate_files(L"stp");
|
||||
}
|
||||
// Orca: add PS url functionality
|
||||
if (app_config->get_bool("ps_url_registered")) {
|
||||
associate_url(L"prusaslicer");
|
||||
}
|
||||
if (app_config->get("associate_gcode") == "true")
|
||||
associate_files(L"gcode");
|
||||
#endif // __WXMSW__
|
||||
|
@ -3576,6 +3590,17 @@ void GUI_App::import_model(wxWindow *parent, wxArrayString& input_files) const
|
|||
dialog.GetPaths(input_files);
|
||||
}
|
||||
|
||||
void GUI_App::import_zip(wxWindow* parent, wxString& input_file) const
|
||||
{
|
||||
wxFileDialog dialog(parent ? parent : GetTopWindow(),
|
||||
_L("Choose ZIP file") + ":",
|
||||
from_u8(app_config->get_last_dir()), "",
|
||||
file_wildcards(FT_ZIP), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
|
||||
if (dialog.ShowModal() == wxID_OK)
|
||||
input_file = dialog.GetPath();
|
||||
}
|
||||
|
||||
void GUI_App::load_gcode(wxWindow* parent, wxString& input_file) const
|
||||
{
|
||||
input_file.Clear();
|
||||
|
@ -5508,6 +5533,10 @@ void GUI_App::open_preferences(size_t open_on_tab, const std::string& highlight_
|
|||
associate_files(L"step");
|
||||
associate_files(L"stp");
|
||||
}
|
||||
// Orca: add PS url functionality
|
||||
if (app_config->get_bool("ps_url_registered")) {
|
||||
associate_url(L"prusaslicer");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (app_config->get("associate_gcode") == "true")
|
||||
|
@ -5861,7 +5890,10 @@ void GUI_App::MacOpenURL(const wxString& url)
|
|||
{
|
||||
BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << "get mac url " << url;
|
||||
|
||||
if (!url.empty() && boost::starts_with(url, "orcasliceropen://")) {
|
||||
if (url.empty())
|
||||
return;
|
||||
|
||||
if (boost::starts_with(url, "orcasliceropen://")) {
|
||||
auto input_str_arr = split_str(url.ToStdString(), "orcasliceropen://");
|
||||
|
||||
std::string download_origin_url;
|
||||
|
@ -5880,7 +5912,8 @@ void GUI_App::MacOpenURL(const wxString& url)
|
|||
m_download_file_url = download_file_url;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (boost::starts_with(url, "prusasliceropen://"))
|
||||
start_download(boost::nowide::narrow(url));
|
||||
}
|
||||
|
||||
// wxWidgets override to get an event on open files.
|
||||
|
@ -6004,6 +6037,11 @@ Model& GUI_App::model()
|
|||
return plater_->model();
|
||||
}
|
||||
|
||||
Downloader* GUI_App::downloader()
|
||||
{
|
||||
return m_downloader.get();
|
||||
}
|
||||
|
||||
void GUI_App::load_url(wxString url)
|
||||
{
|
||||
if (mainframe)
|
||||
|
@ -6593,9 +6631,60 @@ void GUI_App::disassociate_files(std::wstring extend)
|
|||
::SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void GUI_App::associate_url(std::wstring url_prefix)
|
||||
{
|
||||
// Registry key creation for "prusaslicer://" URL
|
||||
|
||||
boost::filesystem::path binary_path(boost::filesystem::canonical(boost::dll::program_location()));
|
||||
// the path to binary needs to be correctly saved in string with respect to localized characters
|
||||
wxString wbinary = wxString::FromUTF8(binary_path.string());
|
||||
std::string binary_string = (boost::format("%1%") % wbinary).str();
|
||||
BOOST_LOG_TRIVIAL(info) << "Downloader registration: Path of binary: " << binary_string;
|
||||
|
||||
std::string key_string = "\"" + binary_string + "\" \"%1\"";
|
||||
|
||||
wxRegKey key_first(wxRegKey::HKCU, "Software\\Classes\\" + url_prefix);
|
||||
wxRegKey key_full(wxRegKey::HKCU, "Software\\Classes\\" + url_prefix + "\\shell\\open\\command");
|
||||
if (!key_first.Exists()) {
|
||||
key_first.Create(false);
|
||||
}
|
||||
key_first.SetValue("URL Protocol", "");
|
||||
|
||||
if (!key_full.Exists()) {
|
||||
key_full.Create(false);
|
||||
}
|
||||
key_full = key_string;
|
||||
}
|
||||
|
||||
void GUI_App::disassociate_url(std::wstring url_prefix)
|
||||
{
|
||||
wxRegKey key_full(wxRegKey::HKCU, "Software\\Classes\\" + url_prefix + "\\shell\\open\\command");
|
||||
if (!key_full.Exists()) {
|
||||
return;
|
||||
}
|
||||
key_full = "";
|
||||
}
|
||||
|
||||
#endif // __WXMSW__
|
||||
|
||||
void GUI_App::start_download(std::string url)
|
||||
{
|
||||
if (!plater_) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Could not start URL download: plater is nullptr.";
|
||||
return;
|
||||
}
|
||||
//lets always init so if the download dest folder was changed, new dest is used
|
||||
boost::filesystem::path dest_folder(app_config->get("download_path"));
|
||||
if (dest_folder.empty() || !boost::filesystem::is_directory(dest_folder)) {
|
||||
std::string msg = _u8L("Could not start URL download. Destination folder is not set. Please choose destination folder in Configuration Wizard.");
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
show_error(nullptr, msg);
|
||||
return;
|
||||
}
|
||||
m_downloader->init(dest_folder);
|
||||
m_downloader->start_download(url);
|
||||
}
|
||||
|
||||
bool is_support_filament(int extruder_id)
|
||||
{
|
||||
auto &filament_presets = Slic3r::GUI::wxGetApp().preset_bundle->filament_presets;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue