diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 6b1984b893..b409e7d06d 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -115,7 +115,8 @@ int CLI::run(int argc, char **argv) std::find(m_transforms.begin(), m_transforms.end(), "cut") == m_transforms.end() && std::find(m_transforms.begin(), m_transforms.end(), "cut_x") == m_transforms.end() && std::find(m_transforms.begin(), m_transforms.end(), "cut_y") == m_transforms.end(); - bool start_as_downloader = false; + bool start_downloader = false; + std::string download_url; bool start_as_gcodeviewer = #ifdef _WIN32 false; @@ -177,14 +178,13 @@ int CLI::run(int argc, char **argv) start_as_gcodeviewer = true; break; } - for (const std::string& file : m_input_files) { - //if (boost::starts_with(file, "open?file=")) { - start_as_downloader = true; - break; - //} - } - if (!start_as_gcodeviewer && !start_as_downloader) { + if (!start_as_gcodeviewer) { for (const std::string& file : m_input_files) { + if (boost::starts_with(file, "prusaslicer://")) { + start_downloader = true; + download_url = file; + continue; + } if (!boost::filesystem::exists(file)) { boost::nowide::cerr << "No such file: " << file << std::endl; exit(1); @@ -625,7 +625,8 @@ int CLI::run(int argc, char **argv) params.extra_config = std::move(m_extra_config); params.input_files = std::move(m_input_files); params.start_as_gcodeviewer = start_as_gcodeviewer; - params.start_as_downloader = start_as_downloader; + params.start_downloader = start_downloader; + params.download_url = download_url; return Slic3r::GUI::GUI_Run(params); #else // SLIC3R_GUI // No GUI support. Just print out a help. diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index f56e59e00a..f44290ab0e 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -1253,11 +1253,13 @@ PageUpdate::PageUpdate(ConfigWizard *parent) boost::filesystem::path binary_path(resources_dir()); - binary_path = binary_path.parent_path() / "prusa-slicer-downloader.exe"; + //binary_path = binary_path.parent_path() / "prusa-slicer-downloader.exe"; + binary_path = binary_path.parent_path() / "prusa-slicer-console.exe"; std::string binary_string = binary_path.string(); - std::string key_string = "\"" + binary_string + "\" \"-u\" \"%1\""; + //std::string key_string = "\"" + binary_string + "\" \"-u\" \"%1\""; + std::string key_string = "\"" + binary_string + "\" \"%1\""; wxRegKey key_first(wxRegKey::HKCU, "Software\\Classes\\prusaslicer"); wxRegKey key_full(wxRegKey::HKCU, "Software\\Classes\\prusaslicer\\shell\\open\\command"); diff --git a/src/slic3r/GUI/Downloader.cpp b/src/slic3r/GUI/Downloader.cpp index 3745f44c65..02ac181b09 100644 --- a/src/slic3r/GUI/Downloader.cpp +++ b/src/slic3r/GUI/Downloader.cpp @@ -1,6 +1,9 @@ -#include "Download.hpp" +#include "Downloader.hpp" +#include "GUI_App.hpp" +#include "NotificationManager.hpp" -namespace Downloader{ +namespace Slic3r { +namespace GUI { namespace { std::string filename_from_url(const std::string& url) @@ -44,4 +47,75 @@ void Download::resume() m_state = DownloadState::DownloadOngoing; m_file_get->resume(); } + + +Downloader::Downloader() + : wxEvtHandler() +{ + Bind(EVT_DWNLDR_FILE_COMPLETE, [](const wxCommandEvent& evt) {}); + Bind(EVT_DWNLDR_FILE_PROGRESS, [](const wxCommandEvent& evt) {}); + Bind(EVT_DWNLDR_FILE_ERROR, [](const wxCommandEvent& evt) {}); + Bind(EVT_DWNLDR_FILE_NAME_CHANGE, [](const wxCommandEvent& evt) {}); + + Bind(EVT_DWNLDR_FILE_COMPLETE, &Downloader::on_complete, this); + Bind(EVT_DWNLDR_FILE_PROGRESS, &Downloader::on_progress, this); + Bind(EVT_DWNLDR_FILE_ERROR, &Downloader::on_error, this); + Bind(EVT_DWNLDR_FILE_NAME_CHANGE, &Downloader::on_name_change, this); +} + +void Downloader::start_download(const std::string& full_url) +{ + assert(m_initialized); + // prusaslicer://open/?file=https%3A%2F%2Fmedia.prusaverse.coex.cz%2Fmedia%2Fprints%2F78695%2Fstls%2F847188_185abf43-1439-4466-8777-3f625719498f%2Farm-upper-arm.stl + if (full_url.rfind("prusaslicer://open/?file=", 0) != 0) { + BOOST_LOG_TRIVIAL(error) << "Could not start download due to wrong url: " << full_url << " " << full_url.rfind("prusaslicer://open?file=", 0); + return; + } + size_t id = get_next_id(); + std::string escaped_url = FileGet::escape_url(full_url.substr(25)); + 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, text, std::bind(&Downloader::cancel_callback, this)); + m_downloads.back()->start(); + BOOST_LOG_TRIVIAL(error) << "started download"; +} + +void Downloader::on_progress(wxCommandEvent& event) +{ + size_t id = event.GetInt(); + float percent = (float)std::stoi(boost::nowide::narrow(event.GetString())) / 100.f; + BOOST_LOG_TRIVIAL(error) << "progress " << id << ": " << percent; + NotificationManager* ntf_mngr = wxGetApp().notification_manager(); + ntf_mngr->set_download_URL_progress(id, percent); +} +void Downloader::on_error(wxCommandEvent& event) +{ + set_download_state(event.GetInt(), DownloadState::DownloadError); +} +void Downloader::on_complete(wxCommandEvent& event) +{ + set_download_state(event.GetInt(), DownloadState::DownloadDone); +} +bool Downloader::cancel_callback() +{ + //TODO + return true; +} +void Downloader::on_name_change(wxCommandEvent& event) +{ + +} + +void Downloader::set_download_state(size_t id, DownloadState state) +{ + for (size_t i = 0; i < m_downloads.size(); ++i) { + if (m_downloads[i]->get_id() == id) { + m_downloads[i]->set_state(state); + return; + } + } +} + +} } \ No newline at end of file diff --git a/src/slic3r/GUI/Downloader.hpp b/src/slic3r/GUI/Downloader.hpp index 2b5da07357..4f4cb6d675 100644 --- a/src/slic3r/GUI/Downloader.hpp +++ b/src/slic3r/GUI/Downloader.hpp @@ -1,11 +1,14 @@ -#ifndef slic3r_Download_hpp_ -#define slic3r_Download_hpp_ - -#include "FileGet.hpp" +#ifndef slic3r_Downloader_hpp_ +#define slic3r_Downloader_hpp_ +#include "DownloaderFileGet.hpp" +#include #include -namespace Downloader { +namespace Slic3r { +namespace GUI { + +class NotificationManager; enum DownloadState { @@ -20,7 +23,7 @@ enum DownloadState class Download { public: - Download(int ID, std::string url, wxEvtHandler* evt_handler,const boost::filesystem::path& dest_folder); + Download(int ID, std::string url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder); void start(); void cancel(); void pause(); @@ -38,6 +41,47 @@ private: std::shared_ptr m_file_get; DownloadState m_state { DownloadState::DownloadPending }; }; -} +class Downloader : public wxEvtHandler { +public: + Downloader(); + + bool get_initialized() { return m_initialized; } + void init(const boost::filesystem::path& dest_folder) + { + m_dest_folder = dest_folder; + m_initialized = true; + } + void start_download(const std::string& full_url); + + bool cancel_callback(); +private: + bool m_initialized { false }; + + std::vector> m_downloads; + boost::filesystem::path m_dest_folder; + + size_t m_next_id { 0 }; + size_t get_next_id() { return ++m_next_id; } + + void on_progress(wxCommandEvent& event); + void on_error(wxCommandEvent& event); + void on_complete(wxCommandEvent& event); + void on_name_change(wxCommandEvent& event); + + void set_download_state(size_t id, DownloadState state); + /* + bool is_in_state(int id, DownloadState state) const; + DownloadState get_download_state(int id) const; + bool cancel_download(int id); + bool pause_download(int id); + bool resume_download(int id); + bool delete_download(int id); + wxString get_path_of(int id) const; + wxString get_folder_path_of(int id) const; + */ +}; + +} +} #endif \ No newline at end of file diff --git a/src/slic3r/GUI/DownloaderFileGet.cpp b/src/slic3r/GUI/DownloaderFileGet.cpp index 2b261fd358..fd8d45ff94 100644 --- a/src/slic3r/GUI/DownloaderFileGet.cpp +++ b/src/slic3r/GUI/DownloaderFileGet.cpp @@ -1,13 +1,12 @@ -#include "FileGet.hpp" - +#include "DownloaderFileGet.hpp" #include #include #include #include - -namespace Downloader { +namespace Slic3r { +namespace GUI { const size_t DOWNLOAD_MAX_CHUNK_SIZE = 10 * 1024 * 1024; const size_t DOWNLOAD_SIZE_LIMIT = 1024 * 1024 * 1024; @@ -39,13 +38,13 @@ unsigned get_current_pid() } // int = DOWNLOAD ID; string = file path -wxDEFINE_EVENT(EVT_FILE_COMPLETE, wxCommandEvent); +wxDEFINE_EVENT(EVT_DWNLDR_FILE_COMPLETE, wxCommandEvent); // int = DOWNLOAD ID; string = error msg -wxDEFINE_EVENT(EVT_FILE_ERROR, wxCommandEvent); +wxDEFINE_EVENT(EVT_DWNLDR_FILE_ERROR, wxCommandEvent); // int = DOWNLOAD ID; string = progress percent -wxDEFINE_EVENT(EVT_FILE_PROGRESS, wxCommandEvent); +wxDEFINE_EVENT(EVT_DWNLDR_FILE_PROGRESS, wxCommandEvent); // int = DOWNLOAD ID; string = name -wxDEFINE_EVENT(EVT_FILE_NAME_CHANGE, wxCommandEvent); +wxDEFINE_EVENT(EVT_DWNLDR_FILE_NAME_CHANGE, wxCommandEvent); struct FileGet::priv @@ -99,7 +98,7 @@ void FileGet::priv::get_perform() m_tmp_path = m_dest_folder / (m_filename + "." + std::to_string(get_current_pid()) + ".download"); - wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_NAME_CHANGE); + wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_NAME_CHANGE); evt->SetString(boost::nowide::widen(m_filename)); evt->SetInt(m_id); m_evt_handler->QueueEvent(evt); @@ -120,10 +119,10 @@ void FileGet::priv::get_perform() size_t written_previously = m_written; size_t written_this_session = 0; - Downloader::Http::get(m_url) + Http::get(m_url) .size_limit(DOWNLOAD_SIZE_LIMIT) //more? .set_range(range_string) - .on_progress([&](Downloader::Http::Progress progress, bool& cancel) { + .on_progress([&](Http::Progress progress, bool& cancel) { if (m_cancel) { fclose(file); // remove canceled file @@ -139,7 +138,7 @@ void FileGet::priv::get_perform() return; } - wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_PROGRESS); + wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_PROGRESS); /*if (progress.dlnow == 0 && m_written == 0) { evt->SetString("0"); evt->SetInt(m_id); @@ -155,7 +154,7 @@ void FileGet::priv::get_perform() catch (const std::exception& e) { // fclose(file); do it? - wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_ERROR); + wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR); evt->SetString(e.what()); evt->SetInt(m_id); m_evt_handler->QueueEvent(evt); @@ -173,7 +172,7 @@ void FileGet::priv::get_perform() }) .on_error([&](std::string body, std::string error, unsigned http_status) { fclose(file); - wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_ERROR); + wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR); evt->SetString(error); evt->SetInt(m_id); m_evt_handler->QueueEvent(evt); @@ -202,14 +201,14 @@ void FileGet::priv::get_perform() { //TODO: report? //error_message = GUI::format("Failed to write and move %1% to %2%", tmp_path, dest_path); - wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_ERROR); + wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR); evt->SetString("Failed to write and move."); evt->SetInt(m_id); m_evt_handler->QueueEvent(evt); return; } - wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_COMPLETE); + wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_COMPLETE); evt->SetString(dest_path.string()); evt->SetInt(m_id); m_evt_handler->QueueEvent(evt); @@ -276,5 +275,5 @@ void FileGet::resume() p->get_perform(); }); } - +} } diff --git a/src/slic3r/GUI/DownloaderFileGet.hpp b/src/slic3r/GUI/DownloaderFileGet.hpp index dd4ab24e42..c73a3ba330 100644 --- a/src/slic3r/GUI/DownloaderFileGet.hpp +++ b/src/slic3r/GUI/DownloaderFileGet.hpp @@ -1,7 +1,7 @@ -#ifndef slic3r_FileGet_hpp_ -#define slic3r_FileGet_hpp_ +#ifndef slic3r_DownloaderFileGet_hpp_ +#define slic3r_DownloaderFileGet_hpp_ -#include "FromSlicer/Http.hpp" +#include "../Utils/Http.hpp" #include #include @@ -9,7 +9,8 @@ #include #include -namespace Downloader { +namespace Slic3r { +namespace GUI { class FileGet : public std::enable_shared_from_this { private: struct priv; @@ -27,12 +28,13 @@ private: std::unique_ptr p; }; // int = DOWNLOAD ID; string = file path -wxDECLARE_EVENT(EVT_FILE_COMPLETE, wxCommandEvent); +wxDECLARE_EVENT(EVT_DWNLDR_FILE_COMPLETE, wxCommandEvent); // int = DOWNLOAD ID; string = error msg -wxDECLARE_EVENT(EVT_FILE_PROGRESS, wxCommandEvent); +wxDECLARE_EVENT(EVT_DWNLDR_FILE_PROGRESS, wxCommandEvent); // int = DOWNLOAD ID; string = progress percent -wxDECLARE_EVENT(EVT_FILE_ERROR, wxCommandEvent); +wxDECLARE_EVENT(EVT_DWNLDR_FILE_ERROR, wxCommandEvent); // int = DOWNLOAD ID; string = name -wxDECLARE_EVENT(EVT_FILE_NAME_CHANGE, wxCommandEvent); +wxDECLARE_EVENT(EVT_DWNLDR_FILE_NAME_CHANGE, wxCommandEvent); +} } #endif diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 8a7af08c64..2f8c49c0ec 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -76,6 +76,7 @@ #include "PrintHostDialogs.hpp" #include "DesktopIntegrationDialog.hpp" #include "SendSystemInfoDialog.hpp" +#include "Downloader.hpp" #include "BitmapCache.hpp" #include "Notebook.hpp" @@ -741,13 +742,16 @@ void GUI_App::post_init() if (! this->init_params->input_files.empty()) this->plater()->load_gcode(wxString::FromUTF8(this->init_params->input_files[0].c_str())); } - if (this->init_params->start_as_downloader) { + if (this->init_params->start_downloader) { + /* std::string msg; for (int i = 0; i < this->init_params->input_files.size(); ++i) { msg += this->init_params->input_files[i]; } show_error(nullptr, "Got url msg." + msg); + */ + start_download(this->init_params->download_url); } else { if (! this->init_params->preset_substitutions.empty()) @@ -826,6 +830,7 @@ GUI_App::GUI_App(EAppMode mode) , m_imgui(new ImGuiWrapper()) , m_removable_drive_manager(std::make_unique()) , m_other_instance_message_handler(std::make_unique()) + , m_downloader(std::make_unique()) { //app config initializes early becasuse it is used in instance checking in PrusaSlicer.cpp this->init_app_config(); @@ -1255,7 +1260,8 @@ bool GUI_App::on_init_inner() Bind(EVT_SLIC3R_APP_OPEN_FAILED, [](const wxCommandEvent& evt) { show_error(nullptr, evt.GetString()); - }); + }); + } else { #ifdef __WXMSW__ @@ -2831,11 +2837,16 @@ wxBookCtrlBase* GUI_App::tab_panel() const return mainframe->m_tabpanel; } -NotificationManager * GUI_App::notification_manager() +NotificationManager* GUI_App::notification_manager() { return plater_->get_notification_manager(); } +Downloader* GUI_App::downloader() +{ + return m_downloader.get(); +} + // extruders count from selected printer preset int GUI_App::extruders_cnt() const { @@ -3364,5 +3375,16 @@ void GUI_App::app_version_check(bool from_user) m_app_updater->sync_version(version_check_url, from_user); } +void GUI_App::start_download(std::string url) +{ + if (!plater_) { + BOOST_LOG_TRIVIAL(error) << "Could not start URL download: plater is nullptr."; + return; + } + if (!m_downloader->get_initialized()) + m_downloader->init(boost::dll::program_location().parent_path()); // TODO WHERE + m_downloader->start_download(url); +} + } // GUI } //Slic3r diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 6d317676cf..b68e49118b 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -46,6 +46,7 @@ class ObjectList; class ObjectLayers; class Plater; class NotificationManager; +class Downloader; struct GUI_InitParams; @@ -161,6 +162,7 @@ private: std::unique_ptr m_other_instance_message_handler; std::unique_ptr m_app_updater; std::unique_ptr m_single_instance_checker; + std::unique_ptr m_downloader; std::string m_instance_hash_string; size_t m_instance_hash_int; @@ -295,7 +297,8 @@ public: Plater* plater(); const Plater* plater() const; Model& model(); - NotificationManager * notification_manager(); + NotificationManager* notification_manager(); + Downloader* downloader(); // Parameters extracted from the command line to be passed to GUI after initialization. GUI_InitParams* init_params { nullptr }; @@ -372,6 +375,9 @@ private: void app_version_check(bool from_user); bool m_datadir_redefined { false }; + + // URL download - PrusaSlicer gets system call to open prusaslicer:// URL which should contain address of download + void start_download(std::string url); }; DECLARE_APP(GUI_App) diff --git a/src/slic3r/GUI/GUI_Init.hpp b/src/slic3r/GUI/GUI_Init.hpp index cf150ac7d2..e5d13c101c 100644 --- a/src/slic3r/GUI/GUI_Init.hpp +++ b/src/slic3r/GUI/GUI_Init.hpp @@ -21,7 +21,8 @@ struct GUI_InitParams std::vector input_files; bool start_as_gcodeviewer; - bool start_as_downloader; + bool start_downloader; + std::string download_url; }; int GUI_Run(GUI_InitParams ¶ms); diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index fc20e43f5d..57e0136766 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1864,7 +1864,6 @@ void NotificationManager::upload_job_notification_show_error(int id, const std:: } } } - void NotificationManager::push_download_progress_notification(const std::string& text, std::function cancel_callback) { // If already exists, change text and reset progress @@ -1896,6 +1895,41 @@ void NotificationManager::set_download_progress_percentage(float percentage) } } +void NotificationManager::push_download_URL_progress_notification(size_t id, const std::string& text, std::function cancel_callback) +{ + // If already exists + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::URLDownload && dynamic_cast(notification.get())->get_download_id() == id) { + return; + } + } + // push new one + NotificationData data{ NotificationType::URLDownload, NotificationLevel::ProgressBarNotificationLevel, 10, text }; + push_notification_data(std::make_unique(data, m_id_provider, m_evt_handler, id, cancel_callback), 0); +} +void NotificationManager::set_download_URL_progress(size_t id, float percentage) +{ + for (std::unique_ptr& notification : m_pop_notifications) { + if (notification->get_type() == NotificationType::URLDownload) { + URLDownloadNotification* ntf = dynamic_cast(notification.get()); + if (ntf->get_download_id() != id) + continue; + // if this changes the percentage, it should be shown now + BOOST_LOG_TRIVIAL(error) << percentage; + float percent_b4 = ntf->get_percentage(); + ntf->set_percentage(percentage); + if (ntf->get_percentage() != percent_b4) + wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0); + return; + } + } +} + +void NotificationManager::set_download_URL_canceled(size_t id, const std::string& text) +{} +void NotificationManager::set_download_URL_error(size_t id, const std::string& text) +{} + void NotificationManager::init_slicing_progress_notification(std::function cancel_callback) { for (std::unique_ptr& notification : m_pop_notifications) { diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index c6a24d997d..cb1e3b2825 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -115,6 +115,8 @@ enum class NotificationType NetfabbFinished, // Short meesage to fill space between start and finish of export ExportOngoing, + // Progressbar of download from prusaslicer:// url + URLDownload }; class NotificationManager @@ -208,6 +210,11 @@ public: // Download App progress void push_download_progress_notification(const std::string& text, std::function cancel_callback); void set_download_progress_percentage(float percentage); + // Download URL progress notif + void push_download_URL_progress_notification(size_t id, const std::string& text, std::function cancel_callback); + void set_download_URL_progress(size_t id, float percentage); + void set_download_URL_canceled(size_t id, const std::string& text); + void set_download_URL_error(size_t id, const std::string& text); // slicing progress void init_slicing_progress_notification(std::function cancel_callback); void set_slicing_progress_began(); @@ -495,6 +502,22 @@ private: long m_hover_time{ 0 }; }; + class URLDownloadNotification : public ProgressBarNotification//ProgressBarWithCancelNotification + { + public: + URLDownloadNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, size_t download_id, std::function cancel_callback) + //: ProgressBarWithCancelNotification(n, id_provider, evt_handler, cancel_callback) + : ProgressBarNotification(n, id_provider, evt_handler) + , m_download_id(download_id) + { + } + + size_t get_download_id() { return m_download_id; } + protected: + + size_t m_download_id; + }; + class PrintHostUploadNotification : public ProgressBarNotification { public: diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp index a6ad54b32d..c0aa68c8ce 100644 --- a/src/slic3r/Utils/Http.cpp +++ b/src/slic3r/Utils/Http.cpp @@ -144,6 +144,7 @@ struct Http::priv void set_post_body(const fs::path &path); void set_post_body(const std::string &body); void set_put_body(const fs::path &path); + void set_range(const std::string& range); std::string curl_error(CURLcode curlcode); std::string body_size_error(); @@ -225,7 +226,7 @@ int Http::priv::xfercb(void *userp, curl_off_t dltotal, curl_off_t dlnow, curl_o bool cb_cancel = false; if (self->progressfn) { - Progress progress(dltotal, dlnow, ultotal, ulnow); + Progress progress(dltotal, dlnow, ultotal, ulnow, self->buffer); self->progressfn(progress, cb_cancel); } @@ -313,6 +314,11 @@ void Http::priv::set_put_body(const fs::path &path) } } +void Http::priv::set_range(const std::string& range) +{ + ::curl_easy_setopt(curl, CURLOPT_RANGE, range.c_str()); +} + std::string Http::priv::curl_error(CURLcode curlcode) { return (boost::format("%1%:\n%2%\n[Error %3%]") @@ -370,7 +376,7 @@ void Http::priv::http_perform() if (res == CURLE_ABORTED_BY_CALLBACK) { if (cancel) { // The abort comes from the request being cancelled programatically - Progress dummyprogress(0, 0, 0, 0); + Progress dummyprogress(0, 0, 0, 0, std::string()); bool cancel = true; if (progressfn) { progressfn(dummyprogress, cancel); } } else { @@ -438,6 +444,12 @@ Http& Http::size_limit(size_t sizeLimit) return *this; } +Http& Http::set_range(const std::string& range) +{ + if (p) { p->set_range(range); } + return *this; +} + Http& Http::header(std::string name, const std::string &value) { if (!p) { return * this; } diff --git a/src/slic3r/Utils/Http.hpp b/src/slic3r/Utils/Http.hpp index 2f458582d2..a99b6164b1 100644 --- a/src/slic3r/Utils/Http.hpp +++ b/src/slic3r/Utils/Http.hpp @@ -21,9 +21,10 @@ public: size_t dlnow; // Bytes downloaded so far size_t ultotal; // Total bytes to upload size_t ulnow; // Bytes uploaded so far + const std::string& buffer; // reference to buffer containing all data - Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) : - dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow) + Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow, const std::string& buffer) : + dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow), buffer(buffer) {} }; @@ -65,6 +66,8 @@ public: // Sets a maximum size of the data that can be received. // A value of zero sets the default limit, which is is 5MB. Http& size_limit(size_t sizeLimit); + // range of donloaded bytes. example: curl_easy_setopt(curl, CURLOPT_RANGE, "0-199"); + Http& set_range(const std::string& range); // Sets a HTTP header field. Http& header(std::string name, const std::string &value); // Removes a header field.