diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 047e03bf2..cfae9edd1 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -11,6 +11,7 @@ namespace Slic3r { extern void set_logging_level(unsigned int level); +extern unsigned get_logging_level(); extern void trace(unsigned int level, const char *message); // Format memory allocated, separate thousands by comma. extern std::string format_memsize_MB(size_t n); diff --git a/src/libslic3r/utils.cpp b/src/libslic3r/utils.cpp index 18e27f34b..f48abfd89 100644 --- a/src/libslic3r/utils.cpp +++ b/src/libslic3r/utils.cpp @@ -59,6 +59,18 @@ void set_logging_level(unsigned int level) ); } +unsigned get_logging_level() +{ + switch (logSeverity) { + case boost::log::trivial::fatal : return 0; + case boost::log::trivial::error : return 1; + case boost::log::trivial::warning : return 2; + case boost::log::trivial::info : return 3; + case boost::log::trivial::debug : return 4; + default: return 1; + } +} + // Force set_logging_level(<=error) after loading of the DLL. // Switch boost::filesystem to utf8. static struct RunOnInit { diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp index ae7b40484..d6b8b438e 100644 --- a/src/slic3r/GUI/MsgDialog.cpp +++ b/src/slic3r/GUI/MsgDialog.cpp @@ -6,6 +6,7 @@ #include <wx/button.h> #include <wx/statbmp.h> #include <wx/scrolwin.h> +#include <wx/clipbrd.h> #include "libslic3r/libslic3r.h" #include "libslic3r/Utils.hpp" @@ -61,8 +62,11 @@ MsgDialog::~MsgDialog() {} // ErrorDialog -ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg) : - MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")), wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png")), wxBITMAP_TYPE_PNG)) +ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg) + : MsgDialog(parent, _(L("Slic3r error")), _(L("Slic3r has encountered an error")), + wxBitmap(from_u8(Slic3r::var("Slic3r_192px_grayscale.png")), wxBITMAP_TYPE_PNG), + wxID_NONE) + , msg(msg) { auto *panel = new wxScrolledWindow(this); auto *p_sizer = new wxBoxSizer(wxVERTICAL); @@ -77,6 +81,20 @@ ErrorDialog::ErrorDialog(wxWindow *parent, const wxString &msg) : content_sizer->Add(panel, 1, wxEXPAND); + auto *btn_copy = new wxButton(this, wxID_ANY, _(L("Copy to clipboard"))); + btn_copy->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) { + if (wxTheClipboard->Open()) { + wxTheClipboard->SetData(new wxTextDataObject(this->msg)); // Note: the clipboard takes ownership of the pointer + wxTheClipboard->Close(); + } + }); + + auto *btn_ok = new wxButton(this, wxID_OK); + btn_ok->SetFocus(); + + btn_sizer->Add(btn_copy, 0, wxRIGHT, HORIZ_SPACING); + btn_sizer->Add(btn_ok); + SetMaxSize(wxSize(-1, CONTENT_MAX_HEIGHT)); Fit(); } diff --git a/src/slic3r/GUI/MsgDialog.hpp b/src/slic3r/GUI/MsgDialog.hpp index ca349eb5c..6064d2a9f 100644 --- a/src/slic3r/GUI/MsgDialog.hpp +++ b/src/slic3r/GUI/MsgDialog.hpp @@ -50,14 +50,18 @@ protected: // Generic error dialog, used for displaying exceptions -struct ErrorDialog : MsgDialog +class ErrorDialog : public MsgDialog { +public: ErrorDialog(wxWindow *parent, const wxString &msg); ErrorDialog(ErrorDialog &&) = delete; ErrorDialog(const ErrorDialog &) = delete; ErrorDialog &operator=(ErrorDialog &&) = delete; ErrorDialog &operator=(const ErrorDialog &) = delete; virtual ~ErrorDialog(); + +private: + wxString msg; }; diff --git a/src/slic3r/Utils/Http.cpp b/src/slic3r/Utils/Http.cpp index 67c24f3f4..6e6c9ed44 100644 --- a/src/slic3r/Utils/Http.cpp +++ b/src/slic3r/Utils/Http.cpp @@ -11,6 +11,7 @@ #include <curl/curl.h> #include "libslic3r/libslic3r.h" +#include "libslic3r/Utils.hpp" namespace fs = boost::filesystem; @@ -44,6 +45,7 @@ struct Http::priv // Using a deque here because unlike vector it doesn't ivalidate pointers on insertion std::deque<fs::ifstream> form_files; std::string postfields; + std::string error_buffer; // Used for CURLOPT_ERRORBUFFER size_t limit; bool cancel; @@ -69,13 +71,14 @@ struct Http::priv void http_perform(); }; -Http::priv::priv(const std::string &url) : - curl(::curl_easy_init()), - form(nullptr), - form_end(nullptr), - headerlist(nullptr), - limit(0), - cancel(false) +Http::priv::priv(const std::string &url) + : curl(::curl_easy_init()) + , form(nullptr) + , form_end(nullptr) + , headerlist(nullptr) + , error_buffer(CURL_ERROR_SIZE + 1, '\0') + , limit(0) + , cancel(false) { if (curl == nullptr) { throw std::runtime_error(std::string("Could not construct Curl object")); @@ -83,6 +86,7 @@ Http::priv::priv(const std::string &url) : ::curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // curl makes a copy internally ::curl_easy_setopt(curl, CURLOPT_USERAGENT, SLIC3R_FORK_NAME "/" SLIC3R_VERSION); + ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer.front()); } Http::priv::~priv() @@ -199,9 +203,10 @@ void Http::priv::set_post_body(const fs::path &path) std::string Http::priv::curl_error(CURLcode curlcode) { - return (boost::format("%1% (%2%)") + return (boost::format("%1% (%2%): %3%") % ::curl_easy_strerror(curlcode) % curlcode + % error_buffer ).str(); } @@ -227,9 +232,7 @@ void Http::priv::http_perform() ::curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, static_cast<void*>(this)); #endif -#ifndef NDEBUG - ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); -#endif + ::curl_easy_setopt(curl, CURLOPT_VERBOSE, get_logging_level() >= 4); if (headerlist != nullptr) { ::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); diff --git a/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp index 863da5d43..cdd0c107e 100644 --- a/src/slic3r/Utils/PrintHost.cpp +++ b/src/slic3r/Utils/PrintHost.cpp @@ -3,6 +3,7 @@ #include <vector> #include <thread> #include <boost/optional.hpp> +#include <boost/log/trivial.hpp> #include <boost/filesystem.hpp> #include <wx/app.h> @@ -144,6 +145,10 @@ void PrintHostJobQueue::priv::perform_job(PrintHostJob the_job) { if (bg_exit || the_job.empty()) { return; } + BOOST_LOG_TRIVIAL(debug) << boost::format("PrintHostJobQueue/bg_thread: Got job: `%1%` -> `%1%`") + % the_job.upload_data.upload_path + % the_job.printhost->get_host(); + const fs::path gcode_path = the_job.upload_data.source_path; the_job.printhost->upload(std::move(the_job.upload_data), @@ -154,7 +159,11 @@ void PrintHostJobQueue::priv::perform_job(PrintHostJob the_job) auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_PROGRESS, queue_dialog->GetId(), job_id, 100); wxQueueEvent(queue_dialog, evt); - fs::remove(gcode_path); // XXX: error handling + boost::system::error_code ec; + fs::remove(gcode_path, ec); + if (ec) { + BOOST_LOG_TRIVIAL(error) << boost::format("PrintHostJobQueue: Error removing file `%1%`: %2%") % gcode_path % ec; + } } void PrintHostJobQueue::enqueue(PrintHostJob job)