mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-05 21:06:07 +08:00
Multiple downloads witch mid download saving to file
This commit is contained in:
parent
816dd9490d
commit
648e56d8bf
@ -24,9 +24,12 @@ Download::Download(int ID, std::string url, wxEvtHandler* evt_handler, const boo
|
||||
|
||||
void Download::start()
|
||||
{
|
||||
m_state = DownloadState::DownloadOngoing;
|
||||
m_file_get->get();
|
||||
}
|
||||
void Download::stop()
|
||||
void Download::cancel()
|
||||
{
|
||||
m_state = DownloadState::DownloadStopped;
|
||||
m_file_get->cancel();
|
||||
}
|
||||
}
|
@ -7,21 +7,34 @@
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
enum DownloadState
|
||||
{
|
||||
DownloadPending,
|
||||
DownloadOngoing,
|
||||
DownloadStopped,
|
||||
DownloadDone,
|
||||
DownloadError,
|
||||
|
||||
};
|
||||
|
||||
class Download {
|
||||
public:
|
||||
Download(int ID, std::string url, wxEvtHandler* evt_handler,const boost::filesystem::path& dest_folder);
|
||||
void start();
|
||||
void stop();
|
||||
void cancel();
|
||||
// void pause();
|
||||
|
||||
int get_id() const { return m_id; }
|
||||
boost::filesystem::path get_final_path() const { return m_final_path; }
|
||||
std::string get_filename() const { return m_filename; }
|
||||
DownloadState get_state() const { return m_state; }
|
||||
void set_state(DownloadState state) { m_state = state; }
|
||||
private:
|
||||
const int m_id;
|
||||
std::string m_filename;
|
||||
boost::filesystem::path m_final_path;
|
||||
std::shared_ptr<FileGet> m_file_get;
|
||||
DownloadState m_state { DownloadState::DownloadPending };
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,61 @@
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
|
||||
namespace{
|
||||
void open_folder(const wxString& widepath)
|
||||
{
|
||||
// Code taken from desktop_open_datadir_folder()
|
||||
|
||||
// Execute command to open a file explorer, platform dependent.
|
||||
// FIXME: The const_casts aren't needed in wxWidgets 3.1, remove them when we upgrade.
|
||||
|
||||
#ifdef _WIN32
|
||||
//const wxString widepath = wxString::FromUTF8(path.c_str());
|
||||
const wchar_t* argv[] = { L"explorer", widepath.GetData(), nullptr };
|
||||
::wxExecute(const_cast<wchar_t**>(argv), wxEXEC_ASYNC, nullptr);
|
||||
#elif __APPLE__
|
||||
std::string path = boost::nowide::narrow(widepath);
|
||||
const char* argv[] = { "open", path.data(), nullptr };
|
||||
::wxExecute(const_cast<char**>(argv), wxEXEC_ASYNC, nullptr);
|
||||
#else
|
||||
std::string path = boost::nowide::narrow(widepath);
|
||||
const char* argv[] = { "xdg-open", path.data(), nullptr };
|
||||
|
||||
// Check if we're running in an AppImage container, if so, we need to remove AppImage's env vars,
|
||||
// because they may mess up the environment expected by the file manager.
|
||||
// Mostly this is about LD_LIBRARY_PATH, but we remove a few more too for good measure.
|
||||
if (wxGetEnv("APPIMAGE", nullptr)) {
|
||||
// We're running from AppImage
|
||||
wxEnvVariableHashMap env_vars;
|
||||
wxGetEnvMap(&env_vars);
|
||||
|
||||
env_vars.erase("APPIMAGE");
|
||||
env_vars.erase("APPDIR");
|
||||
env_vars.erase("LD_LIBRARY_PATH");
|
||||
env_vars.erase("LD_PRELOAD");
|
||||
env_vars.erase("UNION_PRELOAD");
|
||||
|
||||
wxExecuteEnv exec_env;
|
||||
exec_env.env = std::move(env_vars);
|
||||
|
||||
wxString owd;
|
||||
if (wxGetEnv("OWD", &owd)) {
|
||||
// This is the original work directory from which the AppImage image was run,
|
||||
// set it as CWD for the child process:
|
||||
exec_env.cwd = std::move(owd);
|
||||
}
|
||||
|
||||
::wxExecute(const_cast<char**>(argv), wxEXEC_ASYNC, nullptr, &exec_env);
|
||||
}
|
||||
else {
|
||||
// Looks like we're NOT running from AppImage, we'll make no changes to the environment.
|
||||
::wxExecute(const_cast<char**>(argv), wxEXEC_ASYNC, nullptr, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool DownloadApp::OnInit()
|
||||
{
|
||||
m_dwnldr_send = std::make_unique<DownloaderSend>();
|
||||
@ -16,10 +71,10 @@ bool DownloadApp::OnInit()
|
||||
|
||||
if (m_dwnldr_send->get_instance_exists()) {
|
||||
m_other_exists = true;
|
||||
m_frame = new DownloadFrame("PrusaSlicer-Downloader", wxPoint(50, 50), wxSize(0,0));
|
||||
m_frame = new DownloadFrame("Downloader", wxPoint(50, 50), wxSize(0,0));
|
||||
return wxApp::OnInit();
|
||||
}
|
||||
m_frame = new DownloadFrame("PrusaSlicer-Downloader", wxPoint(50, 50), wxSize(450, 340));
|
||||
m_frame = new DownloadFrame("Downloader", wxPoint(50, 50), wxSize(450, 340));
|
||||
m_frame->Show(true);
|
||||
|
||||
wxWindow::MSWRegisterMessageHandler(WM_COPYDATA, [](wxWindow* win, WXUINT /* nMsg */, WXWPARAM wParam, WXLPARAM lParam) {
|
||||
@ -70,6 +125,8 @@ bool DownloadApp::OnCmdLineParsed(wxCmdLineParser& parser)
|
||||
if (!url.empty() && m_frame != nullptr)
|
||||
m_frame->start_download(std::move(url));
|
||||
|
||||
m_frame->start_download("open?file=https%3A%2F%2Fmedia.printables.com%2Fmedia%2Fprints%2F152208%2Fstls%2F1431590_8b8287b3-03b1-4cbe-82d0-268a0affa171%2Ff1_logo.stl");
|
||||
|
||||
return wxApp::OnCmdLineParsed(parser);
|
||||
}
|
||||
}
|
||||
@ -78,35 +135,62 @@ bool DownloadApp::OnCmdLineParsed(wxCmdLineParser& parser)
|
||||
|
||||
DownloadFrame::DownloadFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
|
||||
: wxFrame(NULL, wxID_ANY, title, pos, size)
|
||||
, m_instance_send(std::make_unique<SlicerSend>())
|
||||
, m_slicer_send(std::make_unique<SlicerSend>())
|
||||
{
|
||||
|
||||
dataview = new wxDataViewListCtrl(this, wxID_ANY);
|
||||
auto * data_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
/* dataview->AppendColumn(new wxDataViewColumn("ID", new TextRenderer(), 0, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE));
|
||||
dataview->AppendColumn(new wxDataViewColumn("Filename", new TextRenderer(), 1, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE));
|
||||
dataview->AppendProgressColumn("Progress", wxDATAVIEW_CELL_INERT, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
dataview->AppendColumn(new wxDataViewColumn("status", new TextRenderer(), 2, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE));*/
|
||||
m_dataview = new wxDataViewListCtrl(this, wxID_ANY);
|
||||
|
||||
/* m_dataview->AppendColumn(new wxDataViewColumn("ID", new TextRenderer(), 0, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE));
|
||||
m_dataview->AppendColumn(new wxDataViewColumn("Filename", new TextRenderer(), 1, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE));
|
||||
m_dataview->AppendProgressColumn("Progress", wxDATAVIEW_CELL_INERT, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
m_dataview->AppendColumn(new wxDataViewColumn("status", new TextRenderer(), 2, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE));*/
|
||||
|
||||
|
||||
dataview->AppendTextColumn("ID", wxDATAVIEW_CELL_INERT, 30, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
dataview->AppendTextColumn("Filename", wxDATAVIEW_CELL_INERT, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
dataview->AppendProgressColumn("Progress", wxDATAVIEW_CELL_INERT, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
dataview->AppendTextColumn("status", wxDATAVIEW_CELL_INERT, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
|
||||
m_dataview->AppendTextColumn("ID", wxDATAVIEW_CELL_INERT, 30, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
m_dataview->AppendTextColumn("Filename", wxDATAVIEW_CELL_INERT, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
m_dataview->AppendProgressColumn("Progress", wxDATAVIEW_CELL_INERT, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
m_dataview->AppendTextColumn("status", wxDATAVIEW_CELL_INERT, 100, wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
|
||||
data_sizer->Add(m_dataview, 1, wxEXPAND | wxBOTTOM);
|
||||
|
||||
m_dest_folder = boost::filesystem::path("C:\\Users\\User\\Downloads");
|
||||
|
||||
m_log_label = new wxStaticText(this, wxID_ANY, "Log:");
|
||||
auto* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
//sizer->Add(m_log_label, wxEXPAND);
|
||||
sizer->Add(dataview, 1, wxEXPAND | wxBOTTOM);
|
||||
SetSizer(sizer);
|
||||
//m_log_label = new wxStaticText(this, wxID_ANY, "Log:");
|
||||
|
||||
////sizer->Add(m_log_label, wxEXPAND);
|
||||
//
|
||||
|
||||
|
||||
|
||||
wxBoxSizer* btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxButton* btn_run = new wxButton(this, wxID_OK, "Run");
|
||||
btn_run->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) { on_open_in_slicer(evt); });
|
||||
btn_sizer->Add(btn_run, 0, wxLEFT | wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxButton* btn_run_new = new wxButton(this, wxID_EDIT, "Run new");
|
||||
btn_run_new->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) { on_open_in_new_slicer(evt); });
|
||||
btn_sizer->Add(btn_run_new, 0, wxLEFT | wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxButton* btn_folder = new wxButton(this, wxID_EDIT, "Open");
|
||||
btn_folder->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) { on_open_in_explorer(evt); });
|
||||
btn_sizer->Add(btn_folder, 0, wxLEFT | wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxButton* btn_cancel = new wxButton(this, wxID_EDIT, "Cancel");
|
||||
btn_cancel->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) { on_cancel_button(evt); });
|
||||
btn_sizer->Add(btn_cancel, 0, wxLEFT | wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
//main_sizer->Add(data_sizer);
|
||||
//main_sizer->Add(btn_sizer);
|
||||
|
||||
data_sizer->Add(btn_sizer, 0, wxEXPAND);
|
||||
SetSizer(data_sizer);
|
||||
|
||||
Bind(EVT_FILE_COMPLETE, &DownloadFrame::on_complete, this);
|
||||
Bind(EVT_FILE_PROGRESS, &DownloadFrame::on_progress, this);
|
||||
Bind(EVT_FILE_ERROR, &DownloadFrame::on_error, this);
|
||||
Bind(EVT_FILE_NAME_CHANGE, &DownloadFrame::on_name_change, this);
|
||||
}
|
||||
|
||||
void DownloadFrame::start_download(wxString url)
|
||||
@ -115,62 +199,177 @@ void DownloadFrame::start_download(wxString url)
|
||||
if (url.starts_with("open?file=")) {
|
||||
int id = get_next_id();
|
||||
std::string escaped_url = FileGet::escape_url(boost::nowide::narrow(url.substr(10)));
|
||||
log(std::to_string(id) + ": start " + escaped_url);
|
||||
//log(std::to_string(id) + ": start " + escaped_url);
|
||||
escaped_url = "https://media.printables.com/media/prints/216267/gcodes/1974221_32d21613-b567-4328-8261-49b46d9dd249/01_big_trex_skull_with_threads_015mm_pla_mk3_2d.gcode";
|
||||
m_downloads.emplace_back(std::make_unique<Download>(id, std::move(escaped_url), this, m_dest_folder));
|
||||
m_downloads.back()->start();
|
||||
//
|
||||
|
||||
wxVector<wxVariant> fields;
|
||||
fields.push_back(wxVariant(std::to_wstring(id)));
|
||||
fields.push_back(wxVariant(m_downloads.back()->get_filename()));
|
||||
fields.push_back(wxVariant(0));
|
||||
fields.push_back(wxVariant("Pending"));
|
||||
dataview->AppendItem(fields);
|
||||
m_dataview->AppendItem(fields);
|
||||
|
||||
bool can_start = true;
|
||||
for (size_t i = 0; i < m_downloads.size(); i++) {
|
||||
if (m_downloads[i]->get_state() == DownloadState::DownloadOngoing) {
|
||||
//can_start = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (can_start)
|
||||
m_downloads.back()->start();
|
||||
|
||||
} else {
|
||||
log("wrong url: " + url);
|
||||
//log("wrong url: " + url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DownloadFrame::log(const wxString& msg)
|
||||
{
|
||||
m_log_lines++;
|
||||
wxString old_log = m_log_label->GetLabel();
|
||||
if (m_log_lines > 10) {
|
||||
size_t endline = old_log.Find('\n');
|
||||
endline = old_log.find('\n', endline + 1);
|
||||
if (endline != wxString::npos) {
|
||||
old_log = "Log:\n" + old_log.substr(endline + 1);
|
||||
}
|
||||
}
|
||||
//m_log_label->SetLabel(old_log +"\n"+ msg);
|
||||
//printf("%s\n",old_log + "\n" + msg);
|
||||
m_full_log += +"\n" + msg;
|
||||
//m_log_lines++;
|
||||
//wxString old_log = m_log_label->GetLabel();
|
||||
//if (m_log_lines > 10) {
|
||||
// size_t endline = old_log.Find('\n');
|
||||
// endline = old_log.find('\n', endline + 1);
|
||||
// if (endline != wxString::npos) {
|
||||
// old_log = "Log:\n" + old_log.substr(endline + 1);
|
||||
// }
|
||||
//}
|
||||
////m_log_label->SetLabel(old_log +"\n"+ msg);
|
||||
////printf("%s\n",old_log + "\n" + msg);
|
||||
//m_full_log += +"\n" + msg;
|
||||
}
|
||||
|
||||
void DownloadFrame::on_progress(wxCommandEvent& event)
|
||||
{
|
||||
//log(std::to_string(event.GetInt()) + ": " + event.GetString());
|
||||
dataview->SetValue(std::stoi(boost::nowide::narrow(event.GetString())), event.GetInt() - 1, 2);
|
||||
dataview->SetValue("Downloading", event.GetInt() -1, 3);
|
||||
m_dataview->SetValue(std::stoi(boost::nowide::narrow(event.GetString())), event.GetInt() - 1, 2);
|
||||
m_dataview->SetValue("Downloading", event.GetInt() -1, 3);
|
||||
|
||||
}
|
||||
void DownloadFrame::on_error(wxCommandEvent& event)
|
||||
{
|
||||
//log(std::to_string(event.GetInt()) + ": " + event.GetString());
|
||||
//SetStatusText(event.GetString().c_str());
|
||||
dataview->SetValue("Error", event.GetInt() - 1, 3);
|
||||
set_download_state(event.GetInt(), DownloadState::DownloadError);
|
||||
m_dataview->SetValue("Error", event.GetInt() - 1, 3);
|
||||
}
|
||||
void DownloadFrame::on_complete(wxCommandEvent& event)
|
||||
{
|
||||
dataview->SetValue("Done", event.GetInt() - 1, 3);
|
||||
m_instance_send->start_with_path(event.GetString());
|
||||
|
||||
|
||||
set_download_state(event.GetInt(), DownloadState::DownloadDone);
|
||||
m_dataview->SetValue("Done", event.GetInt() - 1, 3);
|
||||
start_next();
|
||||
}
|
||||
void DownloadFrame::on_name_change(wxCommandEvent& event)
|
||||
{
|
||||
m_dataview->SetValue(event.GetString(), event.GetInt() - 1, 1);
|
||||
}
|
||||
void DownloadFrame::start_next()
|
||||
{
|
||||
for (size_t i = 0; i < m_downloads.size(); i++) {
|
||||
if (m_downloads[i]->get_state() == DownloadState::DownloadPending) {
|
||||
m_downloads[i]->start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadFrame::on_open_in_slicer(wxCommandEvent& event)
|
||||
{
|
||||
int selected = m_dataview->GetSelectedRow();
|
||||
if (selected == wxNOT_FOUND) { return; }
|
||||
int id = std::stoi(boost::nowide::narrow(m_dataview->GetTextValue(selected,0)));
|
||||
|
||||
if (is_in_state(id, DownloadState::DownloadDone)) {
|
||||
m_slicer_send->start_or_send(get_path_of(id));
|
||||
}
|
||||
}
|
||||
void DownloadFrame::on_open_in_new_slicer(wxCommandEvent& event)
|
||||
{
|
||||
int selected = m_dataview->GetSelectedRow();
|
||||
if (selected == wxNOT_FOUND) { return; }
|
||||
int id = std::stoi(boost::nowide::narrow(m_dataview->GetTextValue(selected, 0)));
|
||||
|
||||
if (is_in_state(id, DownloadState::DownloadDone)) {
|
||||
m_slicer_send->start_with_path(get_path_of(id));
|
||||
}
|
||||
}
|
||||
void DownloadFrame::on_open_in_explorer(wxCommandEvent& event)
|
||||
{
|
||||
int selected = m_dataview->GetSelectedRow();
|
||||
if (selected == wxNOT_FOUND) { return; }
|
||||
int id = std::stoi(boost::nowide::narrow(m_dataview->GetTextValue(selected, 0)));
|
||||
|
||||
if (is_in_state(id, DownloadState::DownloadDone)) {
|
||||
open_folder(get_folder_path_of(id));
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadFrame::on_cancel_button(wxCommandEvent& event)
|
||||
{
|
||||
int selected = m_dataview->GetSelectedRow();
|
||||
if (selected == wxNOT_FOUND) { return; }
|
||||
int id = std::stoi(boost::nowide::narrow(m_dataview->GetTextValue(selected, 0)));
|
||||
|
||||
if(cancel_download(id))
|
||||
m_dataview->SetValue("Canceled", id - 1, 3);
|
||||
}
|
||||
|
||||
void DownloadFrame::set_download_state(int 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DownloadFrame::is_in_state(int id, DownloadState state) const
|
||||
{
|
||||
for (size_t i = 0; i < m_downloads.size(); ++i) {
|
||||
if (m_downloads[i]->get_id() == id) {
|
||||
return m_downloads[i]->get_state();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DownloadFrame::cancel_download(int id)
|
||||
{
|
||||
for (size_t i = 0; i < m_downloads.size(); ++i) {
|
||||
if (m_downloads[i]->get_id() == id) {
|
||||
if (m_downloads[i]->get_state() == DownloadState::DownloadOngoing) {
|
||||
m_downloads[i]->cancel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
wxString DownloadFrame::get_path_of(int id) const
|
||||
{
|
||||
for (size_t i = 0; i < m_downloads.size(); ++i) {
|
||||
if (m_downloads[i]->get_id() == id) {
|
||||
return m_downloads[i]->get_final_path().string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxString DownloadFrame::get_folder_path_of(int id) const
|
||||
{
|
||||
for (size_t i = 0; i < m_downloads.size(); ++i) {
|
||||
if (m_downloads[i]->get_id() == id) {
|
||||
return m_downloads[i]->get_final_path().parent_path().string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadFrame::handle_message(const wxString& msg)
|
||||
{
|
||||
log("recieved: " + msg);
|
||||
//log("recieved: " + msg);
|
||||
start_download(msg);
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,20 @@ private:
|
||||
void on_progress(wxCommandEvent& event);
|
||||
void on_error(wxCommandEvent& event);
|
||||
void on_complete(wxCommandEvent& event);
|
||||
|
||||
|
||||
void on_name_change(wxCommandEvent& event);
|
||||
void on_open_in_slicer(wxCommandEvent& event);
|
||||
void on_open_in_new_slicer(wxCommandEvent& event);
|
||||
void on_open_in_explorer(wxCommandEvent& event);
|
||||
void on_cancel_button(wxCommandEvent& event);
|
||||
|
||||
|
||||
void start_next();
|
||||
void set_download_state(int id, DownloadState state);
|
||||
bool is_in_state(int id, DownloadState state) const;
|
||||
bool cancel_download(int id);
|
||||
wxString get_path_of(int id) const;
|
||||
wxString get_folder_path_of(int id) const;
|
||||
|
||||
int m_next_id { 0 };
|
||||
int get_next_id() {return ++m_next_id; }
|
||||
|
||||
@ -33,12 +45,12 @@ private:
|
||||
size_t m_log_lines { 0 };
|
||||
wxString m_full_log;
|
||||
|
||||
wxDataViewListCtrl* dataview;
|
||||
wxDataViewListCtrl* m_dataview;
|
||||
|
||||
wxString m_url;
|
||||
wxString m_path_to_slicer;
|
||||
|
||||
std::unique_ptr<SlicerSend> m_instance_send;
|
||||
std::unique_ptr<SlicerSend> m_slicer_send;
|
||||
|
||||
boost::filesystem::path m_dest_folder;
|
||||
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
const size_t DOWNLOAD_MAX_CHUNK_SIZE = 10 * 1024 * 1024;
|
||||
const size_t DOWNLOAD_SIZE_LIMIT = 1024 * 1024 * 1024;
|
||||
|
||||
std::string FileGet::escape_url(const std::string& unescaped)
|
||||
{
|
||||
@ -41,6 +43,9 @@ wxDEFINE_EVENT(EVT_FILE_COMPLETE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_FILE_ERROR, wxCommandEvent);
|
||||
// int = DOWNLOAD ID; string = progress percent
|
||||
wxDEFINE_EVENT(EVT_FILE_PROGRESS, wxCommandEvent);
|
||||
// int = DOWNLOAD ID; string = name
|
||||
wxDEFINE_EVENT(EVT_FILE_NAME_CHANGE, wxCommandEvent);
|
||||
|
||||
|
||||
struct FileGet::priv
|
||||
{
|
||||
@ -73,23 +78,72 @@ void FileGet::priv::get_perform()
|
||||
assert(!m_filename.empty());
|
||||
assert(boost::filesystem::is_directory(m_dest_folder));
|
||||
|
||||
// open dest file
|
||||
boost::filesystem::path dest_path = m_dest_folder / m_filename;
|
||||
std::string extension = boost::filesystem::extension(dest_path);
|
||||
std::string just_filename = m_filename.substr(0, m_filename.size() - extension.size());
|
||||
std::string final_filename = just_filename;
|
||||
|
||||
size_t version = 0;
|
||||
while (boost::filesystem::exists(m_dest_folder / (final_filename + extension)) || boost::filesystem::exists(m_dest_folder / (final_filename + extension + "." + std::to_string(get_current_pid()) + ".download")))
|
||||
{
|
||||
++version;
|
||||
final_filename = just_filename + "(" + std::to_string(version) + ")";
|
||||
}
|
||||
m_filename = final_filename + extension;
|
||||
|
||||
boost::filesystem::path tmp_path = m_dest_folder / (m_filename + "." + std::to_string(get_current_pid()) + ".download");
|
||||
dest_path = m_dest_folder / m_filename;
|
||||
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_NAME_CHANGE);
|
||||
evt->SetString(boost::nowide::widen(m_filename));
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
|
||||
// open file for writting
|
||||
FILE* file = fopen(tmp_path.string().c_str(), "wb");
|
||||
size_t written = 0;
|
||||
|
||||
Downloader::Http::get(m_url)
|
||||
//.size_limit(size_limit)
|
||||
.size_limit(DOWNLOAD_SIZE_LIMIT) //more?
|
||||
.on_progress([&](Downloader::Http::Progress progress, bool& cancel) {
|
||||
if (m_cancel) {
|
||||
fclose(file);
|
||||
// remove canceled file
|
||||
std::remove(tmp_path.string().c_str());
|
||||
cancel = true;
|
||||
return;
|
||||
// TODO: send canceled event?
|
||||
}
|
||||
}
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_PROGRESS);
|
||||
if (progress.dlnow == 0)
|
||||
evt->SetString("0");
|
||||
else
|
||||
else {
|
||||
if (progress.dlnow - written > DOWNLOAD_MAX_CHUNK_SIZE || progress.dlnow == progress.dltotal) {
|
||||
try
|
||||
{
|
||||
std::string part_for_write = progress.buffer.substr(written, progress.dlnow);
|
||||
fwrite(part_for_write.c_str(), 1, part_for_write.size(), file);
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
// fclose(file); do it?
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_ERROR);
|
||||
evt->SetString("Failed to write progress.");
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
cancel = true;
|
||||
return;
|
||||
}
|
||||
written = progress.dlnow;
|
||||
}
|
||||
evt->SetString(std::to_string(progress.dlnow * 100 / progress.dltotal));
|
||||
}
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
})
|
||||
.on_error([&](std::string body, std::string error, unsigned http_status) {
|
||||
fclose(file);
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_ERROR);
|
||||
evt->SetString(error);
|
||||
evt->SetInt(m_id);
|
||||
@ -102,30 +156,18 @@ void FileGet::priv::get_perform()
|
||||
//if (body_size != expected_size) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
boost::filesystem::path dest_path = m_dest_folder / m_filename;
|
||||
std::string extension = boost::filesystem::extension(dest_path);
|
||||
std::string just_filename = m_filename.substr(0, m_filename.size() - extension.size());
|
||||
std::string final_filename = just_filename;
|
||||
|
||||
size_t version = 0;
|
||||
while (boost::filesystem::exists(m_dest_folder / (final_filename + extension)))
|
||||
{
|
||||
++version;
|
||||
final_filename = just_filename + "("+std::to_string(version)+")";
|
||||
}
|
||||
m_filename = final_filename + extension;
|
||||
|
||||
boost::filesystem::path tmp_path = m_dest_folder / (m_filename + "." + std::to_string(get_current_pid()) + ".download");
|
||||
dest_path = m_dest_folder / m_filename;
|
||||
try
|
||||
{
|
||||
boost::nowide::fstream file(tmp_path.string(), std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
file.write(body.c_str(), body.size());
|
||||
file.close();
|
||||
if (written < body.size())
|
||||
{
|
||||
// this code should never be entered. As there should be on_progress call after last bit downloaded.
|
||||
std::string part_for_write = body.substr(written);
|
||||
fwrite(part_for_write.c_str(), 1, part_for_write.size(), file);
|
||||
}
|
||||
fclose(file);
|
||||
boost::filesystem::rename(tmp_path, dest_path);
|
||||
}
|
||||
catch (const std::exception&)
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
//TODO: report?
|
||||
//error_message = GUI::format("Failed to write and move %1% to %2%", tmp_path, dest_path);
|
||||
|
@ -30,6 +30,7 @@ wxDECLARE_EVENT(EVT_FILE_COMPLETE, wxCommandEvent);
|
||||
wxDECLARE_EVENT(EVT_FILE_PROGRESS, wxCommandEvent);
|
||||
// int = DOWNLOAD ID; string = progress percent
|
||||
wxDECLARE_EVENT(EVT_FILE_ERROR, wxCommandEvent);
|
||||
|
||||
// int = DOWNLOAD ID; string = name
|
||||
wxDECLARE_EVENT(EVT_FILE_NAME_CHANGE, wxCommandEvent);
|
||||
}
|
||||
#endif
|
||||
|
@ -225,7 +225,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);
|
||||
}
|
||||
|
||||
@ -370,7 +370,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 {
|
||||
|
@ -22,8 +22,10 @@ public:
|
||||
size_t ultotal; // Total bytes to upload
|
||||
size_t ulnow; // Bytes uploaded so far
|
||||
|
||||
Progress(size_t dltotal, size_t dlnow, size_t ultotal, size_t ulnow) :
|
||||
dltotal(dltotal), dlnow(dlnow), ultotal(ultotal), ulnow(ulnow)
|
||||
const std::string& buffer; // reference to buffer containing all data
|
||||
|
||||
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)
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -70,9 +70,9 @@ namespace {
|
||||
#ifdef _WIN32
|
||||
static HWND l_prusa_slicer_hwnd;
|
||||
static HWND l_downloader_hwnd;
|
||||
BOOL CALLBACK EnumWindowsProcSlicer(_In_ HWND hwnd, _In_ LPARAM lParam)
|
||||
BOOL CALLBACK EnumWindowsProcSlicer(_In_ HWND hwnd, _In_ LPARAM lParam)
|
||||
{
|
||||
//checks for other instances of prusaslicer, if found brings it to front and return false to stop enumeration and quit this instance
|
||||
//checks for other instances of prusaslicer, if found brings it to front and return false to cancel enumeration and quit this instance
|
||||
//search is done by classname(wxWindowNR is wxwidgets thing, so probably not unique) and name in window upper panel
|
||||
//other option would be do a mutex and check for its existence
|
||||
//BOOST_LOG_TRIVIAL(error) << "ewp: version: " << l_version_wstring;
|
||||
@ -136,9 +136,9 @@ bool send_message_slicer(const wxString& message)
|
||||
}
|
||||
|
||||
|
||||
BOOL CALLBACK EnumWindowsProcDownloader(_In_ HWND hwnd, _In_ LPARAM lParam)
|
||||
BOOL CALLBACK EnumWindowsProcDownloader(_In_ HWND hwnd, _In_ LPARAM lParam)
|
||||
{
|
||||
//checks for other instances of prusaslicer, if found brings it to front and return false to stop enumeration and quit this instance
|
||||
//checks for other instances of prusaslicer, if found brings it to front and return false to cancel enumeration and quit this instance
|
||||
//search is done by classname(wxWindowNR is wxwidgets thing, so probably not unique) and name in window upper panel
|
||||
//other option would be do a mutex and check for its existence
|
||||
//BOOST_LOG_TRIVIAL(error) << "ewp: version: " << l_version_wstring;
|
||||
@ -153,7 +153,7 @@ BOOL CALLBACK EnumWindowsProcDownloader(_In_ HWND hwnd, _In_ LPARAM lParam)
|
||||
return true;
|
||||
std::wstring classNameString(className);
|
||||
std::wstring wndTextString(wndText);
|
||||
if (wndTextString.find(L"PrusaSlicer-Downloader") != std::wstring::npos && classNameString == L"wxWindowNR") {
|
||||
if (wndTextString.find(L"Downloader") != std::wstring::npos && classNameString == L"wxWindowNR") {
|
||||
//check if other instances has same instance hash
|
||||
//if not it is not same version(binary) as this version
|
||||
HANDLE handle = GetProp(hwnd, L"Instance_Hash_Minor");
|
||||
@ -210,6 +210,10 @@ bool execute_command(const wxString& command)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ------ SlicerSend ----------------
|
||||
|
||||
|
||||
bool SlicerSend::get_instance_exists() const
|
||||
{
|
||||
return !EnumWindows(EnumWindowsProcSlicer, 0);
|
||||
@ -219,6 +223,7 @@ bool SlicerSend::send_path(const wxString& path) const
|
||||
std::string escaped = escape_strings_cstyle({ "prusa-downloader", boost::nowide::narrow(path) });
|
||||
return send_message_slicer(boost::nowide::widen(escaped));
|
||||
}
|
||||
|
||||
bool SlicerSend::start_with_path(const wxString& path) const
|
||||
{
|
||||
// "C:\\Users\\User\\Downloads\\PrusaSlicer-2.4.2+win64-202204251110\\prusa-slicer.exe "
|
||||
@ -227,6 +232,17 @@ bool SlicerSend::start_with_path(const wxString& path) const
|
||||
return execute_command("C:\\Users\\User\\Downloads\\PrusaSlicer-2.4.2+win64-202204251110\\prusa-slicer.exe " + boost::nowide::widen(escaped));
|
||||
}
|
||||
|
||||
bool SlicerSend::start_or_send(const wxString& path) const
|
||||
{
|
||||
if (send_path(path))
|
||||
return true;
|
||||
return start_with_path(path);
|
||||
}
|
||||
|
||||
|
||||
// ------ DownloaderSend ----------------
|
||||
|
||||
|
||||
bool DownloaderSend::get_instance_exists() const
|
||||
{
|
||||
return !EnumWindows(EnumWindowsProcDownloader, 0);
|
||||
@ -236,4 +252,6 @@ bool DownloaderSend::send_url(const wxString& url) const
|
||||
//std::string escaped = escape_strings_cstyle({ boost::nowide::narrow(url) });
|
||||
return send_message_downloader(url);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ public:
|
||||
bool get_instance_exists() const;
|
||||
bool send_path(const wxString& path) const;
|
||||
bool start_with_path(const wxString& path) const;
|
||||
bool start_or_send(const wxString& path) const;
|
||||
};
|
||||
|
||||
class DownloaderSend
|
||||
|
Loading…
x
Reference in New Issue
Block a user