mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-03 19:50:40 +08:00
Download with basic UI
This commit is contained in:
parent
ad5b0d0bed
commit
816dd9490d
@ -2,10 +2,14 @@
|
||||
#project(PrusaSlicer_Downloader)
|
||||
|
||||
add_executable(PrusaSlicer_Downloader WIN32
|
||||
Downloader.cpp
|
||||
Downloader.hpp
|
||||
DownloaderApp.cpp
|
||||
DownloaderApp.hpp
|
||||
Download.cpp
|
||||
Download.hpp
|
||||
FileGet.cpp
|
||||
FileGet.hpp
|
||||
InstanceSend.cpp
|
||||
InstanceSend.hpp
|
||||
FromSlicer/Http.cpp
|
||||
FromSlicer/Http.hpp
|
||||
)
|
||||
|
32
src/downloader/Download.cpp
Normal file
32
src/downloader/Download.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "Download.hpp"
|
||||
|
||||
namespace Downloader{
|
||||
|
||||
namespace {
|
||||
std::string filename_from_url(const std::string& url)
|
||||
{
|
||||
// TODO: can it be done with curl?
|
||||
size_t slash = url.find_last_of("/");
|
||||
if (slash == std::string::npos && slash != url.size() - 1)
|
||||
return std::string();
|
||||
return url.substr(slash + 1, url.size() - slash + 1);
|
||||
}
|
||||
}
|
||||
|
||||
Download::Download(int ID, std::string url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder)
|
||||
: m_id(ID)
|
||||
, m_filename(filename_from_url(url))
|
||||
{
|
||||
assert(boost::filesystem::is_directory(dest_folder));
|
||||
m_final_path = dest_folder / m_filename;
|
||||
m_file_get = std::make_shared<FileGet>(ID, std::move(url), m_filename, evt_handler, dest_folder);
|
||||
}
|
||||
|
||||
void Download::start()
|
||||
{
|
||||
m_file_get->get();
|
||||
}
|
||||
void Download::stop()
|
||||
{
|
||||
}
|
||||
}
|
28
src/downloader/Download.hpp
Normal file
28
src/downloader/Download.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef slic3r_Download_hpp_
|
||||
#define slic3r_Download_hpp_
|
||||
|
||||
#include "FileGet.hpp"
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
class Download {
|
||||
public:
|
||||
Download(int ID, std::string url, wxEvtHandler* evt_handler,const boost::filesystem::path& dest_folder);
|
||||
void start();
|
||||
void stop();
|
||||
// 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; }
|
||||
private:
|
||||
const int m_id;
|
||||
std::string m_filename;
|
||||
boost::filesystem::path m_final_path;
|
||||
std::shared_ptr<FileGet> m_file_get;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -1,122 +0,0 @@
|
||||
#include "Downloader.hpp"
|
||||
#include "FileGet.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <wx/event.h>
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
enum
|
||||
{
|
||||
ID_Hello = 1,
|
||||
};
|
||||
|
||||
|
||||
wxBEGIN_EVENT_TABLE(DownloadFrame, wxFrame)
|
||||
EVT_MENU(ID_Hello, DownloadFrame::OnHello)
|
||||
EVT_MENU(wxID_EXIT, DownloadFrame::OnExit)
|
||||
EVT_MENU(wxID_ABOUT, DownloadFrame::OnAbout)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
|
||||
bool DownloadApp::OnInit()
|
||||
{
|
||||
DownloadFrame* frame = new DownloadFrame("Hello World", wxPoint(50, 50), wxSize(450, 340));
|
||||
frame->Show(true);
|
||||
return true;
|
||||
}
|
||||
DownloadFrame::DownloadFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
|
||||
: wxFrame(NULL, wxID_ANY, title, pos, size)
|
||||
{
|
||||
wxMenu* menuFile = new wxMenu;
|
||||
menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
|
||||
"Help string shown in status bar for this menu item");
|
||||
menuFile->AppendSeparator();
|
||||
menuFile->Append(wxID_EXIT);
|
||||
wxMenu* menuHelp = new wxMenu;
|
||||
menuHelp->Append(wxID_ABOUT);
|
||||
wxMenuBar* menuBar = new wxMenuBar;
|
||||
menuBar->Append(menuFile, "&File");
|
||||
menuBar->Append(menuHelp, "&Help");
|
||||
SetMenuBar(menuBar);
|
||||
CreateStatusBar();
|
||||
SetStatusText("Welcome to wxWidgets!");
|
||||
|
||||
m_log_label = new wxStaticText(this, wxID_ANY, "Log:");
|
||||
auto* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(m_log_label, wxEXPAND);
|
||||
SetSizer(sizer);
|
||||
|
||||
// Bind(EVT_FILE_COMPLETE, &on_complete, this);
|
||||
Bind(EVT_FILE_COMPLETE, &DownloadFrame::on_complete, this);
|
||||
Bind(EVT_FILE_PROGRESS, &DownloadFrame::on_progress, this);
|
||||
Bind(EVT_FILE_ERROR, &DownloadFrame::on_error, this);
|
||||
}
|
||||
void DownloadFrame::OnExit(wxCommandEvent& event)
|
||||
{
|
||||
Close(true);
|
||||
}
|
||||
void DownloadFrame::OnAbout(wxCommandEvent& event)
|
||||
{
|
||||
wxMessageBox("This is a wxWidgets' Hello world sample",
|
||||
"About Hello World", wxOK | wxICON_INFORMATION);
|
||||
}
|
||||
void DownloadFrame::OnHello(wxCommandEvent& event)
|
||||
{
|
||||
|
||||
std::string test_url = "https%3A%2F%2Fmedia.printables.com%2Fmedia%2Fprints%2F152208%2Fstls%2F1431590_8b8287b3-03b1-4cbe-82d0-268a0affa171%2Ff1_logo.stl";
|
||||
std::shared_ptr<FileGet> file_get = FileGet(get_next_id(), test_url, this, boost::filesystem::path("C:\\Users\\User\\Downloads")) .get();
|
||||
}
|
||||
|
||||
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);
|
||||
m_full_log += +"\n" + msg;
|
||||
}
|
||||
|
||||
void DownloadFrame::on_progress(wxCommandEvent& event)
|
||||
{
|
||||
log(std::to_string(event.GetInt()) + ": " + event.GetString());
|
||||
//SetStatusText("Progress: " + std::to_string(event.GetInt()));
|
||||
}
|
||||
void DownloadFrame::on_error(wxCommandEvent& event)
|
||||
{
|
||||
log(std::to_string(event.GetInt()) + ": " + event.GetString());
|
||||
//SetStatusText(event.GetString().c_str());
|
||||
}
|
||||
void DownloadFrame::on_complete(wxCommandEvent& event)
|
||||
{
|
||||
log(std::to_string(event.GetInt()) + ": Download complete " + event.GetString());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//wxIMPLEMENT_APP_NO_MAIN(MyApp);
|
||||
|
||||
|
||||
//int main()
|
||||
//{
|
||||
// wxEntry();
|
||||
// return 0;
|
||||
//}
|
||||
//int APIENTRY WinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */)
|
||||
//{
|
||||
// wxEntry();
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
wxIMPLEMENT_APP(Downloader::DownloadApp);
|
@ -1,37 +0,0 @@
|
||||
#ifndef slic3r_Downloader_hpp_
|
||||
#define slic3r_Downloader_hpp_
|
||||
#include <wx/wx.h>
|
||||
|
||||
namespace Downloader {
|
||||
class DownloadApp : public wxApp
|
||||
{
|
||||
public:
|
||||
virtual bool OnInit();
|
||||
};
|
||||
|
||||
class DownloadFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
DownloadFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
|
||||
private:
|
||||
void OnHello(wxCommandEvent& event);
|
||||
void OnExit(wxCommandEvent& event);
|
||||
void OnAbout(wxCommandEvent& event);
|
||||
|
||||
void on_progress(wxCommandEvent& event);
|
||||
void on_error(wxCommandEvent& event);
|
||||
void on_complete(wxCommandEvent& event);
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
|
||||
void log(const wxString& msg);
|
||||
|
||||
int m_next_id { 0 };
|
||||
int get_next_id() {return ++m_next_id; }
|
||||
|
||||
wxStaticText* m_log_label;
|
||||
size_t m_log_lines { 0 };
|
||||
wxString m_full_log;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
251
src/downloader/DownloaderApp.cpp
Normal file
251
src/downloader/DownloaderApp.cpp
Normal file
@ -0,0 +1,251 @@
|
||||
#include "DownloaderApp.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <wx/event.h>
|
||||
#include <wx/cmdline.h>
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
bool DownloadApp::OnInit()
|
||||
{
|
||||
m_dwnldr_send = std::make_unique<DownloaderSend>();
|
||||
|
||||
|
||||
if (m_dwnldr_send->get_instance_exists()) {
|
||||
m_other_exists = true;
|
||||
m_frame = new DownloadFrame("PrusaSlicer-Downloader", wxPoint(50, 50), wxSize(0,0));
|
||||
return wxApp::OnInit();
|
||||
}
|
||||
m_frame = new DownloadFrame("PrusaSlicer-Downloader", wxPoint(50, 50), wxSize(450, 340));
|
||||
m_frame->Show(true);
|
||||
|
||||
wxWindow::MSWRegisterMessageHandler(WM_COPYDATA, [](wxWindow* win, WXUINT /* nMsg */, WXWPARAM wParam, WXLPARAM lParam) {
|
||||
auto frame = dynamic_cast<DownloadFrame*>(win);
|
||||
COPYDATASTRUCT* copy_data_structure = { 0 };
|
||||
copy_data_structure = (COPYDATASTRUCT*)lParam;
|
||||
if (copy_data_structure->dwData == 1) {
|
||||
LPCWSTR arguments = (LPCWSTR)copy_data_structure->lpData;
|
||||
frame->handle_message(arguments);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return wxApp::OnInit();
|
||||
}
|
||||
|
||||
void DownloadApp::OnInitCmdLine(wxCmdLineParser& parser)
|
||||
{
|
||||
static const wxCmdLineEntryDesc cmdLineDesc[] =
|
||||
{
|
||||
{ wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
|
||||
{ wxCMD_LINE_SWITCH, "q", "quiet", "be quiet" },
|
||||
|
||||
// { wxCMD_LINE_OPTION, "s", "slicer", "path to prusaslicer", wxCMD_LINE_VAL_STRING },
|
||||
{ wxCMD_LINE_OPTION, "u", "url", "url to download", wxCMD_LINE_VAL_STRING },
|
||||
|
||||
{ wxCMD_LINE_NONE }
|
||||
};
|
||||
|
||||
parser.SetDesc(cmdLineDesc);
|
||||
|
||||
}
|
||||
|
||||
bool DownloadApp::OnCmdLineParsed(wxCmdLineParser& parser)
|
||||
{
|
||||
wxString option;
|
||||
wxString url;
|
||||
if (parser.Found("u", &option)) {
|
||||
url = option;
|
||||
}
|
||||
|
||||
if (m_other_exists) {
|
||||
m_dwnldr_send->send_url(url);
|
||||
m_frame->log("sent " + url);
|
||||
m_frame->Close(true);
|
||||
return false;
|
||||
} else {
|
||||
if (!url.empty() && m_frame != nullptr)
|
||||
m_frame->start_download(std::move(url));
|
||||
|
||||
return wxApp::OnCmdLineParsed(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>())
|
||||
{
|
||||
|
||||
dataview = new wxDataViewListCtrl(this, wxID_ANY);
|
||||
|
||||
/* 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));*/
|
||||
|
||||
|
||||
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_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);
|
||||
|
||||
Bind(EVT_FILE_COMPLETE, &DownloadFrame::on_complete, this);
|
||||
Bind(EVT_FILE_PROGRESS, &DownloadFrame::on_progress, this);
|
||||
Bind(EVT_FILE_ERROR, &DownloadFrame::on_error, this);
|
||||
}
|
||||
|
||||
void DownloadFrame::start_download(wxString url)
|
||||
{
|
||||
// prusaslicer://open?file=https%3A%2F%2Fmedia.printables.com%2Fmedia%2Fprints%2F152208%2Fstls%2F1431590_8b8287b3-03b1-4cbe-82d0-268a0affa171%2Ff1_logo.stl
|
||||
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);
|
||||
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);
|
||||
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
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);
|
||||
}
|
||||
void DownloadFrame::on_complete(wxCommandEvent& event)
|
||||
{
|
||||
dataview->SetValue("Done", event.GetInt() - 1, 3);
|
||||
m_instance_send->start_with_path(event.GetString());
|
||||
|
||||
|
||||
}
|
||||
void DownloadFrame::handle_message(const wxString& msg)
|
||||
{
|
||||
log("recieved: " + msg);
|
||||
start_download(msg);
|
||||
}
|
||||
|
||||
|
||||
//wxIMPLEMENT_APP_NO_MAIN(MyApp);
|
||||
|
||||
|
||||
//int main()
|
||||
//{
|
||||
// wxEntry();
|
||||
// return 0;
|
||||
//}
|
||||
//int APIENTRY WinMain(HINSTANCE /* hInstance */, HINSTANCE /* hPrevInstance */, PWSTR /* lpCmdLine */, int /* nCmdShow */)
|
||||
//{
|
||||
// wxEntry();
|
||||
// return 0;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
//// ----------------------------------------------------------------------------
|
||||
//// TextRenderer
|
||||
//// ----------------------------------------------------------------------------
|
||||
//
|
||||
//bool TextRenderer::SetValue(const wxVariant& value)
|
||||
//{
|
||||
// m_value = value.GetString();
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//bool TextRenderer::GetValue(wxVariant& value) const
|
||||
//{
|
||||
// value = m_value;
|
||||
// return false;
|
||||
//}
|
||||
//
|
||||
//bool TextRenderer::Render(wxRect rect, wxDC* dc, int state)
|
||||
//{
|
||||
//
|
||||
// RenderText(m_value, 0, rect, dc, state);
|
||||
//
|
||||
////
|
||||
////#ifdef _WIN32
|
||||
//// // workaround for Windows DarkMode : Don't respect to the state & wxDATAVIEW_CELL_SELECTED to avoid update of the text color
|
||||
//// RenderText(m_value, 0, rect, dc, state & wxDATAVIEW_CELL_SELECTED ? 0 : state);
|
||||
////#else
|
||||
//// RenderText(m_value, 0, rect, dc, state);
|
||||
////#endif
|
||||
//
|
||||
// return true;
|
||||
//}
|
||||
//
|
||||
//wxSize TextRenderer::GetSize() const
|
||||
//{
|
||||
// return GetTextExtent(m_value);
|
||||
//}
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
wxIMPLEMENT_APP(Downloader::DownloadApp);
|
96
src/downloader/DownloaderApp.hpp
Normal file
96
src/downloader/DownloaderApp.hpp
Normal file
@ -0,0 +1,96 @@
|
||||
#ifndef slic3r_DownloaderApp_hpp_
|
||||
#define slic3r_DownloadeAppr_hpp_
|
||||
|
||||
#include "InstanceSend.hpp"
|
||||
#include "Download.hpp"
|
||||
#include <vector>
|
||||
#include <wx/wx.h>
|
||||
#include <wx/dataview.h>
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
class DownloadFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
DownloadFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
|
||||
|
||||
void set_path_to_slicer(wxString path) { m_path_to_slicer = path; }
|
||||
void start_download(wxString url);
|
||||
|
||||
void log(const wxString& msg);
|
||||
void handle_message(const wxString& msg);
|
||||
private:
|
||||
|
||||
void on_progress(wxCommandEvent& event);
|
||||
void on_error(wxCommandEvent& event);
|
||||
void on_complete(wxCommandEvent& event);
|
||||
|
||||
|
||||
int m_next_id { 0 };
|
||||
int get_next_id() {return ++m_next_id; }
|
||||
|
||||
wxStaticText* m_log_label;
|
||||
size_t m_log_lines { 0 };
|
||||
wxString m_full_log;
|
||||
|
||||
wxDataViewListCtrl* dataview;
|
||||
|
||||
wxString m_url;
|
||||
wxString m_path_to_slicer;
|
||||
|
||||
std::unique_ptr<SlicerSend> m_instance_send;
|
||||
|
||||
boost::filesystem::path m_dest_folder;
|
||||
|
||||
std::vector<std::unique_ptr<Download>> m_downloads;
|
||||
};
|
||||
|
||||
class DownloadApp : public wxApp
|
||||
{
|
||||
protected:
|
||||
DownloadFrame* m_frame{ nullptr };
|
||||
std::unique_ptr<DownloaderSend> m_dwnldr_send;
|
||||
|
||||
bool m_other_exists { false };
|
||||
|
||||
public:
|
||||
bool OnInit() override;
|
||||
void OnInitCmdLine(wxCmdLineParser& parser) override;
|
||||
bool OnCmdLineParsed(wxCmdLineParser& parser) override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
wxDECLARE_APP(DownloadApp);
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
//class TextRenderer : public wxDataViewCustomRenderer
|
||||
//{
|
||||
//public:
|
||||
// TextRenderer(wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT
|
||||
// , int align = wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL
|
||||
// ) : wxDataViewCustomRenderer(wxT("string"), mode, align) {}
|
||||
//
|
||||
// bool SetValue(const wxVariant& value) override;
|
||||
// bool GetValue(wxVariant& value) const override;
|
||||
//
|
||||
// virtual bool Render(wxRect cell, wxDC* dc, int state) override;
|
||||
// virtual wxSize GetSize() const override;
|
||||
//
|
||||
// bool HasEditorCtrl() const override { return false; }
|
||||
//
|
||||
//private:
|
||||
// wxString m_value;
|
||||
//};
|
||||
//
|
||||
//
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -8,8 +8,8 @@
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
namespace {
|
||||
std::string escape_url(const std::string& unescaped)
|
||||
|
||||
std::string FileGet::escape_url(const std::string& unescaped)
|
||||
{
|
||||
std::string ret_val;
|
||||
CURL* curl = curl_easy_init();
|
||||
@ -24,14 +24,7 @@ std::string escape_url(const std::string& unescaped)
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
std::string filename_from_url(const std::string& url)
|
||||
{
|
||||
// TODO: can it be done with curl?
|
||||
size_t slash = url.find_last_of("/");
|
||||
if (slash == std::string::npos && slash != url.size()-1)
|
||||
return std::string();
|
||||
return url.substr(slash + 1, url.size() - slash + 1);
|
||||
}
|
||||
namespace {
|
||||
unsigned get_current_pid()
|
||||
{
|
||||
#ifdef WIN32
|
||||
@ -57,15 +50,16 @@ struct FileGet::priv
|
||||
std::thread m_io_thread;
|
||||
wxEvtHandler* m_evt_handler;
|
||||
boost::filesystem::path m_dest_folder;
|
||||
|
||||
priv(int ID, std::string&& url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder);
|
||||
std::atomic_bool m_cancel = false;
|
||||
priv(int ID, std::string&& url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder);
|
||||
|
||||
void get_perform();
|
||||
};
|
||||
|
||||
FileGet::priv::priv(int ID, std::string&& url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder)
|
||||
FileGet::priv::priv(int ID, std::string&& url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder)
|
||||
: m_id(ID)
|
||||
, m_url(std::move(url))
|
||||
, m_filename(filename)
|
||||
, m_evt_handler(evt_handler)
|
||||
, m_dest_folder(dest_folder)
|
||||
{
|
||||
@ -75,20 +69,23 @@ void FileGet::priv::get_perform()
|
||||
{
|
||||
assert(m_evt_handler);
|
||||
assert(!m_url.empty());
|
||||
m_url = escape_url(m_url);
|
||||
assert(!m_url.empty());
|
||||
m_filename = filename_from_url(m_url);
|
||||
assert(!m_filename.empty());
|
||||
assert(boost::filesystem::is_directory(m_dest_folder));
|
||||
|
||||
Downloader::Http::get(m_url)
|
||||
//.size_limit(size_limit)
|
||||
.on_progress([&](Downloader::Http::Progress progress, bool& cancel) {
|
||||
if (m_cancel) {
|
||||
cancel = true;
|
||||
return;
|
||||
// TODO: send canceled event?
|
||||
}
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_FILE_PROGRESS);
|
||||
if (progress.dlnow == 0)
|
||||
evt->SetString("0");
|
||||
else
|
||||
evt->SetString(std::to_string((float)progress.dltotal / (float)progress.dlnow));
|
||||
evt->SetString(std::to_string(progress.dlnow * 100 / progress.dltotal));
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
})
|
||||
@ -99,7 +96,7 @@ void FileGet::priv::get_perform()
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
})
|
||||
.on_complete([&](std::string body, unsigned /* http_status */) {
|
||||
|
||||
|
||||
size_t body_size = body.size();
|
||||
// TODO:
|
||||
//if (body_size != expected_size) {
|
||||
@ -148,12 +145,11 @@ void FileGet::priv::get_perform()
|
||||
|
||||
}
|
||||
|
||||
FileGet::FileGet(int ID, std::string url, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder)
|
||||
: p(new priv(ID, std::move(url), evt_handler, dest_folder))
|
||||
, m_ID(ID)
|
||||
FileGet::FileGet(int ID, std::string url, const std::string& filename, wxEvtHandler* evt_handler, const boost::filesystem::path& dest_folder)
|
||||
: p(new priv(ID, std::move(url), filename, evt_handler, dest_folder))
|
||||
{}
|
||||
|
||||
FileGet::FileGet(FileGet&& other) : p(std::move(other.p)), m_ID(other.get_ID()) {}
|
||||
FileGet::FileGet(FileGet&& other) : p(std::move(other.p)) {}
|
||||
|
||||
FileGet::~FileGet()
|
||||
{
|
||||
@ -162,18 +158,21 @@ FileGet::~FileGet()
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<FileGet> FileGet::get()
|
||||
void FileGet::get()
|
||||
{
|
||||
auto self = std::make_shared<FileGet>(std::move(*this));
|
||||
|
||||
if (self->p) {
|
||||
auto io_thread = std::thread([self]() {
|
||||
self->p->get_perform();
|
||||
if (p) {
|
||||
auto io_thread = std::thread([&priv = p]() {
|
||||
priv->get_perform();
|
||||
});
|
||||
self->p->m_io_thread = std::move(io_thread);
|
||||
p->m_io_thread = std::move(io_thread);
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
void FileGet::cancel()
|
||||
{
|
||||
if(p){
|
||||
p->m_cancel = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,18 +14,21 @@ class FileGet : public std::enable_shared_from_this<FileGet> {
|
||||
private:
|
||||
struct priv;
|
||||
public:
|
||||
FileGet(int ID, std::string url, wxEvtHandler* evt_handler,const boost::filesystem::path& dest_folder);
|
||||
FileGet(int ID, std::string url, const std::string& filename, wxEvtHandler* evt_handler,const boost::filesystem::path& dest_folder);
|
||||
FileGet(FileGet&& other);
|
||||
~FileGet();
|
||||
|
||||
std::shared_ptr<FileGet> get();
|
||||
const int get_ID() const { return m_ID; }
|
||||
void get();
|
||||
void cancel();
|
||||
static std::string escape_url(const std::string& url);
|
||||
private:
|
||||
std::unique_ptr<priv> p;
|
||||
const int m_ID;
|
||||
};
|
||||
// int = DOWNLOAD ID; string = file path
|
||||
wxDECLARE_EVENT(EVT_FILE_COMPLETE, wxCommandEvent);
|
||||
// int = DOWNLOAD ID; string = error msg
|
||||
wxDECLARE_EVENT(EVT_FILE_PROGRESS, wxCommandEvent);
|
||||
// int = DOWNLOAD ID; string = progress percent
|
||||
wxDECLARE_EVENT(EVT_FILE_ERROR, wxCommandEvent);
|
||||
|
||||
}
|
||||
|
239
src/downloader/InstanceSend.cpp
Normal file
239
src/downloader/InstanceSend.cpp
Normal file
@ -0,0 +1,239 @@
|
||||
#include "InstanceSend.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
#endif //WIN32
|
||||
|
||||
#include <boost/nowide/convert.hpp>
|
||||
#include <wx/utils.h>
|
||||
|
||||
namespace Downloader {
|
||||
|
||||
namespace {
|
||||
// TODO: Taken from from Config.cpp
|
||||
std::string escape_strings_cstyle(const std::vector<std::string>& strs)
|
||||
{
|
||||
// 1) Estimate the output buffer size to avoid buffer reallocation.
|
||||
size_t outbuflen = 0;
|
||||
for (size_t i = 0; i < strs.size(); ++i)
|
||||
// Reserve space for every character escaped + quotes + semicolon.
|
||||
outbuflen += strs[i].size() * 2 + 3;
|
||||
// 2) Fill in the buffer.
|
||||
std::vector<char> out(outbuflen, 0);
|
||||
char* outptr = out.data();
|
||||
for (size_t j = 0; j < strs.size(); ++j) {
|
||||
if (j > 0)
|
||||
// Separate the strings.
|
||||
(*outptr++) = ';';
|
||||
const std::string& str = strs[j];
|
||||
// Is the string simple or complex? Complex string contains spaces, tabs, new lines and other
|
||||
// escapable characters. Empty string shall be quoted as well, if it is the only string in strs.
|
||||
bool should_quote = strs.size() == 1 && str.empty();
|
||||
for (size_t i = 0; i < str.size(); ++i) {
|
||||
char c = str[i];
|
||||
if (c == ' ' || c == ';' || c == '\t' || c == '\\' || c == '"' || c == '\r' || c == '\n') {
|
||||
should_quote = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (should_quote) {
|
||||
(*outptr++) = '"';
|
||||
for (size_t i = 0; i < str.size(); ++i) {
|
||||
char c = str[i];
|
||||
if (c == '\\' || c == '"') {
|
||||
(*outptr++) = '\\';
|
||||
(*outptr++) = c;
|
||||
}
|
||||
else if (c == '\r') {
|
||||
(*outptr++) = '\\';
|
||||
(*outptr++) = 'r';
|
||||
}
|
||||
else if (c == '\n') {
|
||||
(*outptr++) = '\\';
|
||||
(*outptr++) = 'n';
|
||||
}
|
||||
else
|
||||
(*outptr++) = c;
|
||||
}
|
||||
(*outptr++) = '"';
|
||||
}
|
||||
else {
|
||||
memcpy(outptr, str.data(), str.size());
|
||||
outptr += str.size();
|
||||
}
|
||||
}
|
||||
return std::string(out.data(), outptr - out.data());
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
static HWND l_prusa_slicer_hwnd;
|
||||
static HWND l_downloader_hwnd;
|
||||
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
|
||||
//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;
|
||||
TCHAR wndText[1000];
|
||||
TCHAR className[1000];
|
||||
int err;
|
||||
err = GetClassName(hwnd, className, 1000);
|
||||
if (err == 0)
|
||||
return true;
|
||||
err = GetWindowText(hwnd, wndText, 1000);
|
||||
if (err == 0)
|
||||
return true;
|
||||
std::wstring classNameString(className);
|
||||
std::wstring wndTextString(wndText);
|
||||
if (wndTextString.find(L"PrusaSlicer") != 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");
|
||||
uint64_t other_instance_hash = PtrToUint(handle);
|
||||
uint64_t other_instance_hash_major;
|
||||
//TODO
|
||||
//uint64_t my_instance_hash = GUI::wxGetApp().get_instance_hash_int();
|
||||
handle = GetProp(hwnd, L"Instance_Hash_Major");
|
||||
other_instance_hash_major = PtrToUint(handle);
|
||||
other_instance_hash_major = other_instance_hash_major << 32;
|
||||
other_instance_hash += other_instance_hash_major;
|
||||
//if (my_instance_hash == other_instance_hash)
|
||||
{
|
||||
//BOOST_LOG_TRIVIAL(debug) << "win enum - found correct instance";
|
||||
l_prusa_slicer_hwnd = hwnd;
|
||||
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
|
||||
SetForegroundWindow(hwnd);
|
||||
return false;
|
||||
}
|
||||
//BOOST_LOG_TRIVIAL(debug) << "win enum - found wrong instance";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_message_slicer(const wxString& message)
|
||||
{
|
||||
if (!EnumWindows(EnumWindowsProcSlicer, 0)) {
|
||||
std::wstring wstr(message.c_str());//boost::nowide::widen(message);
|
||||
std::unique_ptr<LPWSTR> command_line_args = std::make_unique<LPWSTR>(const_cast<LPWSTR>(wstr.c_str()));
|
||||
/*LPWSTR command_line_args = new wchar_t[wstr.size() + 1];
|
||||
copy(wstr.begin(), wstr.end(), command_line_args);
|
||||
command_line_args[wstr.size()] = 0;*/
|
||||
|
||||
//Create a COPYDATASTRUCT to send the information
|
||||
//cbData represents the size of the information we want to send.
|
||||
//lpData represents the information we want to send.
|
||||
//dwData is an ID defined by us(this is a type of ID different than WM_COPYDATA).
|
||||
COPYDATASTRUCT data_to_send = { 0 };
|
||||
data_to_send.dwData = 1;
|
||||
data_to_send.cbData = sizeof(TCHAR) * (wcslen(*command_line_args.get()) + 1);
|
||||
data_to_send.lpData = *command_line_args.get();
|
||||
SendMessage(l_prusa_slicer_hwnd, WM_COPYDATA, 0, (LPARAM)&data_to_send);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
//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;
|
||||
TCHAR wndText[1000];
|
||||
TCHAR className[1000];
|
||||
int err;
|
||||
err = GetClassName(hwnd, className, 1000);
|
||||
if (err == 0)
|
||||
return true;
|
||||
err = GetWindowText(hwnd, wndText, 1000);
|
||||
if (err == 0)
|
||||
return true;
|
||||
std::wstring classNameString(className);
|
||||
std::wstring wndTextString(wndText);
|
||||
if (wndTextString.find(L"PrusaSlicer-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");
|
||||
uint64_t other_instance_hash = PtrToUint(handle);
|
||||
uint64_t other_instance_hash_major;
|
||||
//TODO
|
||||
//uint64_t my_instance_hash = GUI::wxGetApp().get_instance_hash_int();
|
||||
handle = GetProp(hwnd, L"Instance_Hash_Major");
|
||||
other_instance_hash_major = PtrToUint(handle);
|
||||
other_instance_hash_major = other_instance_hash_major << 32;
|
||||
other_instance_hash += other_instance_hash_major;
|
||||
//if (my_instance_hash == other_instance_hash)
|
||||
{
|
||||
//BOOST_LOG_TRIVIAL(debug) << "win enum - found correct instance";
|
||||
l_downloader_hwnd = hwnd;
|
||||
ShowWindow(hwnd, SW_NORMAL);
|
||||
SetForegroundWindow(hwnd);
|
||||
return false;
|
||||
}
|
||||
//BOOST_LOG_TRIVIAL(debug) << "win enum - found wrong instance";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool send_message_downloader(const wxString& message)
|
||||
{
|
||||
if (!EnumWindows(EnumWindowsProcDownloader, 0)) {
|
||||
std::wstring wstr(message.c_str());//boost::nowide::widen(message);
|
||||
std::unique_ptr<LPWSTR> command_line_args = std::make_unique<LPWSTR>(const_cast<LPWSTR>(wstr.c_str()));
|
||||
/*LPWSTR command_line_args = new wchar_t[wstr.size() + 1];
|
||||
copy(wstr.begin(), wstr.end(), command_line_args);
|
||||
command_line_args[wstr.size()] = 0;*/
|
||||
|
||||
//Create a COPYDATASTRUCT to send the information
|
||||
//cbData represents the size of the information we want to send.
|
||||
//lpData represents the information we want to send.
|
||||
//dwData is an ID defined by us(this is a type of ID different than WM_COPYDATA).
|
||||
COPYDATASTRUCT data_to_send = { 0 };
|
||||
data_to_send.dwData = 1;
|
||||
data_to_send.cbData = sizeof(TCHAR) * (wcslen(*command_line_args.get()) + 1);
|
||||
data_to_send.lpData = *command_line_args.get();
|
||||
SendMessage(l_downloader_hwnd, WM_COPYDATA, 0, (LPARAM)&data_to_send);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool execute_command(const wxString& command)
|
||||
{
|
||||
return wxExecute(command);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SlicerSend::get_instance_exists() const
|
||||
{
|
||||
return !EnumWindows(EnumWindowsProcSlicer, 0);
|
||||
}
|
||||
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 "
|
||||
std::string escaped = escape_strings_cstyle({ boost::nowide::narrow(path) });
|
||||
//return execute_command(boost::nowide::widen(escaped));
|
||||
return execute_command("C:\\Users\\User\\Downloads\\PrusaSlicer-2.4.2+win64-202204251110\\prusa-slicer.exe " + boost::nowide::widen(escaped));
|
||||
}
|
||||
|
||||
bool DownloaderSend::get_instance_exists() const
|
||||
{
|
||||
return !EnumWindows(EnumWindowsProcDownloader, 0);
|
||||
}
|
||||
bool DownloaderSend::send_url(const wxString& url) const
|
||||
{
|
||||
//std::string escaped = escape_strings_cstyle({ boost::nowide::narrow(url) });
|
||||
return send_message_downloader(url);
|
||||
}
|
||||
}
|
23
src/downloader/InstanceSend.hpp
Normal file
23
src/downloader/InstanceSend.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef slic3r_InstanceSend_hpp_
|
||||
#define slic3r_InstanceSend_hpp_
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <wx/string.h>
|
||||
|
||||
namespace Downloader {
|
||||
class SlicerSend
|
||||
{
|
||||
public:
|
||||
bool get_instance_exists() const;
|
||||
bool send_path(const wxString& path) const;
|
||||
bool start_with_path(const wxString& path) const;
|
||||
};
|
||||
|
||||
class DownloaderSend
|
||||
{
|
||||
public:
|
||||
bool get_instance_exists() const;
|
||||
bool send_url(const wxString& url) const;
|
||||
};
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user