mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-20 15:21:21 -06:00
Revert "Support upload g-code to third-party printers (#2)"
This reverts commit dc5e0eed34
.
This commit is contained in:
parent
dc5e0eed34
commit
82127a92c9
44 changed files with 19 additions and 5543 deletions
|
@ -227,9 +227,6 @@ void BackgroundSlicingProcess::process_fff()
|
|||
if (! m_export_path.empty()) {
|
||||
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id));
|
||||
finalize_gcode();
|
||||
} else if (! m_upload_job.empty()) {
|
||||
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id));
|
||||
prepare_upload();
|
||||
} else {
|
||||
m_print->set_status(100, _utf8(L("Slicing complete")));
|
||||
}
|
||||
|
@ -687,19 +684,6 @@ void BackgroundSlicingProcess::schedule_export(const std::string &path, bool exp
|
|||
m_export_path_on_removable_media = export_path_on_removable_media;
|
||||
}
|
||||
|
||||
void BackgroundSlicingProcess::schedule_upload(Slic3r::PrintHostJob upload_job)
|
||||
{
|
||||
assert(m_export_path.empty());
|
||||
if (! m_export_path.empty())
|
||||
return;
|
||||
|
||||
// Guard against entering the export step before changing the export path.
|
||||
std::scoped_lock<std::mutex> lock(m_print->state_mutex());
|
||||
this->invalidate_step(bspsGCodeFinalize);
|
||||
m_export_path.clear();
|
||||
m_upload_job = std::move(upload_job);
|
||||
}
|
||||
|
||||
void BackgroundSlicingProcess::reset_export()
|
||||
{
|
||||
assert(! this->running());
|
||||
|
@ -816,45 +800,6 @@ void BackgroundSlicingProcess::finalize_gcode()
|
|||
m_print->set_status(100, (boost::format(_utf8(L("Succeed to export G-code to %1%"))) % export_path).str());
|
||||
}
|
||||
|
||||
// A print host upload job has been scheduled, enqueue it to the printhost job queue
|
||||
void BackgroundSlicingProcess::prepare_upload()
|
||||
{
|
||||
// Generate a unique temp path to which the gcode/zip file is copied/exported
|
||||
boost::filesystem::path source_path = boost::filesystem::temp_directory_path()
|
||||
/ boost::filesystem::unique_path("." SLIC3R_APP_KEY ".upload.%%%%-%%%%-%%%%-%%%%");
|
||||
|
||||
if (m_print == m_fff_print) {
|
||||
m_print->set_status(95, _utf8(L("Running post-processing scripts")));
|
||||
std::string error_message;
|
||||
if (copy_file(m_temp_output_path, source_path.string(), error_message) != SUCCESS)
|
||||
throw Slic3r::RuntimeError(_utf8(L("Copying of the temporary G-code to the output G-code failed")));
|
||||
m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
||||
// Make a copy of the source path, as run_post_process_scripts() is allowed to change it when making a copy of the source file
|
||||
// (not here, but when the final target is a file).
|
||||
std::string source_path_str = source_path.string();
|
||||
std::string output_name_str = m_upload_job.upload_data.upload_path.string();
|
||||
if (run_post_process_scripts(source_path_str, false, m_upload_job.printhost->get_name(), output_name_str, m_fff_print->full_print_config()))
|
||||
m_upload_job.upload_data.upload_path = output_name_str;
|
||||
} else {
|
||||
m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
||||
|
||||
ThumbnailsList thumbnails = this->render_thumbnails(
|
||||
ThumbnailsParams{current_print()->full_print_config().option<ConfigOptionPoints>("thumbnails")->values, true, true, true, true});
|
||||
// true, false, true, true); // renders also supports and pad
|
||||
Zipper zipper{source_path.string()};
|
||||
m_sla_archive.export_print(zipper, *m_sla_print, m_upload_job.upload_data.upload_path.string());
|
||||
for (const ThumbnailData& data : thumbnails)
|
||||
if (data.is_valid())
|
||||
write_thumbnail(zipper, data);
|
||||
zipper.finalize();
|
||||
}
|
||||
|
||||
m_print->set_status(100, (boost::format(_utf8(L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"))) % m_upload_job.printhost->get_host()).str());
|
||||
|
||||
m_upload_job.upload_data.source_path = std::move(source_path);
|
||||
|
||||
GUI::wxGetApp().printhost_job_queue().enqueue(std::move(m_upload_job));
|
||||
}
|
||||
// Executed by the background thread, to start a task on the UI thread.
|
||||
ThumbnailsList BackgroundSlicingProcess::render_thumbnails(const ThumbnailsParams ¶ms)
|
||||
{
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "libslic3r/PrintBase.hpp"
|
||||
#include "libslic3r/GCode/ThumbnailData.hpp"
|
||||
#include "libslic3r/Format/SL1.hpp"
|
||||
#include "slic3r/Utils/PrintHost.hpp"
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "PartPlate.hpp"
|
||||
|
||||
|
@ -149,14 +148,10 @@ public:
|
|||
// Set the export path of the G-code.
|
||||
// Once the path is set, the G-code
|
||||
void schedule_export(const std::string &path, bool export_path_on_removable_media);
|
||||
// Set print host upload job data to be enqueued to the PrintHostJobQueue
|
||||
// after current print slicing is complete
|
||||
void schedule_upload(Slic3r::PrintHostJob upload_job);
|
||||
// Clear m_export_path.
|
||||
void reset_export();
|
||||
// Once the G-code export is scheduled, the apply() methods will do nothing.
|
||||
bool is_export_scheduled() const { return ! m_export_path.empty(); }
|
||||
bool is_upload_scheduled() const { return ! m_upload_job.empty(); }
|
||||
|
||||
enum State {
|
||||
// m_thread is not running yet, or it did not reach the STATE_IDLE yet (it does not wait on the condition yet).
|
||||
|
@ -243,9 +238,6 @@ private:
|
|||
// but once set, it cannot be re-set.
|
||||
std::string m_export_path;
|
||||
bool m_export_path_on_removable_media = false;
|
||||
// Print host upload job to schedule after slicing is complete, used by schedule_upload(),
|
||||
// empty by default (ie. no upload to schedule)
|
||||
PrintHostJob m_upload_job;
|
||||
// Thread, on which the background processing is executed. The thread will always be present
|
||||
// and ready to execute the slicing process.
|
||||
boost::thread m_thread;
|
||||
|
@ -284,7 +276,6 @@ private:
|
|||
// If the background processing stop was requested, throw CanceledException.
|
||||
void throw_if_canceled() const { if (m_print->canceled()) throw CanceledException(); }
|
||||
void finalize_gcode();
|
||||
void prepare_upload();
|
||||
// To be executed at the background thread.
|
||||
ThumbnailsList render_thumbnails(const ThumbnailsParams ¶ms);
|
||||
// Execute task from background thread on the UI thread synchronously. Returns true if processed, false if cancelled before executing the task.
|
||||
|
|
|
@ -1,239 +0,0 @@
|
|||
#include "slic3r/Utils/Bonjour.hpp" // On Windows, boost needs to be included before wxWidgets headers
|
||||
|
||||
#include "BonjourDialog.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <mutex>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/listctrl.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include "slic3r/GUI/GUI.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/I18N.hpp"
|
||||
#include "slic3r/Utils/Bonjour.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
|
||||
class BonjourReplyEvent : public wxEvent
|
||||
{
|
||||
public:
|
||||
BonjourReply reply;
|
||||
|
||||
BonjourReplyEvent(wxEventType eventType, int winid, BonjourReply &&reply) :
|
||||
wxEvent(winid, eventType),
|
||||
reply(std::move(reply))
|
||||
{}
|
||||
|
||||
virtual wxEvent *Clone() const
|
||||
{
|
||||
return new BonjourReplyEvent(*this);
|
||||
}
|
||||
};
|
||||
|
||||
wxDEFINE_EVENT(EVT_BONJOUR_REPLY, BonjourReplyEvent);
|
||||
|
||||
wxDECLARE_EVENT(EVT_BONJOUR_COMPLETE, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_BONJOUR_COMPLETE, wxCommandEvent);
|
||||
|
||||
class ReplySet: public std::set<BonjourReply> {};
|
||||
|
||||
struct LifetimeGuard
|
||||
{
|
||||
std::mutex mutex;
|
||||
BonjourDialog *dialog;
|
||||
|
||||
LifetimeGuard(BonjourDialog *dialog) : dialog(dialog) {}
|
||||
};
|
||||
|
||||
BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech)
|
||||
: wxDialog(parent, wxID_ANY, _(L("Network lookup")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
|
||||
, list(new wxListView(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxSIMPLE_BORDER))
|
||||
, replies(new ReplySet)
|
||||
, label(new wxStaticText(this, wxID_ANY, ""))
|
||||
, timer(new wxTimer())
|
||||
, timer_state(0)
|
||||
, tech(tech)
|
||||
{
|
||||
const int em = GUI::wxGetApp().em_unit();
|
||||
list->SetMinSize(wxSize(80 * em, 30 * em));
|
||||
|
||||
wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
vsizer->Add(label, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, em);
|
||||
|
||||
list->SetSingleStyle(wxLC_SINGLE_SEL);
|
||||
list->SetSingleStyle(wxLC_SORT_DESCENDING);
|
||||
list->AppendColumn(_(L("Address")), wxLIST_FORMAT_LEFT, 5 * em);
|
||||
list->AppendColumn(_(L("Hostname")), wxLIST_FORMAT_LEFT, 10 * em);
|
||||
list->AppendColumn(_(L("Service name")), wxLIST_FORMAT_LEFT, 20 * em);
|
||||
if (tech == ptFFF) {
|
||||
list->AppendColumn(_(L("OctoPrint version")), wxLIST_FORMAT_LEFT, 5 * em);
|
||||
}
|
||||
|
||||
vsizer->Add(list, 1, wxEXPAND | wxALL, em);
|
||||
|
||||
wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
button_sizer->Add(new wxButton(this, wxID_OK, "OK"), 0, wxALL, em);
|
||||
button_sizer->Add(new wxButton(this, wxID_CANCEL, "Cancel"), 0, wxALL, em);
|
||||
// ^ Note: The Ok/Cancel labels are translated by wxWidgets
|
||||
|
||||
vsizer->Add(button_sizer, 0, wxALIGN_CENTER);
|
||||
SetSizerAndFit(vsizer);
|
||||
|
||||
Bind(EVT_BONJOUR_REPLY, &BonjourDialog::on_reply, this);
|
||||
|
||||
Bind(EVT_BONJOUR_COMPLETE, [this](wxCommandEvent &) {
|
||||
this->timer_state = 0;
|
||||
});
|
||||
|
||||
Bind(wxEVT_TIMER, &BonjourDialog::on_timer, this);
|
||||
GUI::wxGetApp().UpdateDlgDarkUI(this);
|
||||
}
|
||||
|
||||
BonjourDialog::~BonjourDialog()
|
||||
{
|
||||
// Needed bacuse of forward defs
|
||||
}
|
||||
|
||||
bool BonjourDialog::show_and_lookup()
|
||||
{
|
||||
Show(); // Because we need GetId() to work before ShowModal()
|
||||
|
||||
timer->Stop();
|
||||
timer->SetOwner(this);
|
||||
timer_state = 1;
|
||||
timer->Start(1000);
|
||||
on_timer_process();
|
||||
|
||||
// The background thread needs to queue messages for this dialog
|
||||
// and for that it needs a valid pointer to it (mandated by the wxWidgets API).
|
||||
// Here we put the pointer under a shared_ptr and protect it by a mutex,
|
||||
// so that both threads can access it safely.
|
||||
auto dguard = std::make_shared<LifetimeGuard>(this);
|
||||
|
||||
// Note: More can be done here when we support discovery of hosts other than Octoprint and SL1
|
||||
Bonjour::TxtKeys txt_keys { "version", "model" };
|
||||
|
||||
bonjour = Bonjour("octoprint")
|
||||
.set_txt_keys(std::move(txt_keys))
|
||||
.set_retries(3)
|
||||
.set_timeout(4)
|
||||
.on_reply([dguard](BonjourReply &&reply) {
|
||||
std::lock_guard<std::mutex> lock_guard(dguard->mutex);
|
||||
auto dialog = dguard->dialog;
|
||||
if (dialog != nullptr) {
|
||||
auto evt = new BonjourReplyEvent(EVT_BONJOUR_REPLY, dialog->GetId(), std::move(reply));
|
||||
wxQueueEvent(dialog, evt);
|
||||
}
|
||||
})
|
||||
.on_complete([dguard]() {
|
||||
std::lock_guard<std::mutex> lock_guard(dguard->mutex);
|
||||
auto dialog = dguard->dialog;
|
||||
if (dialog != nullptr) {
|
||||
auto evt = new wxCommandEvent(EVT_BONJOUR_COMPLETE, dialog->GetId());
|
||||
wxQueueEvent(dialog, evt);
|
||||
}
|
||||
})
|
||||
.lookup();
|
||||
|
||||
bool res = ShowModal() == wxID_OK && list->GetFirstSelected() >= 0;
|
||||
{
|
||||
// Tell the background thread the dialog is going away...
|
||||
std::lock_guard<std::mutex> lock_guard(dguard->mutex);
|
||||
dguard->dialog = nullptr;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
wxString BonjourDialog::get_selected() const
|
||||
{
|
||||
auto sel = list->GetFirstSelected();
|
||||
return sel >= 0 ? list->GetItemText(sel) : wxString();
|
||||
}
|
||||
|
||||
|
||||
// Private
|
||||
|
||||
void BonjourDialog::on_reply(BonjourReplyEvent &e)
|
||||
{
|
||||
if (replies->find(e.reply) != replies->end()) {
|
||||
// We already have this reply
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter replies based on selected technology
|
||||
const auto model = e.reply.txt_data.find("model");
|
||||
const bool sl1 = model != e.reply.txt_data.end() && model->second == "SL1";
|
||||
if ((tech == ptFFF && sl1) || (tech == ptSLA && !sl1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
replies->insert(std::move(e.reply));
|
||||
|
||||
auto selected = get_selected();
|
||||
|
||||
wxWindowUpdateLocker freeze_guard(this);
|
||||
(void)freeze_guard;
|
||||
|
||||
list->DeleteAllItems();
|
||||
|
||||
// The whole list is recreated so that we benefit from it already being sorted in the set.
|
||||
// (And also because wxListView's sorting API is bananas.)
|
||||
for (const auto &reply : *replies) {
|
||||
auto item = list->InsertItem(0, reply.full_address);
|
||||
list->SetItem(item, 1, reply.hostname);
|
||||
list->SetItem(item, 2, reply.service_name);
|
||||
|
||||
if (tech == ptFFF) {
|
||||
const auto it = reply.txt_data.find("version");
|
||||
if (it != reply.txt_data.end()) {
|
||||
list->SetItem(item, 3, GUI::from_u8(it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const int em = GUI::wxGetApp().em_unit();
|
||||
|
||||
for (int i = 0; i < list->GetColumnCount(); i++) {
|
||||
list->SetColumnWidth(i, wxLIST_AUTOSIZE);
|
||||
if (list->GetColumnWidth(i) < 10 * em) { list->SetColumnWidth(i, 10 * em); }
|
||||
}
|
||||
|
||||
if (!selected.IsEmpty()) {
|
||||
// Attempt to preserve selection
|
||||
auto hit = list->FindItem(-1, selected);
|
||||
if (hit >= 0) { list->SetItemState(hit, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); }
|
||||
}
|
||||
}
|
||||
|
||||
void BonjourDialog::on_timer(wxTimerEvent &)
|
||||
{
|
||||
on_timer_process();
|
||||
}
|
||||
|
||||
// This is here so the function can be bound to wxEVT_TIMER and also called
|
||||
// explicitly (wxTimerEvent should not be created by user code).
|
||||
void BonjourDialog::on_timer_process()
|
||||
{
|
||||
const auto search_str = _utf8(L("Searching for devices"));
|
||||
|
||||
if (timer_state > 0) {
|
||||
const std::string dots(timer_state, '.');
|
||||
label->SetLabel(GUI::from_u8((boost::format("%1% %2%") % search_str % dots).str()));
|
||||
timer_state = (timer_state) % 3 + 1;
|
||||
} else {
|
||||
label->SetLabel(GUI::from_u8((boost::format("%1%: %2%") % search_str % (_utf8(L("Finished"))+".")).str()));
|
||||
timer->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
#ifndef slic3r_BonjourDialog_hpp_
|
||||
#define slic3r_BonjourDialog_hpp_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <wx/dialog.h>
|
||||
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
||||
class wxListView;
|
||||
class wxStaticText;
|
||||
class wxTimer;
|
||||
class wxTimerEvent;
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Bonjour;
|
||||
class BonjourReplyEvent;
|
||||
class ReplySet;
|
||||
|
||||
|
||||
class BonjourDialog: public wxDialog
|
||||
{
|
||||
public:
|
||||
BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology);
|
||||
BonjourDialog(BonjourDialog &&) = delete;
|
||||
BonjourDialog(const BonjourDialog &) = delete;
|
||||
BonjourDialog &operator=(BonjourDialog &&) = delete;
|
||||
BonjourDialog &operator=(const BonjourDialog &) = delete;
|
||||
~BonjourDialog();
|
||||
|
||||
bool show_and_lookup();
|
||||
wxString get_selected() const;
|
||||
private:
|
||||
wxListView *list;
|
||||
std::unique_ptr<ReplySet> replies;
|
||||
wxStaticText *label;
|
||||
std::shared_ptr<Bonjour> bonjour;
|
||||
std::unique_ptr<wxTimer> timer;
|
||||
unsigned timer_state;
|
||||
Slic3r::PrinterTechnology tech;
|
||||
|
||||
void on_reply(BonjourReplyEvent &);
|
||||
void on_timer(wxTimerEvent &);
|
||||
void on_timer_process();
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1225,9 +1225,7 @@ void Choice::set_value(const boost::any& value, bool change_event)
|
|||
// BBS
|
||||
case coEnums: {
|
||||
int val = boost::any_cast<int>(value);
|
||||
if (m_opt_id.compare("host_type") == 0 && val != 0 &&
|
||||
m_opt.enum_values.size() > field->GetCount()) // for case, when PrusaLink isn't used as a HostType
|
||||
val--;
|
||||
|
||||
if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern")
|
||||
{
|
||||
std::string key;
|
||||
|
@ -1307,11 +1305,7 @@ boost::any& Choice::get_value()
|
|||
// BBS
|
||||
if (m_opt.type == coEnum || m_opt.type == coEnums)
|
||||
{
|
||||
if (m_opt_id.compare("host_type") == 0 && m_opt.enum_values.size() > field->GetCount()) {
|
||||
// for case, when PrusaLink isn't used as a HostType
|
||||
m_value = field->GetSelection()+1;
|
||||
}
|
||||
else if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern") {
|
||||
if (m_opt_id == "top_surface_pattern" || m_opt_id == "bottom_surface_pattern" || m_opt_id == "sparse_infill_pattern") {
|
||||
const std::string& key = m_opt.enum_values[field->GetSelection()];
|
||||
m_value = int(ConfigOptionEnum<InfillPattern>::get_enum_values().at(key));
|
||||
}
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
#include "GLCanvas3D.hpp"
|
||||
|
||||
#include "../Utils/PresetUpdater.hpp"
|
||||
#include "../Utils/PrintHost.hpp"
|
||||
#include "../Utils/Process.hpp"
|
||||
#include "../Utils/MacDarkMode.hpp"
|
||||
#include "../Utils/Http.hpp"
|
||||
|
@ -71,7 +70,6 @@
|
|||
#include "NotificationManager.hpp"
|
||||
#include "UnsavedChangesDialog.hpp"
|
||||
#include "SavePresetDialog.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
#include "DesktopIntegrationDialog.hpp"
|
||||
#include "SendSystemInfoDialog.hpp"
|
||||
#include "ParamsDialog.hpp"
|
||||
|
@ -2083,8 +2081,6 @@ bool GUI_App::on_init_inner()
|
|||
|
||||
plater_->init_notification_manager();
|
||||
|
||||
m_printhost_job_queue.reset(new PrintHostJobQueue(mainframe->printhost_queue_dlg()));
|
||||
|
||||
if (is_gcode_viewer()) {
|
||||
mainframe->update_layout();
|
||||
if (plater_ != nullptr)
|
||||
|
@ -2600,7 +2596,6 @@ void GUI_App::recreate_GUI(const wxString& msg_name)
|
|||
old_main_frame->Destroy();
|
||||
|
||||
dlg.Update(80, _L("Loading current presets") + dots);
|
||||
m_printhost_job_queue.reset(new PrintHostJobQueue(mainframe->printhost_queue_dlg()));
|
||||
load_current_presets();
|
||||
mainframe->Show(true);
|
||||
//mainframe->refresh_plugin_tips();
|
||||
|
@ -4306,34 +4301,6 @@ bool GUI_App::can_load_project()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GUI_App::check_print_host_queue()
|
||||
{
|
||||
wxString dirty;
|
||||
std::vector<std::pair<std::string, std::string>> jobs;
|
||||
// Get ongoing jobs from dialog
|
||||
mainframe->m_printhost_queue_dlg->get_active_jobs(jobs);
|
||||
if (jobs.empty())
|
||||
return true;
|
||||
// Show dialog
|
||||
wxString job_string = wxString();
|
||||
for (const auto& job : jobs) {
|
||||
job_string += format_wxstr(" %1% : %2% \n", job.first, job.second);
|
||||
}
|
||||
wxString message;
|
||||
message += _(L("The uploads are still ongoing")) + ":\n\n" + job_string +"\n" + _(L("Stop them and continue anyway?"));
|
||||
//wxMessageDialog dialog(mainframe,
|
||||
MessageDialog dialog(mainframe,
|
||||
message,
|
||||
wxString(SLIC3R_APP_NAME) + " - " + _(L("Ongoing uploads")),
|
||||
wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT);
|
||||
if (dialog.ShowModal() == wxID_YES)
|
||||
return true;
|
||||
|
||||
// TODO: If already shown, bring forward
|
||||
mainframe->m_printhost_queue_dlg->Show();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GUI_App::checked_tab(Tab* tab)
|
||||
{
|
||||
bool ret = true;
|
||||
|
|
|
@ -7,13 +7,11 @@
|
|||
#include "ConfigWizard.hpp"
|
||||
#include "OpenGLManager.hpp"
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/DeviceManager.hpp"
|
||||
#include "slic3r/Utils/NetworkAgent.hpp"
|
||||
#include "slic3r/GUI/WebViewDialog.hpp"
|
||||
#include "slic3r/GUI/Jobs/UpgradeNetworkJob.hpp"
|
||||
#include "../Utils/PrintHost.hpp"
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/colour.h>
|
||||
|
@ -44,7 +42,6 @@ class AppConfig;
|
|||
class PresetBundle;
|
||||
class PresetUpdater;
|
||||
class ModelObject;
|
||||
// class PrintHostJobQueue;
|
||||
class Model;
|
||||
class DeviceManager;
|
||||
class NetworkAgent;
|
||||
|
@ -247,7 +244,6 @@ private:
|
|||
//std::unique_ptr<RemovableDriveManager> m_removable_drive_manager;
|
||||
|
||||
std::unique_ptr<ImGuiWrapper> m_imgui;
|
||||
std::unique_ptr<PrintHostJobQueue> m_printhost_job_queue;
|
||||
//std::unique_ptr <OtherInstanceMessageHandler> m_other_instance_message_handler;
|
||||
//std::unique_ptr <wxSingleInstanceChecker> m_single_instance_checker;
|
||||
//std::string m_instance_hash_string;
|
||||
|
@ -420,7 +416,6 @@ public:
|
|||
void apply_keeped_preset_modifications();
|
||||
bool check_and_keep_current_preset_changes(const wxString& caption, const wxString& header, int action_buttons, bool* postponed_apply_of_keeped_changes = nullptr);
|
||||
bool can_load_project();
|
||||
bool check_print_host_queue();
|
||||
bool checked_tab(Tab* tab);
|
||||
//BBS: add preset combox re-active logic
|
||||
void load_current_presets(bool active_preset_combox = false, bool check_printer_presets = true);
|
||||
|
@ -488,8 +483,6 @@ public:
|
|||
|
||||
ImGuiWrapper* imgui() { return m_imgui.get(); }
|
||||
|
||||
PrintHostJobQueue& printhost_job_queue() { return *m_printhost_job_queue.get(); }
|
||||
|
||||
void open_web_page_localized(const std::string &http_address);
|
||||
bool may_switch_to_SLA_preset(const wxString& caption);
|
||||
bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME);
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "ProgressStatusBar.hpp"
|
||||
#include "3DScene.hpp"
|
||||
#include "ParamsDialog.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "GUI_ObjectList.hpp"
|
||||
#include "Mouse3DController.hpp"
|
||||
|
@ -150,7 +149,6 @@ wxDEFINE_EVENT(EVT_SYNC_CLOUD_PRESET, SimpleEvent);
|
|||
|
||||
MainFrame::MainFrame() :
|
||||
DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_STYLE, "mainframe")
|
||||
, m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
||||
// BBS
|
||||
, m_recent_projects(9)
|
||||
, m_settings_dialog(this)
|
||||
|
@ -401,10 +399,6 @@ DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_
|
|||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< "cancelled by close_with_confirm selection";
|
||||
return;
|
||||
}
|
||||
if (event.CanVeto() && !wxGetApp().check_print_host_queue()) {
|
||||
event.Veto();
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0 // BBS
|
||||
//if (m_plater != nullptr) {
|
||||
|
@ -1111,15 +1105,6 @@ bool MainFrame::can_export_gcode() const
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MainFrame::can_send_gcode() const
|
||||
{
|
||||
if (m_plater && ! m_plater->model().objects.empty())
|
||||
if (const DynamicPrintConfig *cfg = wxGetApp().preset_bundle->physical_printers.get_selected_printer_config(); cfg)
|
||||
if (const auto *print_host_opt = cfg->option<ConfigOptionString>("print_host"); print_host_opt)
|
||||
return ! print_host_opt->value.empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
/*bool MainFrame::can_export_gcode_sd() const
|
||||
{
|
||||
if (m_plater == nullptr)
|
||||
|
|
|
@ -40,7 +40,6 @@ namespace GUI
|
|||
{
|
||||
|
||||
class Tab;
|
||||
class PrintHostQueueDialog;
|
||||
class Plater;
|
||||
class MainFrame;
|
||||
class ParamsDialog;
|
||||
|
@ -111,7 +110,6 @@ class MainFrame : public DPIFrame
|
|||
bool can_export_toolpaths() const;
|
||||
bool can_export_supports() const;
|
||||
bool can_export_gcode() const;
|
||||
bool can_send_gcode() const;
|
||||
//bool can_export_gcode_sd() const;
|
||||
//bool can_eject() const;
|
||||
bool can_slice() const;
|
||||
|
@ -307,7 +305,6 @@ public:
|
|||
|
||||
// BBS. Replace title bar and menu bar with top bar.
|
||||
BBLTopbar* m_topbar{ nullptr };
|
||||
PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; }
|
||||
Plater* m_plater { nullptr };
|
||||
//BBS: GUI refactor
|
||||
MonitorPanel* m_monitor{ nullptr };
|
||||
|
@ -324,7 +321,6 @@ public:
|
|||
SettingsDialog m_settings_dialog;
|
||||
DiffPresetDialog diff_dialog;
|
||||
wxWindow* m_plater_page{ nullptr };
|
||||
PrintHostQueueDialog* m_printhost_queue_dlg;
|
||||
|
||||
// BBS
|
||||
mutable int m_print_select{ ePrintAll };
|
||||
|
|
|
@ -983,149 +983,6 @@ void NotificationManager::UpdatedItemsInfoNotification::add_type(InfoItemType ty
|
|||
update(data);
|
||||
}
|
||||
|
||||
//------PrintHostUploadNotification----------------
|
||||
void NotificationManager::PrintHostUploadNotification::init()
|
||||
{
|
||||
ProgressBarNotification::init();
|
||||
if (m_state == EState::NotFading && m_uj_state == UploadJobState::PB_COMPLETED)
|
||||
m_state = EState::Shown;
|
||||
}
|
||||
void NotificationManager::PrintHostUploadNotification::count_spaces()
|
||||
{
|
||||
//determine line width
|
||||
m_line_height = ImGui::CalcTextSize("A").y;
|
||||
|
||||
m_left_indentation = m_line_height;
|
||||
if (m_uj_state == UploadJobState::PB_ERROR) {
|
||||
std::string text;
|
||||
text = (m_data.level == NotificationLevel::ErrorNotificationLevel ? ImGui::ErrorMarker : ImGui::WarningMarker);
|
||||
float picture_width = ImGui::CalcTextSize(text.c_str()).x;
|
||||
m_left_indentation = picture_width + m_line_height / 2;
|
||||
}
|
||||
m_window_width_offset = m_line_height * 6; //(m_has_cancel_button ? 6 : 4);
|
||||
m_window_width = m_line_height * 25;
|
||||
}
|
||||
bool NotificationManager::PrintHostUploadNotification::push_background_color()
|
||||
{
|
||||
|
||||
if (m_uj_state == UploadJobState::PB_ERROR) {
|
||||
ImVec4 backcolor = ImGui::GetStyleColorVec4(ImGuiCol_WindowBg);
|
||||
backcolor.x += 0.3f;
|
||||
push_style_color(ImGuiCol_WindowBg, backcolor, m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void NotificationManager::PrintHostUploadNotification::set_percentage(float percent)
|
||||
{
|
||||
m_percentage = percent;
|
||||
if (percent >= 1.0f) {
|
||||
m_uj_state = UploadJobState::PB_COMPLETED;
|
||||
m_has_cancel_button = false;
|
||||
init();
|
||||
} else if (percent < 0.0f) {
|
||||
error();
|
||||
} else {
|
||||
m_uj_state = UploadJobState::PB_PROGRESS;
|
||||
m_has_cancel_button = true;
|
||||
}
|
||||
}
|
||||
void NotificationManager::PrintHostUploadNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
std::string text;
|
||||
switch (m_uj_state) {
|
||||
case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_PROGRESS:
|
||||
{
|
||||
ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
|
||||
float uploaded = m_file_size * m_percentage;
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "% - " << uploaded << " of " << m_file_size << "MB uploaded";
|
||||
text = stream.str();
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4));
|
||||
break;
|
||||
}
|
||||
case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_ERROR:
|
||||
text = _u8L("ERROR");
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2));
|
||||
break;
|
||||
case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_CANCELLED:
|
||||
text = _u8L("CANCELED");
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2));
|
||||
break;
|
||||
case Slic3r::GUI::NotificationManager::PrintHostUploadNotification::UploadJobState::PB_COMPLETED:
|
||||
text = _u8L("COMPLETED");
|
||||
ImGui::SetCursorPosX(m_left_indentation);
|
||||
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? m_line_height / 4 : m_line_height / 2));
|
||||
break;
|
||||
}
|
||||
|
||||
imgui.text(text.c_str());
|
||||
|
||||
}
|
||||
void NotificationManager::PrintHostUploadNotification::render_left_sign(ImGuiWrapper& imgui)
|
||||
{
|
||||
if (m_uj_state == UploadJobState::PB_ERROR) {
|
||||
std::string text;
|
||||
text = ImGui::ErrorMarker;
|
||||
ImGui::SetCursorPosX(m_line_height / 3);
|
||||
ImGui::SetCursorPosY(m_window_height / 2 - m_line_height);
|
||||
imgui.text(text.c_str());
|
||||
}
|
||||
}
|
||||
void NotificationManager::PrintHostUploadNotification::render_cancel_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
|
||||
{
|
||||
ImVec2 win_size(win_size_x, win_size_y);
|
||||
ImVec2 win_pos(win_pos_x, win_pos_y);
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
|
||||
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
|
||||
|
||||
std::string button_text;
|
||||
button_text = ImGui::CancelButton;
|
||||
|
||||
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - m_line_height * 5.f, win_pos.y),
|
||||
ImVec2(win_pos.x - m_line_height * 2.5f, win_pos.y + win_size.y),
|
||||
true))
|
||||
{
|
||||
button_text = ImGui::CancelHoverButton;
|
||||
// tooltip
|
||||
long time_now = wxGetLocalTime();
|
||||
if (m_hover_time > 0 && m_hover_time < time_now) {
|
||||
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
|
||||
ImGui::BeginTooltip();
|
||||
imgui.text(_u8L("Cancel upload") + " " + GUI::shortkey_ctrl_prefix() + "T");
|
||||
ImGui::EndTooltip();
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
if (m_hover_time == 0)
|
||||
m_hover_time = time_now;
|
||||
}
|
||||
else
|
||||
m_hover_time = 0;
|
||||
|
||||
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
|
||||
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
|
||||
ImGui::SetCursorPosX(win_size.x - m_line_height * 5.0f);
|
||||
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
|
||||
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
|
||||
{
|
||||
wxGetApp().printhost_job_queue().cancel(m_job_id - 1);
|
||||
}
|
||||
|
||||
//invisible large button
|
||||
ImGui::SetCursorPosX(win_size.x - m_line_height * 4.625f);
|
||||
ImGui::SetCursorPosY(0);
|
||||
if (imgui.button(" ", m_line_height * 2.f, win_size.y))
|
||||
{
|
||||
wxGetApp().printhost_job_queue().cancel(m_job_id - 1);
|
||||
}
|
||||
ImGui::PopStyleColor(5);
|
||||
}
|
||||
//------SlicingProgressNotification
|
||||
void NotificationManager::SlicingProgressNotification::init()
|
||||
{
|
||||
|
@ -1739,59 +1596,6 @@ void NotificationManager::push_exporting_finished_notification(const std::string
|
|||
set_slicing_progress_hidden();
|
||||
}
|
||||
|
||||
void NotificationManager::push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage)
|
||||
{
|
||||
// find if upload with same id was not already in notification
|
||||
// done by compare_jon_id not compare_text thus has to be performed here
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::PrintHostUpload && dynamic_cast<PrintHostUploadNotification*>(notification.get())->compare_job_id(id)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::string text = PrintHostUploadNotification::get_upload_job_text(id, filename, host);
|
||||
NotificationData data{ NotificationType::PrintHostUpload, NotificationLevel::ProgressBarNotificationLevel, 10, text };
|
||||
push_notification_data(std::make_unique<NotificationManager::PrintHostUploadNotification>(data, m_id_provider, m_evt_handler, 0, id, filesize), 0);
|
||||
}
|
||||
void NotificationManager::set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage)
|
||||
{
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::PrintHostUpload) {
|
||||
PrintHostUploadNotification* phun = dynamic_cast<PrintHostUploadNotification*>(notification.get());
|
||||
if (phun->compare_job_id(id)) {
|
||||
phun->set_percentage(percentage);
|
||||
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void NotificationManager::upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host)
|
||||
{
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::PrintHostUpload) {
|
||||
PrintHostUploadNotification* phun = dynamic_cast<PrintHostUploadNotification*>(notification.get());
|
||||
if (phun->compare_job_id(id)) {
|
||||
phun->cancel();
|
||||
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void NotificationManager::upload_job_notification_show_error(int id, const std::string& filename, const std::string& host)
|
||||
{
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
if (notification->get_type() == NotificationType::PrintHostUpload) {
|
||||
PrintHostUploadNotification* phun = dynamic_cast<PrintHostUploadNotification*>(notification.get());
|
||||
if(phun->compare_job_id(id)) {
|
||||
phun->error();
|
||||
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotificationManager::init_slicing_progress_notification(std::function<bool()> cancel_callback)
|
||||
{
|
||||
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
|
||||
|
|
|
@ -182,11 +182,6 @@ public:
|
|||
void stop_delayed_notifications_of_type(const NotificationType type);
|
||||
// Creates Validate Error notification with a custom text and no fade out.
|
||||
void push_validate_error_notification(StringObjectException const & error);
|
||||
// print host upload
|
||||
void push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage = 0);
|
||||
void set_upload_job_notification_percentage(int id, const std::string& filename, const std::string& host, float percentage);
|
||||
void upload_job_notification_show_canceled(int id, const std::string& filename, const std::string& host);
|
||||
void upload_job_notification_show_error(int id, const std::string& filename, const std::string& host);
|
||||
// Creates Slicing Error notification with a custom text and no fade out.
|
||||
void push_slicing_error_notification(const std::string& text);
|
||||
// Creates Slicing Warning notification with a custom text and no fade out.
|
||||
|
@ -562,48 +557,6 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class PrintHostUploadNotification : public ProgressBarNotification
|
||||
{
|
||||
public:
|
||||
enum class UploadJobState
|
||||
{
|
||||
PB_PROGRESS,
|
||||
PB_ERROR,
|
||||
PB_CANCELLED,
|
||||
PB_COMPLETED
|
||||
};
|
||||
PrintHostUploadNotification(const NotificationData& n, NotificationIDProvider& id_provider, wxEvtHandler* evt_handler, float percentage, int job_id, float filesize)
|
||||
:ProgressBarNotification(n, id_provider, evt_handler)
|
||||
, m_job_id(job_id)
|
||||
, m_file_size(filesize)
|
||||
{
|
||||
m_has_cancel_button = true;
|
||||
set_percentage(percentage);
|
||||
}
|
||||
static std::string get_upload_job_text(int id, const std::string& filename, const std::string& host) { return /*"[" + std::to_string(id) + "] " + */filename + " -> " + host; }
|
||||
void set_percentage(float percent) override;
|
||||
void cancel() { m_uj_state = UploadJobState::PB_CANCELLED; m_has_cancel_button = false; }
|
||||
void error() { m_uj_state = UploadJobState::PB_ERROR; m_has_cancel_button = false; init(); }
|
||||
bool compare_job_id(const int other_id) const { return m_job_id == other_id; }
|
||||
bool compare_text(const std::string& text) const override { return false; }
|
||||
protected:
|
||||
void init() override;
|
||||
void count_spaces() override;
|
||||
bool push_background_color() override;
|
||||
void render_bar(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y) override;
|
||||
void render_cancel_button(ImGuiWrapper& imgui,
|
||||
const float win_size_x, const float win_size_y,
|
||||
const float win_pos_x, const float win_pos_y) override;
|
||||
void render_left_sign(ImGuiWrapper& imgui) override;
|
||||
// Identifies job in cancel callback
|
||||
int m_job_id;
|
||||
// Size of uploaded size to be displayed in MB
|
||||
float m_file_size;
|
||||
long m_hover_time{ 0 };
|
||||
UploadJobState m_uj_state{ UploadJobState::PB_PROGRESS };
|
||||
};
|
||||
class SlicingProgressNotification : public ProgressBarNotification
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1,746 +0,0 @@
|
|||
#include "PhysicalPrinterDialog.hpp"
|
||||
#include "PresetComboBoxes.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/wupdlock.h>
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "format.hpp"
|
||||
#include "Tab.hpp"
|
||||
#include "wxExtensions.hpp"
|
||||
#include "PrintHostDialogs.hpp"
|
||||
#include "../Utils/ASCIIFolding.hpp"
|
||||
#include "../Utils/PrintHost.hpp"
|
||||
#include "../Utils/FixModelByWin10.hpp"
|
||||
#include "../Utils/UndoRedo.hpp"
|
||||
#include "RemovableDriveManager.hpp"
|
||||
#include "BitmapCache.hpp"
|
||||
#include "BonjourDialog.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
#define BORDER_W 10
|
||||
|
||||
//------------------------------------------
|
||||
// PresetForPrinter
|
||||
//------------------------------------------
|
||||
|
||||
PresetForPrinter::PresetForPrinter(PhysicalPrinterDialog* parent, const std::string& preset_name) :
|
||||
m_parent(parent)
|
||||
{
|
||||
m_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_delete_preset_btn = new ScalableButton(parent, wxID_ANY, "cross");
|
||||
m_delete_preset_btn->SetFont(wxGetApp().normal_font());
|
||||
m_delete_preset_btn->SetToolTip(_L("Delete this preset from this printer device"));
|
||||
m_delete_preset_btn->Bind(wxEVT_BUTTON, &PresetForPrinter::DeletePreset, this);
|
||||
|
||||
m_presets_list = new PresetComboBox(parent, Preset::TYPE_PRINTER);
|
||||
m_presets_list->set_printer_technology(parent->get_printer_technology());
|
||||
|
||||
m_presets_list->set_selection_changed_function([this](int selection) {
|
||||
std::string selected_string = Preset::remove_suffix_modified(m_presets_list->GetString(selection).ToUTF8().data());
|
||||
Preset* preset = wxGetApp().preset_bundle->printers.find_preset(selected_string);
|
||||
assert(preset);
|
||||
Preset& edited_preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
||||
if (preset->name == edited_preset.name)
|
||||
preset = &edited_preset;
|
||||
|
||||
// // if created physical printer doesn't have any settings, use the settings from the selected preset
|
||||
// if (m_parent->get_printer()->has_empty_config()) {
|
||||
// // update Print Host upload from the selected preset
|
||||
// m_parent->get_printer()->update_from_preset(*preset);
|
||||
// // update values in parent (PhysicalPrinterDialog)
|
||||
// m_parent->update(true);
|
||||
|
||||
// }
|
||||
|
||||
// update PrinterTechnology if it was changed
|
||||
if (m_presets_list->set_printer_technology(preset->printer_technology()))
|
||||
m_parent->set_printer_technology(preset->printer_technology());
|
||||
|
||||
update_full_printer_name();
|
||||
});
|
||||
m_presets_list->update(preset_name);
|
||||
|
||||
m_info_line = new wxStaticText(parent, wxID_ANY, _L("This printer will be shown in the presets list as") + ":");
|
||||
|
||||
m_full_printer_name = new wxStaticText(parent, wxID_ANY, "");
|
||||
m_full_printer_name->SetFont(wxGetApp().bold_font());
|
||||
|
||||
wxBoxSizer* preset_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
preset_sizer->Add(m_presets_list , 1, wxEXPAND);
|
||||
preset_sizer->Add(m_delete_preset_btn , 0, wxEXPAND | wxLEFT, BORDER_W);
|
||||
|
||||
wxBoxSizer* name_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
name_sizer->Add(m_info_line, 0, wxEXPAND);
|
||||
name_sizer->Add(m_full_printer_name, 0, wxEXPAND | wxLEFT, BORDER_W);
|
||||
|
||||
m_sizer->Add(preset_sizer , 0, wxEXPAND);
|
||||
m_sizer->Add(name_sizer, 0, wxEXPAND);
|
||||
}
|
||||
|
||||
PresetForPrinter::~PresetForPrinter()
|
||||
{
|
||||
m_presets_list->Destroy();
|
||||
m_delete_preset_btn->Destroy();
|
||||
m_info_line->Destroy();
|
||||
m_full_printer_name->Destroy();
|
||||
}
|
||||
|
||||
void PresetForPrinter::DeletePreset(wxEvent& event)
|
||||
{
|
||||
m_parent->DeletePreset(this);
|
||||
}
|
||||
|
||||
void PresetForPrinter::update_full_printer_name()
|
||||
{
|
||||
wxString printer_name = m_parent->get_printer_name();
|
||||
wxString preset_name = m_presets_list->GetString(m_presets_list->GetSelection());
|
||||
|
||||
m_full_printer_name->SetLabelText(printer_name + " * " + preset_name);
|
||||
}
|
||||
|
||||
std::string PresetForPrinter::get_preset_name()
|
||||
{
|
||||
return into_u8(m_presets_list->GetString(m_presets_list->GetSelection()));
|
||||
}
|
||||
|
||||
void PresetForPrinter::SuppressDelete()
|
||||
{
|
||||
m_delete_preset_btn->Enable(false);
|
||||
|
||||
// this case means that now we have only one related preset for the printer
|
||||
// So, allow any selection
|
||||
m_presets_list->set_printer_technology(ptAny);
|
||||
m_presets_list->update();
|
||||
}
|
||||
|
||||
void PresetForPrinter::AllowDelete()
|
||||
{
|
||||
if (!m_delete_preset_btn->IsEnabled())
|
||||
m_delete_preset_btn->Enable();
|
||||
|
||||
m_presets_list->set_printer_technology(m_parent->get_printer_technology());
|
||||
m_presets_list->update();
|
||||
}
|
||||
|
||||
void PresetForPrinter::msw_rescale()
|
||||
{
|
||||
m_presets_list->msw_rescale();
|
||||
m_delete_preset_btn->msw_rescale();
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------
|
||||
// PhysicalPrinterDialog
|
||||
//------------------------------------------
|
||||
|
||||
PhysicalPrinterDialog::PhysicalPrinterDialog(wxWindow* parent, wxString printer_name) :
|
||||
DPIDialog(parent, wxID_ANY, _L("Physical Printer"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), -1), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER),
|
||||
m_printer("", wxGetApp().preset_bundle->physical_printers.default_config()),
|
||||
had_all_mk3(!printer_name.empty())
|
||||
{
|
||||
SetFont(wxGetApp().normal_font());
|
||||
#ifndef _WIN32
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
#endif
|
||||
m_default_name = _L("Type here the name of your printer device");
|
||||
bool new_printer = true;
|
||||
|
||||
if (printer_name.IsEmpty())
|
||||
printer_name = m_default_name;
|
||||
else {
|
||||
std::string full_name = into_u8(printer_name);
|
||||
printer_name = from_u8(PhysicalPrinter::get_short_name(full_name));
|
||||
new_printer = false;
|
||||
}
|
||||
|
||||
wxStaticText* label_top = new wxStaticText(this, wxID_ANY, _L("Descriptive name for the printer") + ":");
|
||||
|
||||
m_add_preset_btn = new ScalableButton(this, wxID_ANY, "add_copies");
|
||||
m_add_preset_btn->SetFont(wxGetApp().normal_font());
|
||||
m_add_preset_btn->SetToolTip(_L("Add preset for this printer device"));
|
||||
m_add_preset_btn->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::AddPreset, this);
|
||||
|
||||
m_printer_name = new wxTextCtrl(this, wxID_ANY, printer_name, wxDefaultPosition, wxDefaultSize);
|
||||
wxGetApp().UpdateDarkUI(m_printer_name);
|
||||
m_printer_name->Bind(wxEVT_TEXT, [this](wxEvent&) { this->update_full_printer_names(); });
|
||||
|
||||
PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers;
|
||||
PhysicalPrinter* printer = printers.find_printer(into_u8(printer_name));
|
||||
if (!printer) {
|
||||
const Preset& preset = wxGetApp().preset_bundle->printers.get_edited_preset();
|
||||
m_printer = PhysicalPrinter(into_u8(printer_name), m_printer.config, preset);
|
||||
// if printer_name is empty it means that new printer is created, so enable all items in the preset list
|
||||
m_presets.emplace_back(new PresetForPrinter(this, preset.name));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_printer = *printer;
|
||||
const std::set<std::string>& preset_names = printer->get_preset_names();
|
||||
for (const std::string& preset_name : preset_names)
|
||||
m_presets.emplace_back(new PresetForPrinter(this, preset_name));
|
||||
}
|
||||
|
||||
if (m_presets.size() == 1)
|
||||
m_presets.front()->SuppressDelete();
|
||||
|
||||
update_full_printer_names();
|
||||
|
||||
m_config = &m_printer.config;
|
||||
m_config = &wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
m_optgroup = new ConfigOptionsGroup(this, _L("Print Host upload"), m_config);
|
||||
build_printhost_settings(m_optgroup);
|
||||
|
||||
wxStdDialogButtonSizer* btns = this->CreateStdDialogButtonSizer(wxOK | wxCANCEL);
|
||||
wxButton* btnOK = static_cast<wxButton*>(this->FindWindowById(wxID_OK, this));
|
||||
wxGetApp().UpdateDarkUI(btnOK);
|
||||
btnOK->Bind(wxEVT_BUTTON, &PhysicalPrinterDialog::OnOK, this);
|
||||
|
||||
wxGetApp().UpdateDarkUI(static_cast<wxButton*>(this->FindWindowById(wxID_CANCEL, this)));
|
||||
|
||||
wxBoxSizer* nameSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
nameSizer->Add(m_printer_name, 1, wxEXPAND);
|
||||
nameSizer->Add(m_add_preset_btn, 0, wxEXPAND | wxLEFT, BORDER_W);
|
||||
|
||||
m_presets_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
for (PresetForPrinter* preset : m_presets)
|
||||
m_presets_sizer->Add(preset->sizer(), 1, wxEXPAND | wxTOP, BORDER_W);
|
||||
|
||||
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
topSizer->Add(label_top , 0, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W);
|
||||
topSizer->Add(nameSizer , 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W);
|
||||
topSizer->Add(m_presets_sizer , 0, wxEXPAND | wxLEFT | wxRIGHT, BORDER_W);
|
||||
topSizer->Add(m_optgroup->sizer , 1, wxEXPAND | wxLEFT | wxTOP | wxRIGHT, BORDER_W);
|
||||
topSizer->Add(btns , 0, wxEXPAND | wxALL, BORDER_W);
|
||||
|
||||
SetSizer(topSizer);
|
||||
topSizer->SetSizeHints(this);
|
||||
|
||||
if (new_printer) {
|
||||
m_printer_name->SetFocus();
|
||||
m_printer_name->SelectAll();
|
||||
}
|
||||
|
||||
this->CenterOnScreen();
|
||||
}
|
||||
|
||||
PhysicalPrinterDialog::~PhysicalPrinterDialog()
|
||||
{
|
||||
for (PresetForPrinter* preset : m_presets) {
|
||||
delete preset;
|
||||
preset = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update_printers()
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
|
||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||
|
||||
wxArrayString printers;
|
||||
Field *rs = m_optgroup->get_field("printhost_port");
|
||||
try {
|
||||
if (! host->get_printers(printers))
|
||||
printers.clear();
|
||||
} catch (const HostNetworkError &err) {
|
||||
printers.clear();
|
||||
show_error(this, _L("Connection to printers connected via the print host failed.") + "\n\n" + from_u8(err.what()));
|
||||
}
|
||||
Choice *choice = dynamic_cast<Choice*>(rs);
|
||||
choice->set_values(printers);
|
||||
printers.empty() ? rs->disable() : rs->enable();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::build_printhost_settings(ConfigOptionsGroup* m_optgroup)
|
||||
{
|
||||
m_optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
if (opt_key == "host_type" || opt_key == "printhost_authorization_type")
|
||||
this->update();
|
||||
if (opt_key == "print_host")
|
||||
this->update_printhost_buttons();
|
||||
};
|
||||
|
||||
m_optgroup->append_single_option_line("host_type");
|
||||
|
||||
auto create_sizer_with_btn = [](wxWindow* parent, ScalableButton** btn, const std::string& icon_name, const wxString& label) {
|
||||
*btn = new ScalableButton(parent, wxID_ANY, icon_name, label, wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT);
|
||||
(*btn)->SetFont(wxGetApp().normal_font());
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(*btn);
|
||||
return sizer;
|
||||
};
|
||||
|
||||
auto printhost_browse = [=](wxWindow* parent)
|
||||
{
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_browse_btn, "browse", _L("Browse") + " " + dots);
|
||||
m_printhost_browse_btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent& e) {
|
||||
BonjourDialog dialog(this, Preset::printer_technology(m_printer.config));
|
||||
if (dialog.show_and_lookup()) {
|
||||
m_optgroup->set_value("print_host", dialog.get_selected(), true);
|
||||
m_optgroup->get_field("print_host")->field_changed();
|
||||
}
|
||||
});
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
auto print_host_test = [=](wxWindow* parent) {
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_test_btn, "test", _L("Test"));
|
||||
|
||||
m_printhost_test_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
|
||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||
if (!host) {
|
||||
const wxString text = _L("Could not get a valid Printer Host reference");
|
||||
show_error(this, text);
|
||||
return;
|
||||
}
|
||||
wxString msg;
|
||||
bool result;
|
||||
{
|
||||
// Show a wait cursor during the connection test, as it is blocking UI.
|
||||
wxBusyCursor wait;
|
||||
result = host->test(msg);
|
||||
}
|
||||
if (result)
|
||||
show_info(this, host->get_test_ok_msg(), _L("Success!"));
|
||||
else
|
||||
show_error(this, host->get_test_failed_msg(msg));
|
||||
});
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
auto print_host_printers = [this, create_sizer_with_btn](wxWindow* parent) {
|
||||
//add_scaled_button(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers")), wxBU_LEFT | wxBU_EXACTFIT);
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers")));
|
||||
ScalableButton* btn = m_printhost_port_browse_btn;
|
||||
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) { update_printers(); });
|
||||
return sizer;
|
||||
};
|
||||
|
||||
// Set a wider width for a better alignment
|
||||
Option option = m_optgroup->get_option("print_host");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line host_line = m_optgroup->create_single_option_line(option);
|
||||
host_line.append_widget(printhost_browse);
|
||||
host_line.append_widget(print_host_test);
|
||||
m_optgroup->append_line(host_line);
|
||||
|
||||
m_optgroup->append_single_option_line("printhost_authorization_type");
|
||||
|
||||
option = m_optgroup->get_option("printhost_apikey");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
m_optgroup->append_single_option_line(option);
|
||||
|
||||
option = m_optgroup->get_option("printhost_port");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line port_line = m_optgroup->create_single_option_line(option);
|
||||
port_line.append_widget(print_host_printers);
|
||||
m_optgroup->append_line(port_line);
|
||||
|
||||
const auto ca_file_hint = _u8L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate.");
|
||||
|
||||
if (Http::ca_file_supported()) {
|
||||
option = m_optgroup->get_option("printhost_cafile");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line cafile_line = m_optgroup->create_single_option_line(option);
|
||||
|
||||
auto printhost_cafile_browse = [=](wxWindow* parent) {
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_cafile_browse_btn, "browse", _L("Browse") + " " + dots);
|
||||
m_printhost_cafile_browse_btn->Bind(wxEVT_BUTTON, [this, m_optgroup](wxCommandEvent e) {
|
||||
static const auto filemasks = _L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*");
|
||||
wxFileDialog openFileDialog(this, _L("Open CA certificate file"), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (openFileDialog.ShowModal() != wxID_CANCEL) {
|
||||
m_optgroup->set_value("printhost_cafile", openFileDialog.GetPath(), true);
|
||||
m_optgroup->get_field("printhost_cafile")->field_changed();
|
||||
}
|
||||
});
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
cafile_line.append_widget(printhost_cafile_browse);
|
||||
m_optgroup->append_line(cafile_line);
|
||||
|
||||
Line cafile_hint{ "", "" };
|
||||
cafile_hint.full_width = 1;
|
||||
cafile_hint.widget = [ca_file_hint](wxWindow* parent) {
|
||||
auto txt = new wxStaticText(parent, wxID_ANY, ca_file_hint);
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(txt);
|
||||
return sizer;
|
||||
};
|
||||
m_optgroup->append_line(cafile_hint);
|
||||
}
|
||||
else {
|
||||
|
||||
Line line{ "", "" };
|
||||
line.full_width = 1;
|
||||
|
||||
line.widget = [ca_file_hint](wxWindow* parent) {
|
||||
std::string info = _u8L("HTTPS CA File") + ":\n\t" +
|
||||
(boost::format(_u8L("On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.")) % SLIC3R_APP_NAME).str() +
|
||||
"\n\t" + _u8L("To use a custom CA file, please import your CA file into Certificate Store / Keychain.");
|
||||
|
||||
//auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\n\t%2%") % info % ca_file_hint).str()));
|
||||
auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\t%2%") % info % ca_file_hint).str()));
|
||||
txt->SetFont(wxGetApp().normal_font());
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(txt, 1, wxEXPAND);
|
||||
return sizer;
|
||||
};
|
||||
m_optgroup->append_line(line);
|
||||
}
|
||||
|
||||
for (const std::string& opt_key : std::vector<std::string>{ "printhost_user", "printhost_password" }) {
|
||||
option = m_optgroup->get_option(opt_key);
|
||||
option.opt.width = Field::def_width_wider();
|
||||
m_optgroup->append_single_option_line(option);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
option = m_optgroup->get_option("printhost_ssl_ignore_revoke");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
m_optgroup->append_single_option_line(option);
|
||||
#endif
|
||||
|
||||
m_optgroup->activate();
|
||||
|
||||
Field* printhost_field = m_optgroup->get_field("print_host");
|
||||
if (printhost_field)
|
||||
{
|
||||
wxTextCtrl* temp = dynamic_cast<wxTextCtrl*>(printhost_field->getWindow());
|
||||
if (temp)
|
||||
temp->Bind(wxEVT_TEXT, ([printhost_field, temp](wxEvent& e)
|
||||
{
|
||||
#ifndef __WXGTK__
|
||||
e.Skip();
|
||||
temp->GetToolTip()->Enable(true);
|
||||
#endif // __WXGTK__
|
||||
// Remove all leading and trailing spaces from the input
|
||||
std::string trimed_str, str = trimed_str = temp->GetValue().ToStdString();
|
||||
boost::trim(trimed_str);
|
||||
if (trimed_str != str)
|
||||
temp->SetValue(trimed_str);
|
||||
|
||||
TextCtrl* field = dynamic_cast<TextCtrl*>(printhost_field);
|
||||
if (field)
|
||||
field->propagate_value();
|
||||
}), temp->GetId());
|
||||
}
|
||||
|
||||
// Always fill in the "printhost_port" combo box from the config and select it.
|
||||
{
|
||||
Choice* choice = dynamic_cast<Choice*>(m_optgroup->get_field("printhost_port"));
|
||||
choice->set_values({ m_config->opt_string("printhost_port") });
|
||||
choice->set_selection();
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update_printhost_buttons()
|
||||
{
|
||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||
m_printhost_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test());
|
||||
m_printhost_browse_btn->Enable(host->has_auto_discovery());
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update(bool printer_change)
|
||||
{
|
||||
m_optgroup->reload_config();
|
||||
|
||||
const PrinterTechnology tech = Preset::printer_technology(*m_config);
|
||||
// Only offer the host type selection for FFF, for SLA it's always the SL1 printer (at the moment)
|
||||
bool supports_multiple_printers = false;
|
||||
if (tech == ptFFF) {
|
||||
update_host_type(printer_change);
|
||||
const auto opt = m_config->option<ConfigOptionEnum<PrintHostType>>("host_type");
|
||||
m_optgroup->show_field("host_type");
|
||||
if (opt->value == htPrusaLink)
|
||||
{
|
||||
m_optgroup->show_field("printhost_authorization_type");
|
||||
AuthorizationType auth_type = m_config->option<ConfigOptionEnum<AuthorizationType>>("printhost_authorization_type")->value;
|
||||
m_optgroup->show_field("printhost_apikey", auth_type == AuthorizationType::atKeyPassword);
|
||||
for (const char* opt_key : { "printhost_user", "printhost_password" })
|
||||
m_optgroup->show_field(opt_key, auth_type == AuthorizationType::atUserPassword);
|
||||
} else {
|
||||
m_optgroup->hide_field("printhost_authorization_type");
|
||||
m_optgroup->show_field("printhost_apikey", true);
|
||||
for (const std::string& opt_key : std::vector<std::string>{ "printhost_user", "printhost_password" })
|
||||
m_optgroup->hide_field(opt_key);
|
||||
supports_multiple_printers = opt && opt->value == htRepetier;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
m_optgroup->set_value("host_type", int(PrintHostType::htOctoPrint), false);
|
||||
m_optgroup->hide_field("host_type");
|
||||
|
||||
m_optgroup->show_field("printhost_authorization_type");
|
||||
|
||||
AuthorizationType auth_type = m_config->option<ConfigOptionEnum<AuthorizationType>>("printhost_authorization_type")->value;
|
||||
m_optgroup->show_field("printhost_apikey", auth_type == AuthorizationType::atKeyPassword);
|
||||
|
||||
for (const char *opt_key : { "printhost_user", "printhost_password" })
|
||||
m_optgroup->show_field(opt_key, auth_type == AuthorizationType::atUserPassword);
|
||||
}
|
||||
|
||||
m_optgroup->show_field("printhost_port", supports_multiple_printers);
|
||||
m_printhost_port_browse_btn->Show(supports_multiple_printers);
|
||||
|
||||
update_printhost_buttons();
|
||||
|
||||
this->SetSize(this->GetBestSize());
|
||||
this->Layout();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update_host_type(bool printer_change)
|
||||
{
|
||||
if (m_presets.empty())
|
||||
return;
|
||||
bool all_presets_are_from_mk3_family = true;
|
||||
|
||||
for (PresetForPrinter* prstft : m_presets) {
|
||||
std::string preset_name = prstft->get_preset_name();
|
||||
if (Preset* preset = wxGetApp().preset_bundle->printers.find_preset(preset_name)) {
|
||||
std::string model_id = preset->config.opt_string("printer_model");
|
||||
auto model_supports_prusalink = [](const std::string &model) {
|
||||
return model.size() >= 3 &&
|
||||
((boost::starts_with(model, "MK") && model[2] > '2' && model[2] <= '9') ||
|
||||
boost::starts_with(model, "MINI"));
|
||||
};
|
||||
if (preset->vendor) {
|
||||
if (preset->vendor->name == "Prusa Research") {
|
||||
const std::vector<VendorProfile::PrinterModel>& models = preset->vendor->models;
|
||||
auto it = std::find_if(models.begin(), models.end(),
|
||||
[model_id](const VendorProfile::PrinterModel& model) { return model.id == model_id; });
|
||||
if (it != models.end() && model_supports_prusalink(it->family))
|
||||
continue;
|
||||
}
|
||||
} else if (model_supports_prusalink(model_id))
|
||||
continue;
|
||||
}
|
||||
all_presets_are_from_mk3_family = false;
|
||||
break;
|
||||
}
|
||||
|
||||
Field* ht = m_optgroup->get_field("host_type");
|
||||
|
||||
wxArrayString types;
|
||||
// Append localized enum_labels
|
||||
assert(ht->m_opt.enum_labels.size() == ht->m_opt.enum_values.size());
|
||||
for (size_t i = 0; i < ht->m_opt.enum_labels.size(); i++) {
|
||||
if (ht->m_opt.enum_values[i] == "prusalink" && !all_presets_are_from_mk3_family)
|
||||
continue;
|
||||
types.Add(_(ht->m_opt.enum_labels[i]));
|
||||
}
|
||||
|
||||
Choice* choice = dynamic_cast<Choice*>(ht);
|
||||
choice->set_values(types);
|
||||
auto set_to_choice_and_config = [this, choice](PrintHostType type) {
|
||||
choice->set_value(static_cast<int>(type));
|
||||
m_config->set_key_value("host_type", new ConfigOptionEnum<PrintHostType>(type));
|
||||
};
|
||||
if ((printer_change && all_presets_are_from_mk3_family) || (!had_all_mk3 && all_presets_are_from_mk3_family))
|
||||
set_to_choice_and_config(htPrusaLink);
|
||||
else if ((printer_change && !all_presets_are_from_mk3_family) || (!all_presets_are_from_mk3_family && m_config->option<ConfigOptionEnum<PrintHostType>>("host_type")->value == htPrusaLink))
|
||||
set_to_choice_and_config(htOctoPrint);
|
||||
else
|
||||
choice->set_value(m_config->option("host_type")->getInt());
|
||||
had_all_mk3 = all_presets_are_from_mk3_family;
|
||||
}
|
||||
|
||||
|
||||
wxString PhysicalPrinterDialog::get_printer_name()
|
||||
{
|
||||
return m_printer_name->GetValue();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::update_full_printer_names()
|
||||
{
|
||||
for (PresetForPrinter* preset : m_presets)
|
||||
preset->update_full_printer_name();
|
||||
|
||||
this->Layout();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::set_printer_technology(PrinterTechnology pt)
|
||||
{
|
||||
m_config->set_key_value("printer_technology", new ConfigOptionEnum<PrinterTechnology>(pt));
|
||||
update();
|
||||
}
|
||||
|
||||
PrinterTechnology PhysicalPrinterDialog::get_printer_technology()
|
||||
{
|
||||
return m_printer.printer_technology();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
{
|
||||
const int& em = em_unit();
|
||||
|
||||
m_add_preset_btn->msw_rescale();
|
||||
m_printhost_browse_btn->msw_rescale();
|
||||
m_printhost_test_btn->msw_rescale();
|
||||
if (m_printhost_cafile_browse_btn)
|
||||
m_printhost_cafile_browse_btn->msw_rescale();
|
||||
|
||||
m_optgroup->msw_rescale();
|
||||
|
||||
msw_buttons_rescale(this, em, { wxID_OK, wxID_CANCEL });
|
||||
|
||||
for (PresetForPrinter* preset : m_presets)
|
||||
preset->msw_rescale();
|
||||
|
||||
const wxSize& size = wxSize(45 * em, 35 * em);
|
||||
SetMinSize(size);
|
||||
|
||||
Fit();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::OnOK(wxEvent& event)
|
||||
{
|
||||
wxString printer_name = m_printer_name->GetValue();
|
||||
if (printer_name.IsEmpty()) {
|
||||
warning_catcher(this, _L("The supplied name is empty. It can't be saved."));
|
||||
return;
|
||||
}
|
||||
if (printer_name == m_default_name) {
|
||||
warning_catcher(this, _L("You should change the name of your printer device."));
|
||||
return;
|
||||
}
|
||||
|
||||
PhysicalPrinterCollection& printers = wxGetApp().preset_bundle->physical_printers;
|
||||
const PhysicalPrinter* existing = printers.find_printer(into_u8(printer_name), false);
|
||||
if (existing && into_u8(printer_name) != printers.get_selected_printer_name())
|
||||
{
|
||||
wxString msg_text = from_u8((boost::format(_u8L("Printer with name \"%1%\" already exists.")) % existing->name/*printer_name*/).str());
|
||||
msg_text += "\n" + _L("Replace?");
|
||||
//wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
MessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
|
||||
if (dialog.ShowModal() == wxID_NO)
|
||||
return;
|
||||
|
||||
m_printer.name = existing->name;
|
||||
}
|
||||
|
||||
std::set<std::string> repeat_presets;
|
||||
m_printer.reset_presets();
|
||||
for (PresetForPrinter* preset : m_presets) {
|
||||
if (!m_printer.add_preset(preset->get_preset_name()))
|
||||
repeat_presets.emplace(preset->get_preset_name());
|
||||
}
|
||||
|
||||
if (!repeat_presets.empty())
|
||||
{
|
||||
wxString repeatable_presets = "\n";
|
||||
int repeat_cnt = 0;
|
||||
for (const std::string& preset_name : repeat_presets) {
|
||||
repeatable_presets += " " + from_u8(preset_name) + "\n";
|
||||
repeat_cnt++;
|
||||
}
|
||||
repeatable_presets += "\n";
|
||||
|
||||
wxString msg_text = format_wxstr(_L_PLURAL("Following printer preset is duplicated:%1%"
|
||||
"The above preset for printer \"%2%\" will be used just once.",
|
||||
"Following printer presets are duplicated:%1%"
|
||||
"The above presets for printer \"%2%\" will be used just once.", repeat_cnt), repeatable_presets, printer_name);
|
||||
//wxMessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxOK | wxCANCEL);
|
||||
MessageDialog dialog(nullptr, msg_text, _L("Warning"), wxICON_WARNING | wxOK | wxCANCEL);
|
||||
if (dialog.ShowModal() == wxID_CANCEL)
|
||||
return;
|
||||
}
|
||||
|
||||
std::string renamed_from;
|
||||
// temporary save previous printer name if it was edited
|
||||
if (m_printer.name != into_u8(m_default_name) &&
|
||||
m_printer.name != into_u8(printer_name))
|
||||
renamed_from = m_printer.name;
|
||||
|
||||
//update printer name, if it was changed
|
||||
m_printer.set_name(into_u8(printer_name));
|
||||
|
||||
// save new physical printer
|
||||
printers.save_printer(m_printer, renamed_from);
|
||||
|
||||
if (m_printer.preset_names.find(printers.get_selected_printer_preset_name()) == m_printer.preset_names.end()) {
|
||||
// select first preset for this printer
|
||||
printers.select_printer(m_printer);
|
||||
// refresh preset list on Printer Settings Tab
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINTER)->select_preset(printers.get_selected_printer_preset_name());
|
||||
}
|
||||
else
|
||||
wxGetApp().get_tab(Preset::TYPE_PRINTER)->update_preset_choice();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::AddPreset(wxEvent& event)
|
||||
{
|
||||
m_presets.emplace_back(new PresetForPrinter(this));
|
||||
// enable DELETE button for the first preset, if was disabled
|
||||
m_presets.front()->AllowDelete();
|
||||
|
||||
m_presets_sizer->Add(m_presets.back()->sizer(), 1, wxEXPAND | wxTOP, BORDER_W);
|
||||
update_full_printer_names();
|
||||
this->Fit();
|
||||
|
||||
update_host_type(true);
|
||||
}
|
||||
|
||||
void PhysicalPrinterDialog::DeletePreset(PresetForPrinter* preset_for_printer)
|
||||
{
|
||||
if (m_presets.size() == 1) {
|
||||
wxString msg_text = _L("It's not possible to delete the last related preset for the printer.");
|
||||
//wxMessageDialog dialog(nullptr, msg_text, _L("Information"), wxICON_INFORMATION | wxOK);
|
||||
MessageDialog dialog(nullptr, msg_text, _L("Information"), wxICON_INFORMATION | wxOK);
|
||||
dialog.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
||||
assert(preset_for_printer);
|
||||
auto it = std::find(m_presets.begin(), m_presets.end(), preset_for_printer);
|
||||
if (it == m_presets.end())
|
||||
return;
|
||||
|
||||
const int remove_id = it - m_presets.begin();
|
||||
m_presets_sizer->Remove(remove_id);
|
||||
delete preset_for_printer;
|
||||
m_presets.erase(it);
|
||||
|
||||
if (m_presets.size() == 1)
|
||||
m_presets.front()->SuppressDelete();
|
||||
|
||||
this->Layout();
|
||||
this->Fit();
|
||||
|
||||
update_host_type(true);
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::GUI
|
|
@ -1,111 +0,0 @@
|
|||
#ifndef slic3r_PhysicalPrinterDialog_hpp_
|
||||
#define slic3r_PhysicalPrinterDialog_hpp_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <wx/gdicmn.h>
|
||||
|
||||
#include "libslic3r/Preset.hpp"
|
||||
#include "GUI_Utils.hpp"
|
||||
|
||||
class wxString;
|
||||
class wxTextCtrl;
|
||||
class wxStaticText;
|
||||
class ScalableButton;
|
||||
class wxBoxSizer;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class PresetComboBox;
|
||||
|
||||
//------------------------------------------
|
||||
// PresetForPrinter
|
||||
//------------------------------------------
|
||||
//static std::string g_info_string = " (modified)";
|
||||
class PhysicalPrinterDialog;
|
||||
class PresetForPrinter
|
||||
{
|
||||
PhysicalPrinterDialog* m_parent { nullptr };
|
||||
|
||||
PresetComboBox* m_presets_list { nullptr };
|
||||
ScalableButton* m_delete_preset_btn { nullptr };
|
||||
wxStaticText* m_info_line { nullptr };
|
||||
wxStaticText* m_full_printer_name { nullptr };
|
||||
|
||||
wxBoxSizer* m_sizer { nullptr };
|
||||
|
||||
void DeletePreset(wxEvent& event);
|
||||
|
||||
public:
|
||||
PresetForPrinter(PhysicalPrinterDialog* parent, const std::string& preset_name = "");
|
||||
~PresetForPrinter();
|
||||
|
||||
wxBoxSizer* sizer() { return m_sizer; }
|
||||
void update_full_printer_name();
|
||||
std::string get_preset_name();
|
||||
void SuppressDelete();
|
||||
void AllowDelete();
|
||||
|
||||
void msw_rescale();
|
||||
void on_sys_color_changed() {};
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------
|
||||
// PhysicalPrinterDialog
|
||||
//------------------------------------------
|
||||
|
||||
class ConfigOptionsGroup;
|
||||
class PhysicalPrinterDialog : public DPIDialog
|
||||
{
|
||||
PhysicalPrinter m_printer;
|
||||
wxString m_default_name;
|
||||
DynamicPrintConfig* m_config { nullptr };
|
||||
|
||||
wxTextCtrl* m_printer_name { nullptr };
|
||||
std::vector<PresetForPrinter*> m_presets;
|
||||
|
||||
ConfigOptionsGroup* m_optgroup { nullptr };
|
||||
|
||||
ScalableButton* m_add_preset_btn {nullptr};
|
||||
ScalableButton* m_printhost_browse_btn {nullptr};
|
||||
ScalableButton* m_printhost_test_btn {nullptr};
|
||||
ScalableButton* m_printhost_cafile_browse_btn {nullptr};
|
||||
ScalableButton* m_printhost_client_cert_browse_btn {nullptr};
|
||||
ScalableButton* m_printhost_port_browse_btn {nullptr};
|
||||
|
||||
wxBoxSizer* m_presets_sizer {nullptr};
|
||||
|
||||
void build_printhost_settings(ConfigOptionsGroup* optgroup);
|
||||
void OnOK(wxEvent& event);
|
||||
void AddPreset(wxEvent& event);
|
||||
|
||||
public:
|
||||
PhysicalPrinterDialog(wxWindow* parent, wxString printer_name);
|
||||
~PhysicalPrinterDialog();
|
||||
|
||||
void update(bool printer_change = false);
|
||||
void update_host_type(bool printer_change);
|
||||
void update_printhost_buttons();
|
||||
void update_printers();
|
||||
wxString get_printer_name();
|
||||
void update_full_printer_names();
|
||||
PhysicalPrinter* get_printer() {return &m_printer; }
|
||||
void set_printer_technology(PrinterTechnology pt);
|
||||
PrinterTechnology get_printer_technology();
|
||||
|
||||
void DeletePreset(PresetForPrinter* preset_for_printer);
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect& suggested_rect) override;
|
||||
void on_sys_color_changed() override {};
|
||||
|
||||
bool had_all_mk3;
|
||||
};
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif
|
|
@ -124,8 +124,6 @@
|
|||
#include "libslic3r/Platform.hpp"
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include "PhysicalPrinterDialog.hpp"
|
||||
|
||||
using boost::optional;
|
||||
namespace fs = boost::filesystem;
|
||||
using Slic3r::_3DScene;
|
||||
|
@ -505,26 +503,12 @@ Sidebar::Sidebar(Plater *parent)
|
|||
combo_printer->edit_btn = edit_btn;
|
||||
p->combo_printer = combo_printer;
|
||||
|
||||
ScalableButton* connection_btn = new ScalableButton(p->m_panel_printer_content, wxID_ANY, "printer");
|
||||
connection_btn->SetBackgroundColour(wxColour(255, 255, 255));
|
||||
connection_btn->SetToolTip(_L("Print connection"));
|
||||
connection_btn->Bind(wxEVT_BUTTON, [this, combo_printer](wxCommandEvent)
|
||||
{
|
||||
auto preset_name = into_u8(combo_printer->GetString(combo_printer->GetSelection()));
|
||||
auto printer_name = from_u8(PhysicalPrinter::get_short_name(preset_name)+"-printer");
|
||||
PhysicalPrinterDialog dlg(this->GetParent(),printer_name);
|
||||
dlg.ShowModal();
|
||||
// wxMessageBox("Connection support WIP", "INFO", wxOK | wxICON_INFORMATION);
|
||||
});
|
||||
|
||||
wxBoxSizer *vsizer_printer = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer *hsizer_printer = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer* vsizer_printer = new wxBoxSizer(wxVERTICAL);
|
||||
wxBoxSizer* hsizer_printer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
hsizer_printer->Add(combo_printer, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
|
||||
hsizer_printer->Add(edit_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
|
||||
hsizer_printer->Add(FromDIP(8), 0, 0, 0, 0);
|
||||
hsizer_printer->Add(connection_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, FromDIP(3));
|
||||
hsizer_printer->Add(FromDIP(8), 0, 0, 0, 0);
|
||||
vsizer_printer->Add(hsizer_printer, 0, wxEXPAND, 0);
|
||||
|
||||
// Bed type selection
|
||||
|
|
|
@ -1,520 +0,0 @@
|
|||
#include "PrintHostDialogs.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
#include <wx/frame.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/dataview.h>
|
||||
#include <wx/wupdlock.h>
|
||||
#include <wx/debug.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/nowide/convert.hpp>
|
||||
|
||||
#include "GUI.hpp"
|
||||
#include "GUI_App.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "I18N.hpp"
|
||||
#include "MainFrame.hpp"
|
||||
#include "libslic3r/AppConfig.hpp"
|
||||
#include "NotificationManager.hpp"
|
||||
#include "ExtraRenderers.hpp"
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
static const char *CONFIG_KEY_PATH = "printhost_path";
|
||||
static const char *CONFIG_KEY_GROUP = "printhost_group";
|
||||
|
||||
PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups)
|
||||
: MsgDialog(static_cast<wxWindow*>(wxGetApp().mainframe), _L("Send G-Code to printer host"), _L("Upload to Printer Host with the following filename:"))
|
||||
, txt_filename(new wxTextCtrl(this, wxID_ANY))
|
||||
, combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr)
|
||||
, post_upload_action(PrintHostPostUploadAction::None)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
txt_filename->OSXDisableAllSmartSubstitutions();
|
||||
#endif
|
||||
const AppConfig *app_config = wxGetApp().app_config;
|
||||
|
||||
auto *label_dir_hint = new wxStaticText(this, wxID_ANY, _L("Use forward slashes ( / ) as a directory separator if needed."));
|
||||
label_dir_hint->Wrap(CONTENT_WIDTH * wxGetApp().em_unit());
|
||||
|
||||
content_sizer->Add(txt_filename, 0, wxEXPAND);
|
||||
content_sizer->Add(label_dir_hint);
|
||||
content_sizer->AddSpacer(VERT_SPACING);
|
||||
|
||||
if (combo_groups != nullptr) {
|
||||
// Repetier specific: Show a selection of file groups.
|
||||
auto *label_group = new wxStaticText(this, wxID_ANY, _L("Group"));
|
||||
content_sizer->Add(label_group);
|
||||
content_sizer->Add(combo_groups, 0, wxBOTTOM, 2*VERT_SPACING);
|
||||
wxString recent_group = from_u8(app_config->get("recent", CONFIG_KEY_GROUP));
|
||||
if (! recent_group.empty())
|
||||
combo_groups->SetValue(recent_group);
|
||||
}
|
||||
|
||||
wxString recent_path = from_u8(app_config->get("recent", CONFIG_KEY_PATH));
|
||||
if (recent_path.Length() > 0 && recent_path[recent_path.Length() - 1] != '/') {
|
||||
recent_path += '/';
|
||||
}
|
||||
const auto recent_path_len = recent_path.Length();
|
||||
recent_path += path.filename().wstring();
|
||||
wxString stem(path.stem().wstring());
|
||||
const auto stem_len = stem.Length();
|
||||
|
||||
txt_filename->SetValue(recent_path);
|
||||
txt_filename->SetFocus();
|
||||
|
||||
m_valid_suffix = recent_path.substr(recent_path.find_last_of('.'));
|
||||
// .gcode suffix control
|
||||
auto validate_path = [this](const wxString &path) -> bool {
|
||||
if (! path.Lower().EndsWith(m_valid_suffix.Lower())) {
|
||||
MessageDialog msg_wingow(this, wxString::Format(_L("Upload filename doesn't end with \"%s\". Do you wish to continue?"), m_valid_suffix), wxString(SLIC3R_APP_NAME), wxYES | wxNO);
|
||||
if (msg_wingow.ShowModal() == wxID_NO)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (post_actions.has(PrintHostPostUploadAction::StartPrint)) {
|
||||
auto* btn_print = add_button(wxID_YES, false, _L("Upload and Print"));
|
||||
btn_print->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) {
|
||||
if (validate_path(txt_filename->GetValue())) {
|
||||
post_upload_action = PrintHostPostUploadAction::StartPrint;
|
||||
EndDialog(wxID_OK);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (post_actions.has(PrintHostPostUploadAction::StartSimulation)) {
|
||||
// Using wxID_MORE as a button identifier to be different from the other buttons, wxID_MORE has no other meaning here.
|
||||
auto* btn_simulate = add_button(wxID_MORE, false, _L("Upload and Simulate"));
|
||||
btn_simulate->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) {
|
||||
if (validate_path(txt_filename->GetValue())) {
|
||||
post_upload_action = PrintHostPostUploadAction::StartSimulation;
|
||||
EndDialog(wxID_OK);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
add_button(wxID_CANCEL);
|
||||
|
||||
if (auto* btn_ok = get_button(wxID_OK); btn_ok != NULL) {
|
||||
btn_ok->SetLabel(_L("Upload"));
|
||||
btn_ok->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) {
|
||||
if (validate_path(txt_filename->GetValue())) {
|
||||
post_upload_action = PrintHostPostUploadAction::None;
|
||||
EndDialog(wxID_OK);
|
||||
}
|
||||
});
|
||||
}
|
||||
finalize();
|
||||
|
||||
#ifdef __linux__
|
||||
// On Linux with GTK2 when text control lose the focus then selection (colored background) disappears but text color stay white
|
||||
// and as a result the text is invisible with light mode
|
||||
// see https://github.com/prusa3d/PrusaSlicer/issues/4532
|
||||
// Workaround: Unselect text selection explicitly on kill focus
|
||||
txt_filename->Bind(wxEVT_KILL_FOCUS, [this](wxEvent& e) {
|
||||
e.Skip();
|
||||
txt_filename->SetInsertionPoint(txt_filename->GetLastPosition());
|
||||
}, txt_filename->GetId());
|
||||
#endif /* __linux__ */
|
||||
|
||||
Bind(wxEVT_SHOW, [=](const wxShowEvent &) {
|
||||
// Another similar case where the function only works with EVT_SHOW + CallAfter,
|
||||
// this time on Mac.
|
||||
CallAfter([=]() {
|
||||
txt_filename->SetSelection(recent_path_len, recent_path_len + stem_len);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fs::path PrintHostSendDialog::filename() const
|
||||
{
|
||||
return into_path(txt_filename->GetValue());
|
||||
}
|
||||
|
||||
PrintHostPostUploadAction PrintHostSendDialog::post_action() const
|
||||
{
|
||||
return post_upload_action;
|
||||
}
|
||||
|
||||
std::string PrintHostSendDialog::group() const
|
||||
{
|
||||
if (combo_groups == nullptr) {
|
||||
return "";
|
||||
} else {
|
||||
wxString group = combo_groups->GetValue();
|
||||
return into_u8(group);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintHostSendDialog::EndModal(int ret)
|
||||
{
|
||||
if (ret == wxID_OK) {
|
||||
// Persist path and print settings
|
||||
wxString path = txt_filename->GetValue();
|
||||
int last_slash = path.Find('/', true);
|
||||
if (last_slash == wxNOT_FOUND)
|
||||
path.clear();
|
||||
else
|
||||
path = path.SubString(0, last_slash);
|
||||
|
||||
AppConfig *app_config = wxGetApp().app_config;
|
||||
app_config->set("recent", CONFIG_KEY_PATH, into_u8(path));
|
||||
|
||||
if (combo_groups != nullptr) {
|
||||
wxString group = combo_groups->GetValue();
|
||||
app_config->set("recent", CONFIG_KEY_GROUP, into_u8(group));
|
||||
}
|
||||
}
|
||||
|
||||
MsgDialog::EndModal(ret);
|
||||
}
|
||||
|
||||
|
||||
|
||||
wxDEFINE_EVENT(EVT_PRINTHOST_PROGRESS, PrintHostQueueDialog::Event);
|
||||
wxDEFINE_EVENT(EVT_PRINTHOST_ERROR, PrintHostQueueDialog::Event);
|
||||
wxDEFINE_EVENT(EVT_PRINTHOST_CANCEL, PrintHostQueueDialog::Event);
|
||||
|
||||
PrintHostQueueDialog::Event::Event(wxEventType eventType, int winid, size_t job_id)
|
||||
: wxEvent(winid, eventType)
|
||||
, job_id(job_id)
|
||||
{}
|
||||
|
||||
PrintHostQueueDialog::Event::Event(wxEventType eventType, int winid, size_t job_id, int progress)
|
||||
: wxEvent(winid, eventType)
|
||||
, job_id(job_id)
|
||||
, progress(progress)
|
||||
{}
|
||||
|
||||
PrintHostQueueDialog::Event::Event(wxEventType eventType, int winid, size_t job_id, wxString error)
|
||||
: wxEvent(winid, eventType)
|
||||
, job_id(job_id)
|
||||
, error(std::move(error))
|
||||
{}
|
||||
|
||||
wxEvent *PrintHostQueueDialog::Event::Clone() const
|
||||
{
|
||||
return new Event(*this);
|
||||
}
|
||||
|
||||
PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent)
|
||||
: DPIDialog(parent, wxID_ANY, _L("Print host upload queue"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER)
|
||||
, on_progress_evt(this, EVT_PRINTHOST_PROGRESS, &PrintHostQueueDialog::on_progress, this)
|
||||
, on_error_evt(this, EVT_PRINTHOST_ERROR, &PrintHostQueueDialog::on_error, this)
|
||||
, on_cancel_evt(this, EVT_PRINTHOST_CANCEL, &PrintHostQueueDialog::on_cancel, this)
|
||||
{
|
||||
const auto em = GetTextExtent("m").x;
|
||||
|
||||
auto *topsizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
std::vector<int> widths;
|
||||
widths.reserve(6);
|
||||
if (!load_user_data(UDT_COLS, widths)) {
|
||||
widths.clear();
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
widths.push_back(-1);
|
||||
}
|
||||
|
||||
job_list = new wxDataViewListCtrl(this, wxID_ANY);
|
||||
|
||||
// MSW DarkMode: workaround for the selected item in the list
|
||||
auto append_text_column = [this](const wxString& label, int width, wxAlignment align = wxALIGN_LEFT,
|
||||
int flags = wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE) {
|
||||
#ifdef _WIN32
|
||||
job_list->AppendColumn(new wxDataViewColumn(label, new TextRenderer(), job_list->GetColumnCount(), width, align, flags));
|
||||
#else
|
||||
job_list->AppendTextColumn(label, wxDATAVIEW_CELL_INERT, width, align, flags);
|
||||
#endif
|
||||
};
|
||||
|
||||
// Note: Keep these in sync with Column
|
||||
append_text_column(_L("ID"), widths[0]);
|
||||
job_list->AppendProgressColumn(_L("Progress"), wxDATAVIEW_CELL_INERT, widths[1], wxALIGN_LEFT, wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
|
||||
append_text_column(_L("Status"),widths[2]);
|
||||
append_text_column(_L("Host"), widths[3]);
|
||||
append_text_column(_CTX_utf8(L_CONTEXT("Size", "OfFile"), "OfFile"), widths[4]);
|
||||
append_text_column(_L("Filename"), widths[5]);
|
||||
append_text_column(_L("Error Message"), -1, wxALIGN_CENTER, wxDATAVIEW_COL_HIDDEN);
|
||||
|
||||
auto *btnsizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
btn_cancel = new wxButton(this, wxID_DELETE, _L("Cancel selected"));
|
||||
btn_cancel->Disable();
|
||||
btn_error = new wxButton(this, wxID_ANY, _L("Show error message"));
|
||||
btn_error->Disable();
|
||||
// Note: The label needs to be present, otherwise we get accelerator bugs on Mac
|
||||
auto *btn_close = new wxButton(this, wxID_CANCEL, _L("Close"));
|
||||
btnsizer->Add(btn_cancel, 0, wxRIGHT, SPACING);
|
||||
btnsizer->Add(btn_error, 0);
|
||||
btnsizer->AddStretchSpacer();
|
||||
btnsizer->Add(btn_close);
|
||||
|
||||
topsizer->Add(job_list, 1, wxEXPAND | wxBOTTOM, SPACING);
|
||||
topsizer->Add(btnsizer, 0, wxEXPAND);
|
||||
SetSizer(topsizer);
|
||||
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
wxGetApp().UpdateDVCDarkUI(job_list);
|
||||
|
||||
std::vector<int> size;
|
||||
SetSize(load_user_data(UDT_SIZE, size) ? wxSize(size[0] * em, size[1] * em) : wxSize(HEIGHT * em, WIDTH * em));
|
||||
|
||||
Bind(wxEVT_SIZE, [this](wxSizeEvent& evt) {
|
||||
OnSize(evt);
|
||||
save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS);
|
||||
});
|
||||
|
||||
std::vector<int> pos;
|
||||
if (load_user_data(UDT_POSITION, pos))
|
||||
SetPosition(wxPoint(pos[0], pos[1]));
|
||||
|
||||
Bind(wxEVT_MOVE, [this](wxMoveEvent& evt) {
|
||||
save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS);
|
||||
});
|
||||
|
||||
job_list->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxDataViewEvent&) { on_list_select(); });
|
||||
|
||||
btn_cancel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||
int selected = job_list->GetSelectedRow();
|
||||
if (selected == wxNOT_FOUND) { return; }
|
||||
|
||||
const JobState state = get_state(selected);
|
||||
if (state < ST_ERROR) {
|
||||
GUI::wxGetApp().printhost_job_queue().cancel(selected);
|
||||
}
|
||||
});
|
||||
|
||||
btn_error->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) {
|
||||
int selected = job_list->GetSelectedRow();
|
||||
if (selected == wxNOT_FOUND) { return; }
|
||||
GUI::show_error(nullptr, job_list->GetTextValue(selected, COL_ERRORMSG));
|
||||
});
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::append_job(const PrintHostJob &job)
|
||||
{
|
||||
wxCHECK_RET(!job.empty(), "PrintHostQueueDialog: Attempt to append an empty job");
|
||||
|
||||
wxVector<wxVariant> fields;
|
||||
fields.push_back(wxVariant(wxString::Format("%d", job_list->GetItemCount() + 1)));
|
||||
fields.push_back(wxVariant(0));
|
||||
fields.push_back(wxVariant(_L("Enqueued")));
|
||||
fields.push_back(wxVariant(job.printhost->get_host()));
|
||||
boost::system::error_code ec;
|
||||
boost::uintmax_t size_i = boost::filesystem::file_size(job.upload_data.source_path, ec);
|
||||
std::stringstream stream;
|
||||
if (ec) {
|
||||
stream << "unknown";
|
||||
size_i = 0;
|
||||
BOOST_LOG_TRIVIAL(error) << ec.message();
|
||||
} else
|
||||
stream << std::fixed << std::setprecision(2) << ((float)size_i / 1024 / 1024) << "MB";
|
||||
fields.push_back(wxVariant(stream.str()));
|
||||
fields.push_back(wxVariant(job.upload_data.upload_path.string()));
|
||||
fields.push_back(wxVariant(""));
|
||||
job_list->AppendItem(fields, static_cast<wxUIntPtr>(ST_NEW));
|
||||
// Both strings are UTF-8 encoded.
|
||||
upload_names.emplace_back(job.printhost->get_host(), job.upload_data.upload_path.string());
|
||||
|
||||
wxGetApp().notification_manager()->push_upload_job_notification(job_list->GetItemCount(), (float)size_i / 1024 / 1024, job.upload_data.upload_path.string(), job.printhost->get_host());
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_dpi_changed(const wxRect &suggested_rect)
|
||||
{
|
||||
const int& em = em_unit();
|
||||
|
||||
msw_buttons_rescale(this, em, { wxID_DELETE, wxID_CANCEL, btn_error->GetId() });
|
||||
|
||||
SetMinSize(wxSize(HEIGHT * em, WIDTH * em));
|
||||
|
||||
Fit();
|
||||
Refresh();
|
||||
|
||||
save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS);
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_sys_color_changed()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wxGetApp().UpdateDlgDarkUI(this);
|
||||
wxGetApp().UpdateDVCDarkUI(job_list);
|
||||
#endif
|
||||
}
|
||||
|
||||
PrintHostQueueDialog::JobState PrintHostQueueDialog::get_state(int idx)
|
||||
{
|
||||
wxCHECK_MSG(idx >= 0 && idx < job_list->GetItemCount(), ST_ERROR, "Out of bounds access to job list");
|
||||
return static_cast<JobState>(job_list->GetItemData(job_list->RowToItem(idx)));
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::set_state(int idx, JobState state)
|
||||
{
|
||||
wxCHECK_RET(idx >= 0 && idx < job_list->GetItemCount(), "Out of bounds access to job list");
|
||||
job_list->SetItemData(job_list->RowToItem(idx), static_cast<wxUIntPtr>(state));
|
||||
|
||||
switch (state) {
|
||||
case ST_NEW: job_list->SetValue(_L("Enqueued"), idx, COL_STATUS); break;
|
||||
case ST_PROGRESS: job_list->SetValue(_L("Uploading"), idx, COL_STATUS); break;
|
||||
case ST_ERROR: job_list->SetValue(_L("Error"), idx, COL_STATUS); break;
|
||||
case ST_CANCELLING: job_list->SetValue(_L("Cancelling"), idx, COL_STATUS); break;
|
||||
case ST_CANCELLED: job_list->SetValue(_L("Cancelled"), idx, COL_STATUS); break;
|
||||
case ST_COMPLETED: job_list->SetValue(_L("Completed"), idx, COL_STATUS); break;
|
||||
}
|
||||
// This might be ambigous call, but user data needs to be saved time to time
|
||||
save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS);
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_list_select()
|
||||
{
|
||||
int selected = job_list->GetSelectedRow();
|
||||
if (selected != wxNOT_FOUND) {
|
||||
const JobState state = get_state(selected);
|
||||
btn_cancel->Enable(state < ST_ERROR);
|
||||
btn_error->Enable(state == ST_ERROR);
|
||||
Layout();
|
||||
} else {
|
||||
btn_cancel->Disable();
|
||||
}
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_progress(Event &evt)
|
||||
{
|
||||
wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list");
|
||||
|
||||
if (evt.progress < 100) {
|
||||
set_state(evt.job_id, ST_PROGRESS);
|
||||
job_list->SetValue(wxVariant(evt.progress), evt.job_id, COL_PROGRESS);
|
||||
} else {
|
||||
set_state(evt.job_id, ST_COMPLETED);
|
||||
job_list->SetValue(wxVariant(100), evt.job_id, COL_PROGRESS);
|
||||
}
|
||||
|
||||
on_list_select();
|
||||
|
||||
if (evt.progress > 0)
|
||||
{
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->set_upload_job_notification_percentage(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()), evt.progress / 100.f);
|
||||
}
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_error(Event &evt)
|
||||
{
|
||||
wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list");
|
||||
|
||||
set_state(evt.job_id, ST_ERROR);
|
||||
|
||||
auto errormsg = from_u8((boost::format("%1%\n%2%") % _utf8(L("Error uploading to print host:")) % std::string(evt.error.ToUTF8())).str());
|
||||
job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS);
|
||||
job_list->SetValue(wxVariant(errormsg), evt.job_id, COL_ERRORMSG); // Stashes the error message into a hidden column for later
|
||||
|
||||
on_list_select();
|
||||
|
||||
GUI::show_error(nullptr, errormsg);
|
||||
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->upload_job_notification_show_error(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()));
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::on_cancel(Event &evt)
|
||||
{
|
||||
wxCHECK_RET(evt.job_id < (size_t)job_list->GetItemCount(), "Out of bounds access to job list");
|
||||
|
||||
set_state(evt.job_id, ST_CANCELLED);
|
||||
job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS);
|
||||
|
||||
on_list_select();
|
||||
|
||||
wxVariant nm, hst;
|
||||
job_list->GetValue(nm, evt.job_id, COL_FILENAME);
|
||||
job_list->GetValue(hst, evt.job_id, COL_HOST);
|
||||
wxGetApp().notification_manager()->upload_job_notification_show_canceled(evt.job_id + 1, boost::nowide::narrow(nm.GetString()), boost::nowide::narrow(hst.GetString()));
|
||||
}
|
||||
|
||||
void PrintHostQueueDialog::get_active_jobs(std::vector<std::pair<std::string, std::string>>& ret)
|
||||
{
|
||||
int ic = job_list->GetItemCount();
|
||||
for (int i = 0; i < ic; i++)
|
||||
{
|
||||
auto item = job_list->RowToItem(i);
|
||||
auto data = job_list->GetItemData(item);
|
||||
JobState st = static_cast<JobState>(data);
|
||||
if(st == JobState::ST_NEW || st == JobState::ST_PROGRESS)
|
||||
ret.emplace_back(upload_names[i]);
|
||||
}
|
||||
//job_list->data
|
||||
}
|
||||
void PrintHostQueueDialog::save_user_data(int udt)
|
||||
{
|
||||
const auto em = GetTextExtent("m").x;
|
||||
auto *app_config = wxGetApp().app_config;
|
||||
if (udt & UserDataType::UDT_SIZE) {
|
||||
|
||||
app_config->set("print_host_queue_dialog_height", std::to_string(this->GetSize().x / em));
|
||||
app_config->set("print_host_queue_dialog_width", std::to_string(this->GetSize().y / em));
|
||||
}
|
||||
if (udt & UserDataType::UDT_POSITION)
|
||||
{
|
||||
app_config->set("print_host_queue_dialog_x", std::to_string(this->GetPosition().x));
|
||||
app_config->set("print_host_queue_dialog_y", std::to_string(this->GetPosition().y));
|
||||
}
|
||||
if (udt & UserDataType::UDT_COLS)
|
||||
{
|
||||
for (size_t i = 0; i < job_list->GetColumnCount() - 1; i++)
|
||||
{
|
||||
app_config->set("print_host_queue_dialog_column_" + std::to_string(i), std::to_string(job_list->GetColumn(i)->GetWidth()));
|
||||
}
|
||||
}
|
||||
}
|
||||
bool PrintHostQueueDialog::load_user_data(int udt, std::vector<int>& vector)
|
||||
{
|
||||
auto* app_config = wxGetApp().app_config;
|
||||
auto hasget = [app_config](const std::string& name, std::vector<int>& vector)->bool {
|
||||
if (app_config->has(name)) {
|
||||
vector.push_back(std::stoi(app_config->get(name)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
if (udt & UserDataType::UDT_SIZE) {
|
||||
if (!hasget("print_host_queue_dialog_height",vector))
|
||||
return false;
|
||||
if (!hasget("print_host_queue_dialog_width", vector))
|
||||
return false;
|
||||
}
|
||||
if (udt & UserDataType::UDT_POSITION)
|
||||
{
|
||||
if (!hasget("print_host_queue_dialog_x", vector))
|
||||
return false;
|
||||
if (!hasget("print_host_queue_dialog_y", vector))
|
||||
return false;
|
||||
}
|
||||
if (udt & UserDataType::UDT_COLS)
|
||||
{
|
||||
for (size_t i = 0; i < 6; i++)
|
||||
{
|
||||
if (!hasget("print_host_queue_dialog_column_" + std::to_string(i), vector))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}}
|
|
@ -1,130 +0,0 @@
|
|||
#ifndef slic3r_PrintHostSendDialog_hpp_
|
||||
#define slic3r_PrintHostSendDialog_hpp_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <wx/string.h>
|
||||
#include <wx/event.h>
|
||||
#include <wx/dialog.h>
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
#include "MsgDialog.hpp"
|
||||
#include "../Utils/PrintHost.hpp"
|
||||
|
||||
class wxButton;
|
||||
class wxTextCtrl;
|
||||
class wxChoice;
|
||||
class wxComboBox;
|
||||
class wxDataViewListCtrl;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class PrintHostSendDialog : public GUI::MsgDialog
|
||||
{
|
||||
public:
|
||||
PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups);
|
||||
boost::filesystem::path filename() const;
|
||||
PrintHostPostUploadAction post_action() const;
|
||||
std::string group() const;
|
||||
|
||||
virtual void EndModal(int ret) override;
|
||||
private:
|
||||
wxTextCtrl *txt_filename;
|
||||
wxComboBox *combo_groups;
|
||||
PrintHostPostUploadAction post_upload_action;
|
||||
wxString m_valid_suffix;
|
||||
};
|
||||
|
||||
|
||||
class PrintHostQueueDialog : public DPIDialog
|
||||
{
|
||||
public:
|
||||
class Event : public wxEvent
|
||||
{
|
||||
public:
|
||||
size_t job_id;
|
||||
int progress = 0; // in percent
|
||||
wxString error;
|
||||
|
||||
Event(wxEventType eventType, int winid, size_t job_id);
|
||||
Event(wxEventType eventType, int winid, size_t job_id, int progress);
|
||||
Event(wxEventType eventType, int winid, size_t job_id, wxString error);
|
||||
|
||||
virtual wxEvent *Clone() const;
|
||||
};
|
||||
|
||||
|
||||
PrintHostQueueDialog(wxWindow *parent);
|
||||
|
||||
void append_job(const PrintHostJob &job);
|
||||
void get_active_jobs(std::vector<std::pair<std::string, std::string>>& ret);
|
||||
|
||||
virtual bool Show(bool show = true) override
|
||||
{
|
||||
if(!show)
|
||||
save_user_data(UDT_SIZE | UDT_POSITION | UDT_COLS);
|
||||
return DPIDialog::Show(show);
|
||||
}
|
||||
protected:
|
||||
void on_dpi_changed(const wxRect &suggested_rect) override;
|
||||
void on_sys_color_changed() override;
|
||||
|
||||
private:
|
||||
enum Column {
|
||||
COL_ID,
|
||||
COL_PROGRESS,
|
||||
COL_STATUS,
|
||||
COL_HOST,
|
||||
COL_SIZE,
|
||||
COL_FILENAME,
|
||||
COL_ERRORMSG
|
||||
};
|
||||
|
||||
enum JobState {
|
||||
ST_NEW,
|
||||
ST_PROGRESS,
|
||||
ST_ERROR,
|
||||
ST_CANCELLING,
|
||||
ST_CANCELLED,
|
||||
ST_COMPLETED,
|
||||
};
|
||||
|
||||
enum { HEIGHT = 60, WIDTH = 30, SPACING = 5 };
|
||||
|
||||
enum UserDataType{
|
||||
UDT_SIZE = 1,
|
||||
UDT_POSITION = 2,
|
||||
UDT_COLS = 4
|
||||
};
|
||||
|
||||
wxButton *btn_cancel;
|
||||
wxButton *btn_error;
|
||||
wxDataViewListCtrl *job_list;
|
||||
// Note: EventGuard prevents delivery of progress evts to a freed PrintHostQueueDialog
|
||||
EventGuard on_progress_evt;
|
||||
EventGuard on_error_evt;
|
||||
EventGuard on_cancel_evt;
|
||||
|
||||
JobState get_state(int idx);
|
||||
void set_state(int idx, JobState);
|
||||
void on_list_select();
|
||||
void on_progress(Event&);
|
||||
void on_error(Event&);
|
||||
void on_cancel(Event&);
|
||||
// This vector keep adress and filename of uploads. It is used when checking for running uploads during exit.
|
||||
std::vector<std::pair<std::string, std::string>> upload_names;
|
||||
void save_user_data(int);
|
||||
bool load_user_data(int, std::vector<int>&);
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(EVT_PRINTHOST_PROGRESS, PrintHostQueueDialog::Event);
|
||||
wxDECLARE_EVENT(EVT_PRINTHOST_ERROR, PrintHostQueueDialog::Event);
|
||||
wxDECLARE_EVENT(EVT_PRINTHOST_CANCEL, PrintHostQueueDialog::Event);
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
|
@ -43,7 +43,6 @@
|
|||
#include "MarkdownTip.hpp"
|
||||
#include "Search.hpp"
|
||||
|
||||
// #include "BonjourDialog.hpp"
|
||||
#ifdef WIN32
|
||||
#include <commctrl.h>
|
||||
#endif // WIN32
|
||||
|
@ -2876,7 +2875,7 @@ void TabPrinter::build_fff()
|
|||
|
||||
// build_preset_description_line(optgroup.get());
|
||||
#endif
|
||||
build_print_host_page();
|
||||
|
||||
build_unregular_pages(true);
|
||||
}
|
||||
|
||||
|
@ -3039,256 +3038,6 @@ PageShp TabPrinter::build_kinematics_page()
|
|||
|
||||
return page;
|
||||
}
|
||||
void TabPrinter::update_printers()
|
||||
{
|
||||
wxBusyCursor wait;
|
||||
|
||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||
|
||||
wxArrayString printers;
|
||||
Field *rs = get_field("printhost_port");
|
||||
try {
|
||||
if (! host->get_printers(printers))
|
||||
printers.clear();
|
||||
} catch (const HostNetworkError &err) {
|
||||
printers.clear();
|
||||
show_error(this, _L("Connection to printers connected via the print host failed.") + "\n\n" + from_u8(err.what()));
|
||||
}
|
||||
Choice *choice = dynamic_cast<Choice*>(rs);
|
||||
choice->set_values(printers);
|
||||
printers.empty() ? rs->disable() : rs->enable();
|
||||
}
|
||||
|
||||
void TabPrinter::update_host_type(bool printer_change)
|
||||
{
|
||||
Field* ht = get_field("host_type");
|
||||
|
||||
wxArrayString types;
|
||||
// Append localized enum_labels
|
||||
assert(ht->m_opt.enum_labels.size() == ht->m_opt.enum_values.size());
|
||||
for (size_t i = 0; i < ht->m_opt.enum_labels.size(); i++) {
|
||||
if (ht->m_opt.enum_values[i] == "prusalink")
|
||||
continue;
|
||||
types.Add(_(ht->m_opt.enum_labels[i]));
|
||||
}
|
||||
|
||||
Choice* choice = dynamic_cast<Choice*>(ht);
|
||||
choice->set_values(types);
|
||||
auto set_to_choice_and_config = [this, choice](PrintHostType type) {
|
||||
choice->set_value(static_cast<int>(type));
|
||||
m_config->set_key_value("host_type", new ConfigOptionEnum<PrintHostType>(type));
|
||||
};
|
||||
set_to_choice_and_config(htOctoPrint);
|
||||
}
|
||||
|
||||
void TabPrinter::update_printhost_buttons()
|
||||
{
|
||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||
m_printhost_test_btn->Enable(!m_config->opt_string("print_host").empty() && host->can_test());
|
||||
m_printhost_browse_btn->Enable(host->has_auto_discovery());
|
||||
}
|
||||
|
||||
|
||||
PageShp TabPrinter::build_print_host_page()
|
||||
{
|
||||
auto page = add_options_page(L("Connection"), "printer");
|
||||
#if 1
|
||||
auto optgroup = page->new_optgroup(L("Moonraker"));
|
||||
Option option = optgroup->get_option("connection_moonraker_url");
|
||||
option.opt.full_width = true;
|
||||
optgroup->append_single_option_line(option);
|
||||
optgroup->append_single_option_line("connection_port");
|
||||
#else
|
||||
auto optgroup = page->new_optgroup(L("Print Host upload"));
|
||||
optgroup->m_on_change = [this](t_config_option_key opt_key, boost::any value) {
|
||||
if (opt_key == "host_type" || opt_key == "printhost_authorization_type")
|
||||
this->update();
|
||||
if (opt_key == "print_host")
|
||||
this->update_printhost_buttons();
|
||||
};
|
||||
|
||||
optgroup->append_single_option_line("host_type");
|
||||
|
||||
auto create_sizer_with_btn = [](wxWindow* parent, ScalableButton** btn, const std::string& icon_name, const wxString& label) {
|
||||
*btn = new ScalableButton(parent, wxID_ANY, icon_name, label, wxDefaultSize, wxDefaultPosition, wxBU_LEFT | wxBU_EXACTFIT);
|
||||
(*btn)->SetFont(wxGetApp().normal_font());
|
||||
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(*btn);
|
||||
return sizer;
|
||||
};
|
||||
|
||||
auto printhost_browse = [=](wxWindow* parent)
|
||||
{
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_browse_btn, "browse", _L("Browse") + " " + dots);
|
||||
// m_printhost_browse_btn->Bind(wxEVT_BUTTON, [=](wxCommandEvent& e) {
|
||||
// BonjourDialog dialog(this, m_printer_technology);
|
||||
// if (dialog.show_and_lookup()) {
|
||||
// optgroup->set_value("print_host", dialog.get_selected(), true);
|
||||
// optgroup->get_field("print_host")->field_changed();
|
||||
// }
|
||||
// });
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
auto print_host_test = [=](wxWindow* parent) {
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_test_btn, "test", _L("Test"));
|
||||
|
||||
m_printhost_test_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& e) {
|
||||
std::unique_ptr<PrintHost> host(PrintHost::get_print_host(m_config));
|
||||
if (!host) {
|
||||
const wxString text = _L("Could not get a valid Printer Host reference");
|
||||
show_error(this, text);
|
||||
return;
|
||||
}
|
||||
wxString msg;
|
||||
bool result;
|
||||
{
|
||||
// Show a wait cursor during the connection test, as it is blocking UI.
|
||||
wxBusyCursor wait;
|
||||
result = host->test(msg);
|
||||
}
|
||||
if (result)
|
||||
show_info(this, host->get_test_ok_msg(), _L("Success!"));
|
||||
else
|
||||
show_error(this, host->get_test_failed_msg(msg));
|
||||
});
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
auto print_host_printers = [this, create_sizer_with_btn](wxWindow* parent) {
|
||||
//add_scaled_button(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers")), wxBU_LEFT | wxBU_EXACTFIT);
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_port_browse_btn, "browse", _(L("Refresh Printers")));
|
||||
ScalableButton* btn = m_printhost_port_browse_btn;
|
||||
btn->SetFont(Slic3r::GUI::wxGetApp().normal_font());
|
||||
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent e) { update_printers(); });
|
||||
return sizer;
|
||||
};
|
||||
|
||||
// Set a wider width for a better alignment
|
||||
Option option = optgroup->get_option("print_host");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line host_line = optgroup->create_single_option_line(option);
|
||||
host_line.append_widget(printhost_browse);
|
||||
host_line.append_widget(print_host_test);
|
||||
optgroup->append_line(host_line);
|
||||
|
||||
optgroup->append_single_option_line("printhost_authorization_type");
|
||||
|
||||
option = optgroup->get_option("printhost_apikey");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
option = optgroup->get_option("printhost_port");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line port_line = optgroup->create_single_option_line(option);
|
||||
port_line.append_widget(print_host_printers);
|
||||
optgroup->append_line(port_line);
|
||||
|
||||
const auto ca_file_hint = _u8L("HTTPS CA file is optional. It is only needed if you use HTTPS with a self-signed certificate.");
|
||||
|
||||
if (Http::ca_file_supported()) {
|
||||
option = optgroup->get_option("printhost_cafile");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
Line cafile_line = optgroup->create_single_option_line(option);
|
||||
|
||||
auto printhost_cafile_browse = [=](wxWindow* parent) {
|
||||
auto sizer = create_sizer_with_btn(parent, &m_printhost_cafile_browse_btn, "browse", _L("Browse") + " " + dots);
|
||||
m_printhost_cafile_browse_btn->Bind(wxEVT_BUTTON, [this, optgroup](wxCommandEvent e) {
|
||||
static const auto filemasks = _L("Certificate files (*.crt, *.pem)|*.crt;*.pem|All files|*.*");
|
||||
wxFileDialog openFileDialog(this, _L("Open CA certificate file"), "", "", filemasks, wxFD_OPEN | wxFD_FILE_MUST_EXIST);
|
||||
if (openFileDialog.ShowModal() != wxID_CANCEL) {
|
||||
optgroup->set_value("printhost_cafile", openFileDialog.GetPath(), true);
|
||||
optgroup->get_field("printhost_cafile")->field_changed();
|
||||
}
|
||||
});
|
||||
|
||||
return sizer;
|
||||
};
|
||||
|
||||
cafile_line.append_widget(printhost_cafile_browse);
|
||||
optgroup->append_line(cafile_line);
|
||||
|
||||
Line cafile_hint{ "", "" };
|
||||
cafile_hint.full_width = 1;
|
||||
cafile_hint.widget = [ca_file_hint](wxWindow* parent) {
|
||||
auto txt = new wxStaticText(parent, wxID_ANY, ca_file_hint);
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(txt);
|
||||
return sizer;
|
||||
};
|
||||
optgroup->append_line(cafile_hint);
|
||||
}
|
||||
else {
|
||||
|
||||
Line line{ "", "" };
|
||||
line.full_width = 1;
|
||||
|
||||
line.widget = [ca_file_hint](wxWindow* parent) {
|
||||
std::string info = _u8L("HTTPS CA File") + ":\n\t" +
|
||||
(boost::format(_u8L("On this system, %s uses HTTPS certificates from the system Certificate Store or Keychain.")) % SLIC3R_APP_NAME).str() +
|
||||
"\n\t" + _u8L("To use a custom CA file, please import your CA file into Certificate Store / Keychain.");
|
||||
|
||||
//auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\n\t%2%") % info % ca_file_hint).str()));
|
||||
auto txt = new wxStaticText(parent, wxID_ANY, from_u8((boost::format("%1%\n\t%2%") % info % ca_file_hint).str()));
|
||||
txt->SetFont(wxGetApp().normal_font());
|
||||
auto sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(txt, 1, wxEXPAND);
|
||||
return sizer;
|
||||
};
|
||||
optgroup->append_line(line);
|
||||
}
|
||||
|
||||
for (const std::string& opt_key : std::vector<std::string>{ "printhost_user", "printhost_password" }) {
|
||||
option = optgroup->get_option(opt_key);
|
||||
option.opt.width = Field::def_width_wider();
|
||||
optgroup->append_single_option_line(option);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
option = optgroup->get_option("printhost_ssl_ignore_revoke");
|
||||
option.opt.width = Field::def_width_wider();
|
||||
optgroup->append_single_option_line(option);
|
||||
#endif
|
||||
|
||||
optgroup->activate();
|
||||
|
||||
Field* printhost_field = optgroup->get_field("print_host");
|
||||
if (printhost_field)
|
||||
{
|
||||
wxTextCtrl* temp = dynamic_cast<wxTextCtrl*>(printhost_field->getWindow());
|
||||
if (temp)
|
||||
temp->Bind(wxEVT_TEXT, ([printhost_field, temp](wxEvent& e)
|
||||
{
|
||||
#ifndef __WXGTK__
|
||||
e.Skip();
|
||||
temp->GetToolTip()->Enable(true);
|
||||
#endif // __WXGTK__
|
||||
// Remove all leading and trailing spaces from the input
|
||||
std::string trimed_str, str = trimed_str = temp->GetValue().ToStdString();
|
||||
boost::trim(trimed_str);
|
||||
if (trimed_str != str)
|
||||
temp->SetValue(trimed_str);
|
||||
|
||||
TextCtrl* field = dynamic_cast<TextCtrl*>(printhost_field);
|
||||
if (field)
|
||||
field->propagate_value();
|
||||
}), temp->GetId());
|
||||
}
|
||||
|
||||
// Always fill in the "printhost_port" combo box from the config and select it.
|
||||
{
|
||||
Choice* choice = dynamic_cast<Choice*>(optgroup->get_field("printhost_port"));
|
||||
// choice->set_values({ m_config->opt_string("printhost_port") });
|
||||
choice->set_selection();
|
||||
}
|
||||
|
||||
// update();
|
||||
#endif
|
||||
return page;
|
||||
}
|
||||
|
||||
/* Previous name build_extruder_pages().
|
||||
*
|
||||
|
|
|
@ -547,14 +547,6 @@ private:
|
|||
std::vector<PageShp> m_pages_fff;
|
||||
std::vector<PageShp> m_pages_sla;
|
||||
|
||||
//SoftFever
|
||||
ScalableButton* m_add_preset_btn {nullptr};
|
||||
ScalableButton* m_printhost_browse_btn {nullptr};
|
||||
ScalableButton* m_printhost_test_btn {nullptr};
|
||||
ScalableButton* m_printhost_cafile_browse_btn {nullptr};
|
||||
ScalableButton* m_printhost_port_browse_btn {nullptr};
|
||||
|
||||
wxBoxSizer* m_presets_sizer {nullptr};
|
||||
public:
|
||||
ScalableButton* m_reset_to_filament_color = nullptr;
|
||||
|
||||
|
@ -593,13 +585,6 @@ public:
|
|||
//wxSizer* create_bed_shape_widget(wxWindow* parent);
|
||||
void cache_extruder_cnt();
|
||||
bool apply_extruder_cnt_from_cache();
|
||||
|
||||
//SoftFever
|
||||
void update_host_type(bool printer_change);
|
||||
void update_printhost_buttons();
|
||||
void update_printers();
|
||||
PageShp build_print_host_page();
|
||||
|
||||
};
|
||||
|
||||
class TabSLAMaterial : public Tab
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue