This commit is contained in:
bubnikv 2018-12-20 10:56:04 +01:00
commit 6282e904b9
24 changed files with 166 additions and 93 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Before After
Before After

View file

@ -1549,7 +1549,7 @@ void GLCanvas3D::Selection::start_dragging()
_set_caches(); _set_caches();
} }
void GLCanvas3D::Selection::translate(const Vec3d& displacement) void GLCanvas3D::Selection::translate(const Vec3d& displacement, bool local)
{ {
if (!m_valid) if (!m_valid)
return; return;
@ -1559,7 +1559,7 @@ void GLCanvas3D::Selection::translate(const Vec3d& displacement)
#if ENABLE_MODELVOLUME_TRANSFORM #if ENABLE_MODELVOLUME_TRANSFORM
if ((m_mode == Volume) || (*m_volumes)[i]->is_wipe_tower) if ((m_mode == Volume) || (*m_volumes)[i]->is_wipe_tower)
{ {
if (_requires_local_axes()) if (local)
(*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement); (*m_volumes)[i]->set_volume_offset(m_cache.volumes_data[i].get_volume_position() + displacement);
else else
{ {
@ -1614,7 +1614,7 @@ void GLCanvas3D::Selection::rotate(const Vec3d& rotation, bool local)
else if (is_single_volume() || is_single_modifier()) else if (is_single_volume() || is_single_modifier())
#if ENABLE_WORLD_ROTATIONS #if ENABLE_WORLD_ROTATIONS
{ {
if (_requires_local_axes()) if (requires_local_axes())
(*m_volumes)[i]->set_volume_rotation(rotation); (*m_volumes)[i]->set_volume_rotation(rotation);
else else
{ {
@ -2118,6 +2118,11 @@ void GLCanvas3D::Selection::render_sidebar_hints(const std::string& sidebar_fiel
} }
#endif // ENABLE_SIDEBAR_VISUAL_HINTS #endif // ENABLE_SIDEBAR_VISUAL_HINTS
bool GLCanvas3D::Selection::requires_local_axes() const
{
return (m_mode == Volume) && is_from_single_instance();
}
void GLCanvas3D::Selection::_update_valid() void GLCanvas3D::Selection::_update_valid()
{ {
m_valid = (m_volumes != nullptr) && (m_model != nullptr); m_valid = (m_volumes != nullptr) && (m_model != nullptr);
@ -2746,11 +2751,6 @@ void GLCanvas3D::Selection::_ensure_on_bed()
} }
#endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING #endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING
bool GLCanvas3D::Selection::_requires_local_axes() const
{
return (m_mode == Volume) && is_from_single_instance();
}
const float GLCanvas3D::Gizmos::OverlayIconsScale = 1.0f; const float GLCanvas3D::Gizmos::OverlayIconsScale = 1.0f;
const float GLCanvas3D::Gizmos::OverlayBorder = 5.0f; const float GLCanvas3D::Gizmos::OverlayBorder = 5.0f;
const float GLCanvas3D::Gizmos::OverlayGapY = 5.0f * OverlayIconsScale; const float GLCanvas3D::Gizmos::OverlayGapY = 5.0f * OverlayIconsScale;

View file

@ -578,7 +578,7 @@ public:
void start_dragging(); void start_dragging();
void translate(const Vec3d& displacement); void translate(const Vec3d& displacement, bool local = false);
void rotate(const Vec3d& rotation, bool local); void rotate(const Vec3d& rotation, bool local);
void flattening_rotate(const Vec3d& normal); void flattening_rotate(const Vec3d& normal);
void scale(const Vec3d& scale, bool local); void scale(const Vec3d& scale, bool local);
@ -597,6 +597,8 @@ public:
void render_sidebar_hints(const std::string& sidebar_field) const; void render_sidebar_hints(const std::string& sidebar_field) const;
#endif // ENABLE_SIDEBAR_VISUAL_HINTS #endif // ENABLE_SIDEBAR_VISUAL_HINTS
bool requires_local_axes() const;
private: private:
void _update_valid(); void _update_valid();
void _update_type(); void _update_type();
@ -626,7 +628,6 @@ public:
#if ENABLE_ENSURE_ON_BED_WHILE_SCALING #if ENABLE_ENSURE_ON_BED_WHILE_SCALING
void _ensure_on_bed(); void _ensure_on_bed();
#endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING #endif // ENABLE_ENSURE_ON_BED_WHILE_SCALING
bool _requires_local_axes() const;
}; };
class ClippingPlane class ClippingPlane

View file

@ -137,7 +137,7 @@ bool GUI_App::OnInit()
std::cerr << "Creating main frame..." << std::endl; std::cerr << "Creating main frame..." << std::endl;
if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr) if (wxImage::FindHandler(wxBITMAP_TYPE_PNG) == nullptr)
wxImage::AddHandler(new wxPNGHandler()); wxImage::AddHandler(new wxPNGHandler());
mainframe = new MainFrame(no_plater, false); mainframe = new MainFrame();
sidebar().obj_list()->init_objects(); // propagate model objects to object list sidebar().obj_list()->init_objects(); // propagate model objects to object list
update_mode(); update_mode();
SetTopWindow(mainframe); SetTopWindow(mainframe);
@ -277,8 +277,8 @@ void GUI_App::recreate_GUI()
{ {
std::cerr << "recreate_GUI" << std::endl; std::cerr << "recreate_GUI" << std::endl;
auto topwindow = GetTopWindow(); MainFrame* topwindow = dynamic_cast<MainFrame*>(GetTopWindow());
mainframe = new MainFrame(no_plater,false); mainframe = new MainFrame();
sidebar().obj_list()->init_objects(); // propagate model objects to object list sidebar().obj_list()->init_objects(); // propagate model objects to object list
update_mode(); update_mode();
@ -287,6 +287,20 @@ void GUI_App::recreate_GUI()
topwindow->Destroy(); topwindow->Destroy();
} }
m_printhost_job_queue.reset(new PrintHostJobQueue(mainframe->printhost_queue_dlg()));
CallAfter([this]() {
// temporary workaround for the correct behavior of the Scrolled sidebar panel
auto& panel = sidebar();
if (panel.obj_list()->GetMinHeight() > 200) {
wxWindowUpdateLocker noUpdates_sidebar(&panel);
panel.obj_list()->SetMinSize(wxSize(-1, 200));
panel.Layout();
}
});
mainframe->Show(true);
// On OSX the UI was not initialized correctly if the wizard was called // On OSX the UI was not initialized correctly if the wizard was called
// before the UI was up and running. // before the UI was up and running.
CallAfter([]() { CallAfter([]() {
@ -434,7 +448,7 @@ bool GUI_App::select_language( wxArrayString & names,
m_wxLocale = new wxLocale; m_wxLocale = new wxLocale;
m_wxLocale->Init(identifiers[index]); m_wxLocale->Init(identifiers[index]);
m_wxLocale->AddCatalogLookupPathPrefix(localization_dir()); m_wxLocale->AddCatalogLookupPathPrefix(localization_dir());
m_wxLocale->AddCatalog(GetAppName()); m_wxLocale->AddCatalog(/*GetAppName()*/"Slic3rPE");
wxSetlocale(LC_NUMERIC, "C"); wxSetlocale(LC_NUMERIC, "C");
Preset::update_suffix_modified(); Preset::update_suffix_modified();
return true; return true;
@ -461,7 +475,7 @@ bool GUI_App::load_language()
m_wxLocale = new wxLocale; m_wxLocale = new wxLocale;
m_wxLocale->Init(identifiers[i]); m_wxLocale->Init(identifiers[i]);
m_wxLocale->AddCatalogLookupPathPrefix(localization_dir()); m_wxLocale->AddCatalogLookupPathPrefix(localization_dir());
m_wxLocale->AddCatalog(GetAppName()); m_wxLocale->AddCatalog(/*GetAppName()*/"Slic3rPE");
wxSetlocale(LC_NUMERIC, "C"); wxSetlocale(LC_NUMERIC, "C");
Preset::update_suffix_modified(); Preset::update_suffix_modified();
return true; return true;
@ -504,7 +518,8 @@ void GUI_App::get_installed_languages(wxArrayString & names, wxArrayLong & ident
{ {
auto full_file_name = dir.GetName() + wxFileName::GetPathSeparator() + auto full_file_name = dir.GetName() + wxFileName::GetPathSeparator() +
filename + wxFileName::GetPathSeparator() + filename + wxFileName::GetPathSeparator() +
GetAppName() + wxT(".mo"); /*GetAppName()*/"Slic3rPE" +
wxT(".mo");
if (wxFileExists(full_file_name)) if (wxFileExists(full_file_name))
{ {
names.Add(langinfo->Description); names.Add(langinfo->Description);

View file

@ -71,7 +71,6 @@ static wxString dots("…", wxConvUTF8);
class GUI_App : public wxApp class GUI_App : public wxApp
{ {
bool no_plater{ false };
bool app_conf_exists{ false }; bool app_conf_exists{ false };
// Lock to guard the callback stack // Lock to guard the callback stack

View file

@ -361,8 +361,9 @@ void ObjectManipulation::update_rotation_value(const Vec3d& rotation)
void ObjectManipulation::change_position_value(const Vec3d& position) void ObjectManipulation::change_position_value(const Vec3d& position)
{ {
auto canvas = wxGetApp().plater()->canvas3D(); auto canvas = wxGetApp().plater()->canvas3D();
canvas->get_selection().start_dragging(); GLCanvas3D::Selection& selection = canvas->get_selection();
canvas->get_selection().translate(position - cache_position); selection.start_dragging();
selection.translate(position - cache_position, selection.requires_local_axes());
canvas->do_move(); canvas->do_move();
cache_position = position; cache_position = position;

View file

@ -586,7 +586,8 @@ void Preview::create_double_slider()
auto& config = wxGetApp().preset_bundle->project_config; auto& config = wxGetApp().preset_bundle->project_config;
((config.option<ConfigOptionFloats>("colorprint_heights"))->values) = (m_slider->GetTicksValues()); ((config.option<ConfigOptionFloats>("colorprint_heights"))->values) = (m_slider->GetTicksValues());
m_schedule_background_process(); m_schedule_background_process();
int type = m_choice_view_type->FindString(_(L("Color Print"))); bool color_print = !config.option<ConfigOptionFloats>("colorprint_heights")->values.empty();
int type = m_choice_view_type->FindString(color_print ? _(L("Color Print")) : _(L("Feature type")) );
if (m_choice_view_type->GetSelection() != type) { if (m_choice_view_type->GetSelection() != type) {
m_choice_view_type->SetSelection(type); m_choice_view_type->SetSelection(type);
if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types)) if ((0 <= type) && (type < (int)GCodePreviewData::Extrusion::Num_View_Types))

View file

@ -23,7 +23,7 @@ KBShortcutsDialog::KBShortcutsDialog()
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
font.SetPointSize(10); font.SetPointSize(10);
const wxFont bold_font = font.Bold(); wxFont bold_font = font.Bold();
#ifdef __WXOSX__ #ifdef __WXOSX__
font.SetPointSize(12); font.SetPointSize(12);
bold_font.SetPointSize(14); bold_font.SetPointSize(14);

View file

@ -28,10 +28,8 @@
namespace Slic3r { namespace Slic3r {
namespace GUI { namespace GUI {
MainFrame::MainFrame(const bool no_plater, const bool loaded) : MainFrame::MainFrame() :
wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE), wxFrame(NULL, wxID_ANY, SLIC3R_BUILD, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE),
m_no_plater(no_plater),
m_loaded(loaded),
m_printhost_queue_dlg(new PrintHostQueueDialog(this)) m_printhost_queue_dlg(new PrintHostQueueDialog(this))
{ {
// Load the icon either from the exe, or from the ico file. // Load the icon either from the exe, or from the ico file.
@ -125,11 +123,9 @@ void MainFrame::init_tabpanel()
} }
}); });
if (!m_no_plater) { m_plater = new Slic3r::GUI::Plater(m_tabpanel, this);
m_plater = new Slic3r::GUI::Plater(m_tabpanel, this); wxGetApp().plater_ = m_plater;
wxGetApp().plater_ = m_plater; m_tabpanel->AddPage(m_plater, _(L("Plater")));
m_tabpanel->AddPage(m_plater, _(L("Plater")));
}
// The following event is emited by Tab implementation on config value change. // The following event is emited by Tab implementation on config value change.
Bind(EVT_TAB_VALUE_CHANGED, &MainFrame::on_value_changed, this); Bind(EVT_TAB_VALUE_CHANGED, &MainFrame::on_value_changed, this);

View file

@ -42,10 +42,7 @@ struct PresetTab {
class MainFrame : public wxFrame class MainFrame : public wxFrame
{ {
bool m_no_plater; bool m_loaded {false};
bool m_loaded;
int m_lang_ch_event;
int m_preferences_event;
wxString m_qs_last_input_file = wxEmptyString; wxString m_qs_last_input_file = wxEmptyString;
wxString m_qs_last_output_file = wxEmptyString; wxString m_qs_last_output_file = wxEmptyString;
@ -71,8 +68,7 @@ class MainFrame : public wxFrame
bool can_delete_all() const; bool can_delete_all() const;
public: public:
MainFrame() {} MainFrame();
MainFrame(const bool no_plater, const bool loaded);
~MainFrame() {} ~MainFrame() {}
Plater* plater() { return m_plater; } Plater* plater() { return m_plater; }

View file

@ -102,7 +102,7 @@ PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent)
job_list->AppendTextColumn("Filename", wxDATAVIEW_CELL_INERT); job_list->AppendTextColumn("Filename", wxDATAVIEW_CELL_INERT);
auto *btnsizer = new wxBoxSizer(wxHORIZONTAL); auto *btnsizer = new wxBoxSizer(wxHORIZONTAL);
auto *btn_cancel = new wxButton(this, wxID_DELETE, _(L("Cancel selected"))); auto *btn_cancel = new wxButton(this, wxID_DELETE, _(L("Cancel selected"))); // TODO: enable based on status ("show error" for failed jobs)
auto *btn_close = new wxButton(this, wxID_CANCEL, _(L("Close"))); auto *btn_close = new wxButton(this, wxID_CANCEL, _(L("Close")));
btnsizer->Add(btn_cancel, 0, wxRIGHT, SPACING); btnsizer->Add(btn_cancel, 0, wxRIGHT, SPACING);
btnsizer->AddStretchSpacer(); btnsizer->AddStretchSpacer();
@ -140,7 +140,13 @@ void PrintHostQueueDialog::on_error(Event &evt)
{ {
wxCHECK_RET(evt.job_id < job_list->GetItemCount(), "Out of bounds access to job list"); wxCHECK_RET(evt.job_id < job_list->GetItemCount(), "Out of bounds access to job list");
// TODO job_list->SetValue(wxVariant(0), evt.job_id, 1);
job_list->SetValue(wxVariant(_(L("Error"))), evt.job_id, 2);
// TODO: keep the error for repeated display
auto errormsg = wxString::Format("%s\n%s", _(L("Error uploading to print host:")), evt.error);
GUI::show_error(nullptr, std::move(errormsg));
} }

View file

@ -1551,7 +1551,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
auto printhost_browse = [this, optgroup] (wxWindow* parent) { auto printhost_browse = [this, optgroup] (wxWindow* parent) {
// TODO: SLA // TODO: SLA Bonjour
auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT); auto btn = m_printhost_browse_btn = new wxButton(parent, wxID_ANY, _(L(" Browse "))+dots, wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG)); btn->SetBitmap(wxBitmap(from_u8(Slic3r::var("zoom.png")), wxBITMAP_TYPE_PNG));
@ -1562,6 +1562,7 @@ void TabPrinter::build_printhost(ConfigOptionsGroup *optgroup)
BonjourDialog dialog(parent); BonjourDialog dialog(parent);
if (dialog.show_and_lookup()) { if (dialog.show_and_lookup()) {
optgroup->set_value("print_host", std::move(dialog.get_selected()), true); optgroup->set_value("print_host", std::move(dialog.get_selected()), true);
// FIXME: emit killfocus on the edit widget
} }
}); });

View file

@ -2058,7 +2058,7 @@ void PrusaDoubleSlider::enter_window(wxMouseEvent& event, const bool enter)
// - value decrease (if wxSL_HORIZONTAL) // - value decrease (if wxSL_HORIZONTAL)
void PrusaDoubleSlider::move_current_thumb(const bool condition) void PrusaDoubleSlider::move_current_thumb(const bool condition)
{ {
m_is_one_layer = wxGetKeyState(WXK_CONTROL); // m_is_one_layer = wxGetKeyState(WXK_CONTROL);
int delta = condition ? -1 : 1; int delta = condition ? -1 : 1;
if (is_horizontal()) if (is_horizontal())
delta *= -1; delta *= -1;

View file

@ -46,7 +46,7 @@ bool Duet::test(wxString &msg) const
wxString Duet::get_test_ok_msg () const wxString Duet::get_test_ok_msg () const
{ {
return wxString::Format("%s", _(L("Connection to Duet works correctly."))); return _(L("Connection to Duet works correctly."));
} }
wxString Duet::get_test_failed_msg (wxString &msg) const wxString Duet::get_test_failed_msg (wxString &msg) const
@ -135,7 +135,7 @@ wxString Duet::get_test_failed_msg (wxString &msg) const
// return res; // return res;
// } // }
bool Duet::upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn, Http::ErrorFn error_fn) const bool Duet::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const
{ {
// XXX: TODO // XXX: TODO
throw "unimplemented"; throw "unimplemented";

View file

@ -19,12 +19,12 @@ public:
Duet(DynamicPrintConfig *config); Duet(DynamicPrintConfig *config);
virtual ~Duet(); virtual ~Duet();
bool test(wxString &curl_msg) const; virtual bool test(wxString &curl_msg) const;
wxString get_test_ok_msg () const; virtual wxString get_test_ok_msg () const;
wxString get_test_failed_msg (wxString &msg) const; virtual wxString get_test_failed_msg (wxString &msg) const;
bool upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn, Http::ErrorFn error_fn) const; virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const;
bool has_auto_discovery() const; virtual bool has_auto_discovery() const;
bool can_test() const; virtual bool can_test() const;
virtual std::string get_host() const { return host; } virtual std::string get_host() const { return host; }
private: private:
std::string host; std::string host;

View file

@ -32,6 +32,7 @@ class CurlGlobalInit
struct Http::priv struct Http::priv
{ {
enum { enum {
DEFAULT_TIMEOUT = 10,
DEFAULT_SIZE_LIMIT = 5 * 1024 * 1024, DEFAULT_SIZE_LIMIT = 5 * 1024 * 1024,
}; };
@ -63,6 +64,7 @@ struct Http::priv
static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow); static int xfercb_legacy(void *userp, double dltotal, double dlnow, double ultotal, double ulnow);
static size_t form_file_read_cb(char *buffer, size_t size, size_t nitems, void *userp); static size_t form_file_read_cb(char *buffer, size_t size, size_t nitems, void *userp);
void set_timeout(long timeout);
void form_add_file(const char *name, const fs::path &path, const char* filename); void form_add_file(const char *name, const fs::path &path, const char* filename);
void set_post_body(const fs::path &path); void set_post_body(const fs::path &path);
@ -84,6 +86,7 @@ Http::priv::priv(const std::string &url)
throw std::runtime_error(std::string("Could not construct Curl object")); throw std::runtime_error(std::string("Could not construct Curl object"));
} }
set_timeout(DEFAULT_TIMEOUT);
::curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // curl makes a copy internally ::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_USERAGENT, SLIC3R_FORK_NAME "/" SLIC3R_VERSION);
::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer.front()); ::curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, &error_buffer.front());
@ -167,6 +170,12 @@ size_t Http::priv::form_file_read_cb(char *buffer, size_t size, size_t nitems, v
return stream->gcount(); return stream->gcount();
} }
void Http::priv::set_timeout(long timeout)
{
::curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout);
::curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
}
void Http::priv::form_add_file(const char *name, const fs::path &path, const char* filename) void Http::priv::form_add_file(const char *name, const fs::path &path, const char* filename)
{ {
// We can't use CURLFORM_FILECONTENT, because curl doesn't support Unicode filenames on Windows // We can't use CURLFORM_FILECONTENT, because curl doesn't support Unicode filenames on Windows
@ -203,10 +212,10 @@ void Http::priv::set_post_body(const fs::path &path)
std::string Http::priv::curl_error(CURLcode curlcode) std::string Http::priv::curl_error(CURLcode curlcode)
{ {
return (boost::format("%1% (%2%): %3%") return (boost::format("%1%:\n%2%\n[Error %3%]")
% ::curl_easy_strerror(curlcode) % ::curl_easy_strerror(curlcode)
% error_buffer.c_str()
% curlcode % curlcode
% error_buffer
).str(); ).str();
} }
@ -293,6 +302,13 @@ Http::~Http()
} }
Http& Http::timeout(long timeout)
{
if (timeout < 1) { timeout = priv::DEFAULT_TIMEOUT; }
if (p) { p->set_timeout(timeout); }
return *this;
}
Http& Http::size_limit(size_t sizeLimit) Http& Http::size_limit(size_t sizeLimit)
{ {
if (p) { p->limit = sizeLimit; } if (p) { p->limit = sizeLimit; }

View file

@ -55,6 +55,8 @@ public:
Http& operator=(const Http &) = delete; Http& operator=(const Http &) = delete;
Http& operator=(Http &&) = delete; Http& operator=(Http &&) = delete;
// Sets a maximum connection timeout in seconds
Http& timeout(long timeout);
// Sets a maximum size of the data that can be received. // Sets a maximum size of the data that can be received.
// A value of zero sets the default limit, which is is 5MB. // A value of zero sets the default limit, which is is 5MB.
Http& size_limit(size_t sizeLimit); Http& size_limit(size_t sizeLimit);

View file

@ -1,8 +1,12 @@
#include "OctoPrint.hpp" #include "OctoPrint.hpp"
#include <algorithm> #include <algorithm>
#include <sstream>
#include <boost/format.hpp> #include <boost/format.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <wx/progdlg.h> #include <wx/progdlg.h>
@ -12,6 +16,7 @@
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace pt = boost::property_tree;
namespace Slic3r { namespace Slic3r {
@ -41,11 +46,29 @@ bool OctoPrint::test(wxString &msg) const
res = false; res = false;
msg = format_error(body, error, status); msg = format_error(body, error, status);
}) })
.on_complete([&](std::string body, unsigned) { .on_complete([&, this](std::string body, unsigned) {
BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body; BOOST_LOG_TRIVIAL(debug) << boost::format("Octoprint: Got version: %1%") % body;
// TODO: parse body, call validate_version_text try {
std::stringstream ss(body);
pt::ptree ptree;
pt::read_json(ss, ptree);
if (! ptree.get_optional<std::string>("api")) {
res = false;
return;
}
const auto text = ptree.get_optional<std::string>("text");
res = validate_version_text(text);
if (! res) {
msg = wxString::Format(_(L("Mismatched type of print host: %s")), text ? *text : "OctoPrint");
}
}
catch (...) {
res = false;
msg = "Could not parse server response";
}
}) })
.perform_sync(); .perform_sync();
@ -54,28 +77,24 @@ bool OctoPrint::test(wxString &msg) const
wxString OctoPrint::get_test_ok_msg () const wxString OctoPrint::get_test_ok_msg () const
{ {
return wxString::Format("%s", _(L("Connection to OctoPrint works correctly."))); return _(L("Connection to OctoPrint works correctly."));
} }
wxString OctoPrint::get_test_failed_msg (wxString &msg) const wxString OctoPrint::get_test_failed_msg (wxString &msg) const
{ {
return wxString::Format("%s: %s\n\n%s", return wxString::Format("%s: %s\n\n%s",
_(L("Could not connect to OctoPrint")), msg, _(L("Note: OctoPrint version at least 1.1.0 is required."))); _(L("Could not connect to OctoPrint")), msg, _(L("Note: OctoPrint version at least 1.1.0 is required.")));
} }
bool OctoPrint::upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn, Http::ErrorFn error_fn) const bool OctoPrint::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const
{ {
const auto upload_filename = upload_data.upload_path.filename(); const auto upload_filename = upload_data.upload_path.filename();
const auto upload_parent_path = upload_data.upload_path.parent_path(); const auto upload_parent_path = upload_data.upload_path.parent_path();
wxString test_msg; wxString test_msg;
if (! test(test_msg)) { if (! test(test_msg)) {
error_fn(std::move(test_msg));
// TODO: return false;
// auto errormsg = wxString::Format("%s: %s", errortitle, test_msg);
// GUI::show_error(&progress_dialog, std::move(errormsg));
// return false;
} }
bool res = true; bool res = true;
@ -99,7 +118,8 @@ bool OctoPrint::upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn
}) })
.on_error([&](std::string body, std::string error, unsigned status) { .on_error([&](std::string body, std::string error, unsigned status) {
BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body; BOOST_LOG_TRIVIAL(error) << boost::format("Octoprint: Error uploading file: %1%, HTTP %2%, body: `%3%`") % error % status % body;
error_fn(std::move(body), std::move(error), status); // error_fn(std::move(body), std::move(error), status);
error_fn(format_error(body, error, status));
res = false; res = false;
}) })
.on_progress([&](Http::Progress progress, bool &cancel) { .on_progress([&](Http::Progress progress, bool &cancel) {
@ -125,10 +145,9 @@ bool OctoPrint::can_test() const
return true; return true;
} }
bool OctoPrint::validate_version_text(const std::string &version_text) bool OctoPrint::validate_version_text(const boost::optional<std::string> &version_text) const
{ {
// FIXME return version_text ? boost::starts_with(*version_text, "OctoPrint") : true;
return true;
} }
void OctoPrint::set_auth(Http &http) const void OctoPrint::set_auth(Http &http) const
@ -164,14 +183,23 @@ wxString OctoPrint::format_error(const std::string &body, const std::string &err
} }
// SL1 // SLAHost
SL1Host::~SL1Host() {} SLAHost::~SLAHost() {}
bool SL1Host::validate_version_text(const std::string &version_text) wxString SLAHost::get_test_ok_msg () const
{ {
// FIXME return _(L("Connection to Prusa SLA works correctly."));
return true; }
wxString SLAHost::get_test_failed_msg (wxString &msg) const
{
return wxString::Format("%s: %s", _(L("Could not connect to Prusa SLA")), msg);
}
bool SLAHost::validate_version_text(const boost::optional<std::string> &version_text) const
{
return version_text ? boost::starts_with(*version_text, "Prusa SLA") : false;
} }

View file

@ -3,6 +3,7 @@
#include <string> #include <string>
#include <wx/string.h> #include <wx/string.h>
#include <boost/optional.hpp>
#include "PrintHost.hpp" #include "PrintHost.hpp"
@ -19,16 +20,16 @@ public:
OctoPrint(DynamicPrintConfig *config); OctoPrint(DynamicPrintConfig *config);
virtual ~OctoPrint(); virtual ~OctoPrint();
bool test(wxString &curl_msg) const; virtual bool test(wxString &curl_msg) const;
wxString get_test_ok_msg () const; virtual wxString get_test_ok_msg () const;
wxString get_test_failed_msg (wxString &msg) const; virtual wxString get_test_failed_msg (wxString &msg) const;
bool upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn, Http::ErrorFn error_fn) const; virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const;
bool has_auto_discovery() const; virtual bool has_auto_discovery() const;
bool can_test() const; virtual bool can_test() const;
virtual std::string get_host() const { return host; } virtual std::string get_host() const { return host; }
protected: protected:
virtual bool validate_version_text(const std::string &version_text); virtual bool validate_version_text(const boost::optional<std::string> &version_text) const;
private: private:
std::string host; std::string host;
@ -41,14 +42,16 @@ private:
}; };
class SL1Host: public OctoPrint class SLAHost: public OctoPrint
{ {
public: public:
SL1Host(DynamicPrintConfig *config) : OctoPrint(config) {} SLAHost(DynamicPrintConfig *config) : OctoPrint(config) {}
virtual ~SL1Host(); virtual ~SLAHost();
virtual wxString get_test_ok_msg () const;
virtual wxString get_test_failed_msg (wxString &msg) const;
protected: protected:
virtual bool validate_version_text(const std::string &version_text); virtual bool validate_version_text(const boost::optional<std::string> &version_text) const;
}; };

View file

@ -2,10 +2,12 @@
#include <vector> #include <vector>
#include <thread> #include <thread>
#include <exception>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <wx/string.h>
#include <wx/app.h> #include <wx/app.h>
#include "libslic3r/PrintConfig.hpp" #include "libslic3r/PrintConfig.hpp"
@ -30,8 +32,8 @@ PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config)
switch (opt->value) { switch (opt->value) {
case htOctoPrint: return new OctoPrint(config); case htOctoPrint: return new OctoPrint(config);
case htSL1: return new SL1Host(config);
case htDuet: return new Duet(config); case htDuet: return new Duet(config);
case htSL1: return new SLAHost(config);
default: return nullptr; default: return nullptr;
} }
} }
@ -58,7 +60,6 @@ struct PrintHostJobQueue::priv
void start_bg_thread(); void start_bg_thread();
void bg_thread_main(); void bg_thread_main();
void progress_fn(Http::Progress progress, bool &cancel); void progress_fn(Http::Progress progress, bool &cancel);
void error_fn(std::string body, std::string error, unsigned http_status);
void perform_job(PrintHostJob the_job); void perform_job(PrintHostJob the_job);
}; };
@ -100,6 +101,9 @@ void PrintHostJobQueue::priv::bg_thread_main()
} }
job_id++; job_id++;
} }
} catch (const std::exception &e) {
auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_ERROR, queue_dialog->GetId(), job_id, e.what());
wxQueueEvent(queue_dialog, evt);
} catch (...) { } catch (...) {
wxTheApp->OnUnhandledException(); wxTheApp->OnUnhandledException();
} }
@ -136,28 +140,28 @@ void PrintHostJobQueue::priv::progress_fn(Http::Progress progress, bool &cancel)
} }
} }
void PrintHostJobQueue::priv::error_fn(std::string body, std::string error, unsigned http_status)
{
// TODO
}
void PrintHostJobQueue::priv::perform_job(PrintHostJob the_job) void PrintHostJobQueue::priv::perform_job(PrintHostJob the_job)
{ {
if (bg_exit || the_job.empty()) { return; } if (bg_exit || the_job.empty()) { return; }
BOOST_LOG_TRIVIAL(debug) << boost::format("PrintHostJobQueue/bg_thread: Got job: `%1%` -> `%1%`") BOOST_LOG_TRIVIAL(debug) << boost::format("PrintHostJobQueue/bg_thread: Got job: `%1%` -> `%2%`")
% the_job.upload_data.upload_path % the_job.upload_data.upload_path
% the_job.printhost->get_host(); % the_job.printhost->get_host();
const fs::path gcode_path = the_job.upload_data.source_path; const fs::path gcode_path = the_job.upload_data.source_path;
the_job.printhost->upload(std::move(the_job.upload_data), bool success = the_job.printhost->upload(std::move(the_job.upload_data),
[this](Http::Progress progress, bool &cancel) { this->progress_fn(std::move(progress), cancel); }, [this](Http::Progress progress, bool &cancel) { this->progress_fn(std::move(progress), cancel); },
[this](std::string body, std::string error, unsigned http_status) { this->error_fn(std::move(body), std::move(error), http_status); } [this](wxString error) {
auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_ERROR, queue_dialog->GetId(), job_id, std::move(error));
wxQueueEvent(queue_dialog, evt);
}
); );
auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_PROGRESS, queue_dialog->GetId(), job_id, 100); if (success) {
wxQueueEvent(queue_dialog, evt); auto evt = new PrintHostQueueDialog::Event(GUI::EVT_PRINTHOST_PROGRESS, queue_dialog->GetId(), job_id, 100);
wxQueueEvent(queue_dialog, evt);
}
boost::system::error_code ec; boost::system::error_code ec;
fs::remove(gcode_path, ec); fs::remove(gcode_path, ec);

View file

@ -3,6 +3,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <functional>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <wx/string.h> #include <wx/string.h>
@ -28,10 +29,13 @@ class PrintHost
public: public:
virtual ~PrintHost(); virtual ~PrintHost();
typedef Http::ProgressFn ProgressFn;
typedef std::function<void(wxString /* error */)> ErrorFn;
virtual bool test(wxString &curl_msg) const = 0; virtual bool test(wxString &curl_msg) const = 0;
virtual wxString get_test_ok_msg () const = 0; virtual wxString get_test_ok_msg () const = 0;
virtual wxString get_test_failed_msg (wxString &msg) const = 0; virtual wxString get_test_failed_msg (wxString &msg) const = 0;
virtual bool upload(PrintHostUpload upload_data, Http::ProgressFn prorgess_fn, Http::ErrorFn error_fn) const = 0; virtual bool upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, ErrorFn error_fn) const = 0;
virtual bool has_auto_discovery() const = 0; virtual bool has_auto_discovery() const = 0;
virtual bool can_test() const = 0; virtual bool can_test() const = 0;
virtual std::string get_host() const = 0; virtual std::string get_host() const = 0;