Slic3r::format(), Slic3r::GUI::format_wxstr():

wrappers around boost::format using C++17 variadic templates,
replacing the ugly and verbose
	(boost::format("template") % arg1 % arg2).str()
syntax.
The wrappers also implictely convert input parameters including the template
from wxString to UTF8.

The new format wrapper has been applied at multiple places as a start,
also some double macros _(L()) with new single macro _L().
This commit is contained in:
bubnikv 2020-04-01 09:48:56 +02:00
parent daa6dd0a25
commit b843a094f6
10 changed files with 364 additions and 240 deletions

View File

@ -64,6 +64,7 @@ add_library(libslic3r STATIC
Fill/FillRectilinear3.hpp
Flow.cpp
Flow.hpp
format.hpp
Format/3mf.cpp
Format/3mf.hpp
Format/AMF.cpp

View File

@ -1,4 +1,5 @@
#include "Config.hpp"
#include "format.hpp"
#include "Utils.hpp"
#include <assert.h>
#include <fstream>
@ -464,7 +465,7 @@ bool ConfigBase::set_deserialize_nothrow(const t_config_option_key &opt_key_src,
void ConfigBase::set_deserialize(const t_config_option_key &opt_key_src, const std::string &value_src, bool append)
{
if (! this->set_deserialize_nothrow(opt_key_src, value_src, append))
throw BadOptionTypeException((boost::format("ConfigBase::set_deserialize() failed for parameter \"%1%\", value \"%2%\"") % opt_key_src % value_src).str());
throw BadOptionTypeException(format("ConfigBase::set_deserialize() failed for parameter \"%1%\", value \"%2%\"", opt_key_src, value_src));
}
void ConfigBase::set_deserialize(std::initializer_list<SetDeserializeItem> items)
@ -620,7 +621,7 @@ void ConfigBase::load_from_gcode_file(const std::string &file)
size_t key_value_pairs = load_from_gcode_string(data.data());
if (key_value_pairs < 80)
throw std::runtime_error((boost::format("Suspiciously low number of configuration values extracted from %1%: %2%") % file % key_value_pairs).str());
throw std::runtime_error(format("Suspiciously low number of configuration values extracted from %1%: %2%", file, key_value_pairs));
}
// Load the config keys from the given string.

57
src/libslic3r/format.hpp Normal file
View File

@ -0,0 +1,57 @@
#ifndef slic3r_format_hpp_
#define slic3r_format_hpp_
// Functional wrapper around boost::format.
// One day we may replace this wrapper with C++20 format
// https://en.cppreference.com/w/cpp/utility/format/format
// though C++20 format uses a different template pattern for position independent parameters.
//
// Boost::format works around the missing variadic templates by an ugly % chaining operator. The usage of boost::format looks like this:
// (boost::format("template") % arg1 %arg2).str()
// This wrapper allows for a nicer syntax:
// Slic3r::format("template", arg1, arg2)
// One can also override Slic3r::internal::format::cook() function to convert a Slic3r::format() argument to something that
// boost::format may convert to string, see slic3r/GUI/I18N.hpp for a "cook" function to convert wxString to UTF8.
#include <boost/format.hpp>
namespace Slic3r {
// https://gist.github.com/gchudnov/6a90d51af004d97337ec
namespace internal {
namespace format {
// Default "cook" function - just forward.
template<typename T>
inline T&& cook(T&& arg) {
return std::forward<T>(arg);
}
// End of the recursive chain.
inline std::string format_recursive(boost::format& message) {
return message.str();
}
template<typename TValue, typename... TArgs>
std::string format_recursive(boost::format& message, TValue&& arg, TArgs&&... args) {
// Format, possibly convert the argument by the "cook" function.
message % cook(std::forward<TValue>(arg));
return format_recursive(message, std::forward<TArgs>(args)...);
}
}
};
template<typename... TArgs>
inline std::string format(const char* fmt, TArgs&&... args) {
boost::format message(fmt);
return internal::format::format_recursive(message, std::forward<TArgs>(args)...);
}
template<typename... TArgs>
inline std::string format(const std::string& fmt, TArgs&&... args) {
boost::format message(fmt);
return internal::format::format_recursive(message, std::forward<TArgs>(args)...);
}
} // namespace Slic3r
#endif // slic3r_format_hpp_

View File

@ -111,6 +111,7 @@
#include "BoundingBox.hpp"
#include "ClipperUtils.hpp"
#include "Config.hpp"
#include "format.hpp"
#include "I18N.hpp"
#include "MultiPoint.hpp"
#include "Point.hpp"

View File

@ -22,6 +22,7 @@ set(SLIC3R_GUI_SOURCES
GUI/ConfigSnapshotDialog.hpp
GUI/3DScene.cpp
GUI/3DScene.hpp
GUI/format.hpp
GUI/GLShader.cpp
GUI/GLShader.hpp
GUI/GLCanvas3D.hpp

View File

@ -20,11 +20,13 @@
#include <cmath>
#include <boost/algorithm/string/replace.hpp>
#include "Field.hpp"
#include "format.hpp"
namespace Slic3r {
using GUI::from_u8;
using GUI::into_u8;
using GUI::format_wxstr;
namespace DoubleSlider {
@ -530,7 +532,7 @@ wxString Control::get_label(int tick) const
const wxString str = m_values.empty() ?
wxNumberFormatter::ToString(m_label_koef*value, 2, wxNumberFormatter::Style_None) :
wxNumberFormatter::ToString(m_values[value], 2, wxNumberFormatter::Style_None);
return from_u8((boost::format("%1%\n(%2%)") % str % (m_values.empty() ? value : value+1)).str());
return format_wxstr("%1%\n(%2%)", str, m_values.empty() ? value : value+1);
}
void Control::draw_tick_text(wxDC& dc, const wxPoint& pos, int tick, bool right_side/*=true*/) const
@ -1001,15 +1003,15 @@ wxString Control::get_tooltip(int tick/*=-1*/)
// Show custom Gcode as a first string of tooltop
tooltip = " ";
tooltip += tick_code_it->gcode == ColorChangeCode ? ( m_mode == t_mode::SingleExtruder ?
from_u8((boost::format(_utf8(L("Color change (\"%1%\")"))) % tick_code_it->gcode ).str()) :
from_u8((boost::format(_utf8(L("Color change (\"%1%\") for Extruder %2%"))) %
tick_code_it->gcode % tick_code_it->extruder).str()) ) :
tooltip +=
tick_code_it->gcode == ColorChangeCode ?
(m_mode == t_mode::SingleExtruder ?
format_wxstr(_L("Color change (\"%1%\")"), tick_code_it->gcode) :
format_wxstr(_L("Color change (\"%1%\") for Extruder %2%"), tick_code_it->gcode, tick_code_it->extruder)) :
tick_code_it->gcode == PausePrintCode ?
from_u8((boost::format(_utf8(L("Pause print (\"%1%\")"))) % tick_code_it->gcode ).str()) :
format_wxstr(_L("Pause print (\"%1%\")"), tick_code_it->gcode) :
tick_code_it->gcode == ToolChangeCode ?
from_u8((boost::format(_utf8(L("Extruder (tool) is changed to Extruder \"%1%\""))) %
tick_code_it->extruder ).str()) :
format_wxstr(_L("Extruder (tool) is changed to Extruder \"%1%\""), tick_code_it->extruder) :
from_u8(tick_code_it->gcode);
// If tick is marked as a conflict (exclamation icon),
@ -1176,8 +1178,8 @@ void Control::append_add_color_change_menu_item(wxMenu* menu, bool switch_curren
}
const wxString menu_name = switch_current_code ?
from_u8((boost::format(_utf8(L("Switch code to Color change (%1%) for:"))) % ColorChangeCode).str()) :
from_u8((boost::format(_utf8(L("Add color change (%1%) for:"))) % ColorChangeCode).str());
format_wxstr(_L("Switch code to Color change (%1%) for:"), ColorChangeCode) :
format_wxstr(_L("Add color change (%1%) for:"), ColorChangeCode);
wxMenuItem* add_color_change_menu_item = menu->AppendSubMenu(add_color_change_menu, menu_name, "");
add_color_change_menu_item->SetBitmap(create_scaled_bitmap("colorchange_add_m"));
}
@ -1615,8 +1617,8 @@ static void upgrade_text_entry_dialog(wxTextEntryDialog* dlg, double min = -1.0,
static std::string get_custom_code(const std::string& code_in, double height)
{
wxString msg_text = from_u8(_utf8(L("Enter custom G-code used on current layer"))) + ":";
wxString msg_header = from_u8((boost::format(_utf8(L("Custom G-code on current layer (%1% mm)."))) % height).str());
wxString msg_text = _L("Enter custom G-code used on current layer") + ":";
wxString msg_header = format_wxstr(_L("Custom G-code on current layer (%1% mm)."), height);
// get custom gcode
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, code_in,
@ -1631,8 +1633,8 @@ static std::string get_custom_code(const std::string& code_in, double height)
static std::string get_pause_print_msg(const std::string& msg_in, double height)
{
wxString msg_text = from_u8(_utf8(L("Enter short message shown on Printer display when a print is paused"))) + ":";
wxString msg_header = from_u8((boost::format(_utf8(L("Message for pause print on current layer (%1% mm)."))) % height).str());
wxString msg_text = _L("Enter short message shown on Printer display when a print is paused") + ":";
wxString msg_header = format_wxstr(_L("Message for pause print on current layer (%1% mm)."), height);
// get custom gcode
wxTextEntryDialog dlg(nullptr, msg_text, msg_header, from_u8(msg_in),

View File

@ -138,7 +138,7 @@ public:
};
ObjectInfo::ObjectInfo(wxWindow *parent) :
wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _(L("Info"))), wxVERTICAL)
wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _L("Info")), wxVERTICAL)
{
GetStaticBox()->SetFont(wxGetApp().bold_font());
@ -157,13 +157,13 @@ ObjectInfo::ObjectInfo(wxWindow *parent) :
return text;
};
init_info_label(&info_size, _(L("Size")));
label_volume = init_info_label(&info_volume, _(L("Volume")));
init_info_label(&info_facets, _(L("Facets")));
label_materials = init_info_label(&info_materials, _(L("Materials")));
init_info_label(&info_size, _L("Size"));
label_volume = init_info_label(&info_volume, _L("Volume"));
init_info_label(&info_facets, _L("Facets"));
label_materials = init_info_label(&info_materials, _L("Materials"));
Add(grid_sizer, 0, wxEXPAND);
auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _(L("Manifold")) + ":");
auto *info_manifold_text = new wxStaticText(parent, wxID_ANY, _L("Manifold") + ":");
info_manifold_text->SetFont(wxGetApp().small_font());
info_manifold = new wxStaticText(parent, wxID_ANY, "");
info_manifold->SetFont(wxGetApp().small_font());
@ -213,7 +213,7 @@ private:
};
SlicedInfo::SlicedInfo(wxWindow *parent) :
wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _(L("Sliced Info"))), wxVERTICAL)
wxStaticBoxSizer(new wxStaticBox(parent, wxID_ANY, _L("Sliced Info")), wxVERTICAL)
{
GetStaticBox()->SetFont(wxGetApp().bold_font());
@ -232,13 +232,13 @@ SlicedInfo::SlicedInfo(wxWindow *parent) :
info_vec.push_back(std::pair<wxStaticText*, wxStaticText*>(text, info_label));
};
init_info_label(_(L("Used Filament (m)")));
init_info_label(_(L("Used Filament (mm³)")));
init_info_label(_(L("Used Filament (g)")));
init_info_label(_(L("Used Material (unit)")));
init_info_label(_(L("Cost (money)")));
init_info_label(_(L("Estimated printing time")));
init_info_label(_(L("Number of tool changes")));
init_info_label(_L("Used Filament (m)"));
init_info_label(_L("Used Filament (mm³)"));
init_info_label(_L("Used Filament (g)"));
init_info_label(_L("Used Material (unit)"));
init_info_label(_L("Cost (money)"));
init_info_label(_L("Estimated printing time"));
init_info_label(_L("Number of tool changes"));
Add(grid_sizer, 0, wxEXPAND);
this->Show(false);
@ -345,7 +345,7 @@ PresetBitmapComboBox(parent, wxSize(15 * wxGetApp().em_unit(), -1)),
}
edit_btn = new ScalableButton(parent, wxID_ANY, "cog");
edit_btn->SetToolTip(_(L("Click to edit preset")));
edit_btn->SetToolTip(_L("Click to edit preset"));
edit_btn->Bind(wxEVT_BUTTON, ([preset_type, this](wxCommandEvent)
{
@ -546,7 +546,7 @@ FreqChangedParams::FreqChangedParams(wxWindow* parent) :
line.append_option(option);
auto wiping_dialog_btn = [this](wxWindow* parent) {
m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _(L("Purging volumes")) + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
m_wiping_dialog_button = new wxButton(parent, wxID_ANY, _L("Purging volumes") + dots, wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
m_wiping_dialog_button->SetFont(wxGetApp().normal_font());
auto sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(m_wiping_dialog_button, 0, wxALIGN_CENTER_VERTICAL);
@ -817,11 +817,11 @@ Sidebar::Sidebar(Plater *parent)
};
p->combos_filament.push_back(nullptr);
init_combo(&p->combo_print, _(L("Print settings")), Preset::TYPE_PRINT, false);
init_combo(&p->combos_filament[0], _(L("Filament")), Preset::TYPE_FILAMENT, true);
init_combo(&p->combo_sla_print, _(L("SLA print settings")), Preset::TYPE_SLA_PRINT, false);
init_combo(&p->combo_sla_material, _(L("SLA material")), Preset::TYPE_SLA_MATERIAL, false);
init_combo(&p->combo_printer, _(L("Printer")), Preset::TYPE_PRINTER, false);
init_combo(&p->combo_print, _L("Print settings"), Preset::TYPE_PRINT, false);
init_combo(&p->combos_filament[0], _L("Filament"), Preset::TYPE_FILAMENT, true);
init_combo(&p->combo_sla_print, _L("SLA print settings"), Preset::TYPE_SLA_PRINT, false);
init_combo(&p->combo_sla_material, _L("SLA material"), Preset::TYPE_SLA_MATERIAL, false);
init_combo(&p->combo_printer, _L("Printer"), Preset::TYPE_PRINTER, false);
const int margin_5 = int(0.5*wxGetApp().em_unit());// 5;
@ -880,9 +880,9 @@ Sidebar::Sidebar(Plater *parent)
(*btn)->Hide();
};
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _(L("Send to printer")) + "\tCtrl+Shift+G");
init_scalable_btn(&p->btn_remove_device, "eject_sd" , _(L("Remove device")) + "\tCtrl+T");
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _(L("Export to SD card / Flash drive")) + "\tCtrl+U");
init_scalable_btn(&p->btn_send_gcode , "export_gcode", _L("Send to printer") + "\tCtrl+Shift+G");
init_scalable_btn(&p->btn_remove_device, "eject_sd" , _L("Remove device") + "\tCtrl+T");
init_scalable_btn(&p->btn_export_gcode_removable, "export_to_sd", _L("Export to SD card / Flash drive") + "\tCtrl+U");
// regular buttons "Slice now" and "Export G-code"
@ -893,8 +893,8 @@ Sidebar::Sidebar(Plater *parent)
(*btn)->SetFont(wxGetApp().bold_font());
};
init_btn(&p->btn_export_gcode, _(L("Export G-code")) + dots , scaled_height);
init_btn(&p->btn_reslice , _(L("Slice now")) , scaled_height);
init_btn(&p->btn_export_gcode, _L("Export G-code") + dots , scaled_height);
init_btn(&p->btn_reslice , _L("Slice now") , scaled_height);
enable_buttons(false);
@ -1044,7 +1044,7 @@ void Sidebar::update_reslice_btn_tooltip() const
{
wxString tooltip = wxString("Slice") + " [" + GUI::shortkey_ctrl_prefix() + "R]";
if (m_mode != comSimple)
tooltip += wxString("\n") + _(L("Hold Shift to Slice & Export G-code"));
tooltip += wxString("\n") + _L("Hold Shift to Slice & Export G-code");
p->btn_reslice->SetToolTip(tooltip);
}
@ -1154,16 +1154,16 @@ void Sidebar::show_info_sizer()
const auto& stats = model_object->get_object_stl_stats();//model_object->volumes.front()->mesh.stl.stats;
p->object_info->info_volume->SetLabel(wxString::Format("%.2f", stats.volume));
p->object_info->info_facets->SetLabel(wxString::Format(_(L("%d (%d shells)")), static_cast<int>(model_object->facets_count()), stats.number_of_parts));
p->object_info->info_facets->SetLabel(wxString::Format(_L("%d (%d shells)"), static_cast<int>(model_object->facets_count()), stats.number_of_parts));
int errors = stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
stats.facets_added + stats.facets_reversed + stats.backwards_edges;
if (errors > 0) {
wxString tooltip = wxString::Format(_(L("Auto-repaired (%d errors)")), errors);
wxString tooltip = wxString::Format(_L("Auto-repaired (%d errors)"), errors);
p->object_info->info_manifold->SetLabel(tooltip);
tooltip += ":\n" + wxString::Format(_(L("%d degenerate facets, %d edges fixed, %d facets removed, "
"%d facets added, %d facets reversed, %d backwards edges")),
tooltip += ":\n" + wxString::Format(_L("%d degenerate facets, %d edges fixed, %d facets removed, "
"%d facets added, %d facets reversed, %d backwards edges"),
stats.degenerate_facets, stats.edges_fixed, stats.facets_removed,
stats.facets_added, stats.facets_reversed, stats.backwards_edges);
@ -1172,7 +1172,7 @@ void Sidebar::show_info_sizer()
p->object_info->manifold_warning_icon->SetToolTip(tooltip);
}
else {
p->object_info->info_manifold->SetLabel(_(L("Yes")));
p->object_info->info_manifold->SetLabel(_L("Yes"));
p->object_info->showing_manifold_warning_icon = false;
p->object_info->info_manifold->SetToolTip("");
p->object_info->manifold_warning_icon->SetToolTip("");
@ -1193,10 +1193,10 @@ void Sidebar::update_sliced_info_sizer()
if (p->plater->printer_technology() == ptSLA)
{
const SLAPrintStatistics& ps = p->plater->sla_print().print_statistics();
wxString new_label = _(L("Used Material (ml)")) + ":";
wxString new_label = _L("Used Material (ml)") + ":";
const bool is_supports = ps.support_used_material > 0.0;
if (is_supports)
new_label += from_u8((boost::format("\n - %s\n - %s") % _utf8(L("object(s)")) % _utf8(L("supports and pad"))).str());
new_label += format_wxstr("\n - %s\n - %s", _L("object(s)"), _L("supports and pad"));
wxString info_text = is_supports ?
wxString::Format("%.2f \n%.2f \n%.2f", (ps.objects_used_material + ps.support_used_material) / 1000,
@ -1218,7 +1218,7 @@ void Sidebar::update_sliced_info_sizer()
p->sliced_info->SetTextAndShow(siCost, str_total_cost, "Cost");
wxString t_est = std::isnan(ps.estimated_print_time) ? "N/A" : get_time_dhms(float(ps.estimated_print_time));
p->sliced_info->SetTextAndShow(siEstimatedTime, t_est, _(L("Estimated printing time")) + ":");
p->sliced_info->SetTextAndShow(siEstimatedTime, t_est, _L("Estimated printing time") + ":");
// Hide non-SLA sliced info parameters
p->sliced_info->SetTextAndShow(siFilament_m, "N/A");
@ -1231,9 +1231,9 @@ void Sidebar::update_sliced_info_sizer()
const PrintStatistics& ps = p->plater->fff_print().print_statistics();
const bool is_wipe_tower = ps.total_wipe_tower_filament > 0;
wxString new_label = _(L("Used Filament (m)"));
wxString new_label = _L("Used Filament (m)");
if (is_wipe_tower)
new_label += from_u8((boost::format(":\n - %1%\n - %2%") % _utf8(L("objects")) % _utf8(L("wipe tower"))).str());
new_label += format_wxstr(":\n - %1%\n - %2%", _L("objects"), _L("wipe tower"));
wxString info_text = is_wipe_tower ?
wxString::Format("%.2f \n%.2f \n%.2f", ps.total_used_filament / 1000,
@ -1245,9 +1245,9 @@ void Sidebar::update_sliced_info_sizer()
p->sliced_info->SetTextAndShow(siFilament_mm3, wxString::Format("%.2f", ps.total_extruded_volume));
p->sliced_info->SetTextAndShow(siFilament_g, ps.total_weight == 0.0 ? "N/A" : wxString::Format("%.2f", ps.total_weight));
new_label = _(L("Cost"));
new_label = _L("Cost");
if (is_wipe_tower)
new_label += from_u8((boost::format(":\n - %1%\n - %2%") % _utf8(L("objects")) % _utf8(L("wipe tower"))).str());
new_label += format_wxstr(":\n - %1%\n - %2%", _L("objects"), _L("wipe tower"));
info_text = ps.total_cost == 0.0 ? "N/A" :
is_wipe_tower ?
@ -1260,10 +1260,10 @@ void Sidebar::update_sliced_info_sizer()
if (ps.estimated_normal_print_time == "N/A" && ps.estimated_silent_print_time == "N/A")
p->sliced_info->SetTextAndShow(siEstimatedTime, "N/A");
else {
new_label = _(L("Estimated printing time")) +":";
new_label = _L("Estimated printing time") +":";
info_text = "";
wxString str_color = _(L("Color"));
wxString str_pause = _(L("Pause"));
wxString str_color = _L("Color");
wxString str_pause = _L("Pause");
auto fill_labels = [str_color, str_pause](const std::vector<std::pair<CustomGcodeType, std::string>>& times,
wxString& new_label, wxString& info_text)
@ -1276,25 +1276,25 @@ void Sidebar::update_sliced_info_sizer()
for (int i = (int)times.size() - 1; i >= 0; --i)
{
if (i == 0 || times[i - 1].first == cgtPausePrint)
new_label += from_u8((boost::format("\n - %1%%2%") % (std::string(str_color.ToUTF8()) + " ") % color_change_count).str());
new_label += format_wxstr("\n - %1%%2%", str_color + " ", color_change_count);
else if (times[i - 1].first == cgtColorChange)
new_label += from_u8((boost::format("\n - %1%%2%") % (std::string(str_color.ToUTF8()) + " ") % color_change_count--).str());
new_label += format_wxstr("\n - %1%%2%", str_color + " ", color_change_count--);
if (i != (int)times.size() - 1 && times[i].first == cgtPausePrint)
new_label += from_u8((boost::format(" -> %1%") % std::string(str_pause.ToUTF8())).str());
new_label += format_wxstr(" -> %1%", str_pause);
info_text += from_u8((boost::format("\n%1%") % times[i].second).str());
info_text += format_wxstr("\n%1%", times[i].second);
}
};
if (ps.estimated_normal_print_time != "N/A") {
new_label += from_u8((boost::format("\n - %1%") % _utf8(L("normal mode"))).str());
info_text += from_u8((boost::format("\n%1%") % ps.estimated_normal_print_time).str());
new_label += format_wxstr("\n - %1%", _L("normal mode"));
info_text += format_wxstr("\n%1%", ps.estimated_normal_print_time);
fill_labels(ps.estimated_normal_custom_gcode_print_times, new_label, info_text);
}
if (ps.estimated_silent_print_time != "N/A") {
new_label += from_u8((boost::format("\n - %1%") % _utf8(L("stealth mode"))).str());
info_text += from_u8((boost::format("\n%1%") % ps.estimated_silent_print_time).str());
new_label += format_wxstr("\n - %1%", _L("stealth mode"));
info_text += format_wxstr("\n%1%", ps.estimated_silent_print_time);
fill_labels(ps.estimated_silent_custom_gcode_print_times, new_label, info_text);
}
p->sliced_info->SetTextAndShow(siEstimatedTime, info_text, new_label);
@ -1397,11 +1397,11 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
wxString snapshot_label;
assert(! paths.empty());
if (paths.size() == 1) {
snapshot_label = _(L("Load File"));
snapshot_label = _L("Load File");
snapshot_label += ": ";
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
} else {
snapshot_label = _(L("Load Files"));
snapshot_label = _L("Load Files");
snapshot_label += ": ";
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
for (size_t i = 1; i < paths.size(); ++ i) {
@ -2201,11 +2201,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this](RemovableDriveEjectEvent &evt) {
if (evt.data.second) {
this->show_action_buttons(this->ready_to_slice);
Slic3r::GUI::show_info(this->q, (boost::format(_utf8(L("Unmounting successful. The device %s(%s) can now be safely removed from the computer.")))
% evt.data.first.name % evt.data.first.path).str());
Slic3r::GUI::show_info(this->q, format_wxstr(_L("Unmounting successful. The device %s(%s) can now be safely removed from the computer."),
evt.data.first.name, evt.data.first.path));
} else
Slic3r::GUI::show_info(this->q, (boost::format(_utf8(L("Ejecting of device %s(%s) has failed.")))
% evt.data.first.name % evt.data.first.path).str());
Slic3r::GUI::show_info(this->q, format_wxstr(_L("Ejecting of device %s(%s) has failed."),
evt.data.first.name, evt.data.first.path));
});
this->q->Bind(EVT_REMOVABLE_DRIVES_CHANGED, [this](RemovableDrivesChangedEvent &) { this->show_action_buttons(this->ready_to_slice); });
// Start the background thread and register this window as a target for update events.
@ -2217,7 +2217,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
#endif /* _WIN32 */
// Initialize the Undo / Redo stack with a first snapshot.
this->take_snapshot(_(L("New Project")));
this->take_snapshot(_L("New Project"));
}
Plater::priv::~priv()
@ -2331,7 +2331,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
}
const auto loading = _(L("Loading")) + dots;
const auto loading = _L("Loading") + dots;
wxProgressDialog dlg(loading, loading);
dlg.Pulse();
@ -2341,7 +2341,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
for (size_t i = 0; i < input_files.size(); i++) {
const auto &path = input_files[i];
const auto filename = path.filename();
const auto dlg_info = from_u8((boost::format(_utf8(L("Processing input file %s"))) % from_path(filename)).str()) + "\n";
const auto dlg_info = format_wxstr(_L("Processing input file %s"), from_path(filename)) + "\n";
dlg.Update(100 * i / input_files.size(), dlg_info);
const bool type_3mf = std::regex_match(path.string(), pattern_3mf);
@ -2369,9 +2369,9 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
if (object->volumes.size() > 1)
{
Slic3r::GUI::show_info(nullptr,
_(L("You cannot load SLA project with a multi-part object on the bed")) + "\n\n" +
_(L("Please check your object list before preset changing.")),
_(L("Attention!")));
_L("You cannot load SLA project with a multi-part object on the bed") + "\n\n" +
_L("Please check your object list before preset changing."),
_L("Attention!"));
return obj_idxs;
}
}
@ -2414,19 +2414,19 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
if (! is_project_file) {
if (model.looks_like_multipart_object()) {
wxMessageDialog msg_dlg(q, _(L(
wxMessageDialog msg_dlg(q, _L(
"This file contains several objects positioned at multiple heights.\n"
"Instead of considering them as multiple objects, should I consider\n"
"this file as a single object having multiple parts?")) + "\n",
_(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO);
"this file as a single object having multiple parts?") + "\n",
_L("Multi-part object detected"), wxICON_WARNING | wxYES | wxNO);
if (msg_dlg.ShowModal() == wxID_YES) {
model.convert_multipart_object(nozzle_dmrs->values.size());
}
}
}
else if ((wxGetApp().get_mode() == comSimple) && (type_3mf || type_any_amf) && model_has_advanced_features(model)) {
wxMessageDialog msg_dlg(q, _(L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?"))+"\n",
_(L("Detected advanced data")), wxICON_WARNING | wxYES | wxNO);
wxMessageDialog msg_dlg(q, _L("This file cannot be loaded in a simple mode. Do you want to switch to an advanced mode?")+"\n",
_L("Detected advanced data"), wxICON_WARNING | wxYES | wxNO);
if (msg_dlg.ShowModal() == wxID_YES)
{
Slic3r::GUI::wxGetApp().save_mode(comAdvanced);
@ -2448,8 +2448,8 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
for (auto obj : model.objects)
if ( obj->volumes.size()>1 ) {
Slic3r::GUI::show_error(nullptr,
from_u8((boost::format(_utf8(L("You can't to add the object(s) from %s because of one or some of them is(are) multi-part")))
% from_path(filename)).str()));
format_wxstr(_L("You can't to add the object(s) from %s because of one or some of them is(are) multi-part"),
from_path(filename)));
return obj_idxs;
}
}
@ -2467,11 +2467,11 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
}
if (new_model != nullptr && new_model->objects.size() > 1) {
wxMessageDialog msg_dlg(q, _(L(
wxMessageDialog msg_dlg(q, _L(
"Multiple objects were loaded for a multi-material printer.\n"
"Instead of considering them as multiple objects, should I consider\n"
"these files to represent a single object having multiple parts?")) + "\n",
_(L("Multi-part object detected")), wxICON_WARNING | wxYES | wxNO);
"these files to represent a single object having multiple parts?") + "\n",
_L("Multi-part object detected"), wxICON_WARNING | wxYES | wxNO);
if (msg_dlg.ShowModal() == wxID_YES) {
new_model->convert_multipart_object(nozzle_dmrs->values.size());
}
@ -2484,7 +2484,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
{
wxGetApp().app_config->update_skein_dir(input_files[input_files.size() - 1].parent_path().string());
// XXX: Plater.pm had @loaded_files, but didn't seem to fill them with the filenames...
statusbar()->set_status_text(_(L("Loaded")));
statusbar()->set_status_text(_L("Loaded"));
}
// automatic selection of added objects
@ -2586,8 +2586,8 @@ std::vector<size_t> Plater::priv::load_model_objects(const ModelObjectPtrs &mode
if (scaled_down) {
GUI::show_info(q,
_(L("Your object appears to be too large, so it was automatically scaled down to fit your print bed.")),
_(L("Object too large?")));
_L("Your object appears to be too large, so it was automatically scaled down to fit your print bed."),
_L("Object too large?"));
}
for (const size_t idx : obj_idxs) {
@ -2649,26 +2649,26 @@ wxString Plater::priv::get_export_file(GUI::FileType file_type)
case FT_STL:
{
output_file.replace_extension("stl");
dlg_title = _(L("Export STL file:"));
dlg_title = _L("Export STL file:");
break;
}
case FT_AMF:
{
// XXX: Problem on OS X with double extension?
output_file.replace_extension("zip.amf");
dlg_title = _(L("Export AMF file:"));
dlg_title = _L("Export AMF file:");
break;
}
case FT_3MF:
{
output_file.replace_extension("3mf");
dlg_title = _(L("Save file as:"));
dlg_title = _L("Save file as:");
break;
}
case FT_OBJ:
{
output_file.replace_extension("obj");
dlg_title = _(L("Export OBJ file:"));
dlg_title = _L("Export OBJ file:");
break;
}
default: break;
@ -2740,15 +2740,12 @@ void Plater::priv::object_list_changed()
void Plater::priv::select_all()
{
// this->take_snapshot(_(L("Select All")));
view3D->select_all();
this->sidebar->obj_list()->update_selections();
}
void Plater::priv::deselect_all()
{
// this->take_snapshot(_(L("Deselect All")));
view3D->deselect_all();
}
@ -2770,7 +2767,7 @@ void Plater::priv::remove(size_t obj_idx)
void Plater::priv::delete_object_from_model(size_t obj_idx)
{
wxString snapshot_label = _(L("Delete Object"));
wxString snapshot_label = _L("Delete Object");
if (! model.objects[obj_idx]->name.empty())
snapshot_label += ": " + wxString::FromUTF8(model.objects[obj_idx]->name.c_str());
Plater::TakeSnapshot snapshot(q, snapshot_label);
@ -2781,7 +2778,7 @@ void Plater::priv::delete_object_from_model(size_t obj_idx)
void Plater::priv::reset()
{
Plater::TakeSnapshot snapshot(q, _(L("Reset Project")));
Plater::TakeSnapshot snapshot(q, _L("Reset Project"));
set_project_filename(wxEmptyString);
@ -2812,7 +2809,7 @@ void Plater::priv::mirror(Axis axis)
void Plater::priv::arrange()
{
this->take_snapshot(_(L("Arrange")));
this->take_snapshot(_L("Arrange"));
m_ui_jobs.start(Jobs::Arrange);
}
@ -2820,7 +2817,7 @@ void Plater::priv::arrange()
// This method will find an optimal orientation for the currently selected item
// Very similar in nature to the arrange method above...
void Plater::priv::sla_optimize_rotation() {
this->take_snapshot(_(L("Optimize Rotation")));
this->take_snapshot(_L("Optimize Rotation"));
m_ui_jobs.start(Jobs::Rotoptimize);
}
@ -2866,7 +2863,7 @@ void Plater::priv::find_new_position(const ModelInstancePtrs &instances,
}
void Plater::priv::ArrangeJob::process() {
static const auto arrangestr = _(L("Arranging"));
static const auto arrangestr = _L("Arranging");
// FIXME: I don't know how to obtain the minimum distance, it depends
// on printer technology. I guess the following should work but it crashes.
@ -2893,14 +2890,14 @@ void Plater::priv::ArrangeJob::process() {
}, stopfn);
} catch (std::exception & /*e*/) {
GUI::show_error(plater().q,
_(L("Could not arrange model objects! "
"Some geometries may be invalid.")));
_L("Could not arrange model objects! "
"Some geometries may be invalid."));
}
// finalize just here.
update_status(int(count),
was_canceled() ? _(L("Arranging canceled."))
: _(L("Arranging done.")));
was_canceled() ? _L("Arranging canceled.")
: _L("Arranging done."));
}
void Plater::priv::RotoptimizeJob::process()
@ -2916,7 +2913,7 @@ void Plater::priv::RotoptimizeJob::process()
[this](unsigned s) {
if (s < 100)
update_status(int(s),
_(L("Searching for optimal orientation")));
_L("Searching for optimal orientation"));
},
[this]() { return was_canceled(); });
@ -2949,8 +2946,8 @@ void Plater::priv::RotoptimizeJob::process()
}
update_status(100,
was_canceled() ? _(L("Orientation search canceled."))
: _(L("Orientation found.")));
was_canceled() ? _L("Orientation search canceled.")
: _L("Orientation found."));
}
@ -2967,7 +2964,7 @@ void Plater::priv::split_object()
if (current_model_object->volumes.size() > 1)
{
Slic3r::GUI::warning_catcher(q, _(L("The selected object can't be split because it contains more than one volume/material.")));
Slic3r::GUI::warning_catcher(q, _L("The selected object can't be split because it contains more than one volume/material."));
return;
}
@ -2975,10 +2972,10 @@ void Plater::priv::split_object()
ModelObjectPtrs new_objects;
current_model_object->split(&new_objects);
if (new_objects.size() == 1)
Slic3r::GUI::warning_catcher(q, _(L("The selected object couldn't be split because it contains only one part.")));
Slic3r::GUI::warning_catcher(q, _L("The selected object couldn't be split because it contains only one part."));
else
{
Plater::TakeSnapshot snapshot(q, _(L("Split to Objects")));
Plater::TakeSnapshot snapshot(q, _L("Split to Objects"));
unsigned int counter = 1;
for (ModelObject* m : new_objects)
@ -3103,7 +3100,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
if ((return_state & UPDATE_BACKGROUND_PROCESS_INVALID) != 0)
{
// Validation of the background data failed.
const wxString invalid_str = _(L("Invalid data"));
const wxString invalid_str = _L("Invalid data");
for (auto btn : {ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport})
sidebar->set_btn_label(btn, invalid_str);
}
@ -3112,13 +3109,13 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool
// Background data is valid.
if ((return_state & UPDATE_BACKGROUND_PROCESS_RESTART) != 0 ||
(return_state & UPDATE_BACKGROUND_PROCESS_REFRESH_SCENE) != 0 )
this->statusbar()->set_status_text(_(L("Ready to slice")));
this->statusbar()->set_status_text(_L("Ready to slice"));
sidebar->set_btn_label(ActionButtonType::abExport, _(label_btn_export));
sidebar->set_btn_label(ActionButtonType::abSendGCode, _(label_btn_send));
const wxString slice_string = background_process.running() && wxGetApp().get_mode() == comSimple ?
_(L("Slicing")) + dots : _(L("Slice now"));
_L("Slicing") + dots : _L("Slice now");
sidebar->set_btn_label(ActionButtonType::abReslice, slice_string);
if (background_process.finished())
@ -3150,7 +3147,7 @@ bool Plater::priv::restart_background_process(unsigned int state)
// The print is valid and it can be started.
if (this->background_process.start()) {
this->statusbar()->set_cancel_callback([this]() {
this->statusbar()->set_status_text(_(L("Cancelling")));
this->statusbar()->set_status_text(_L("Cancelling"));
this->background_process.stop();
});
return true;
@ -3167,7 +3164,7 @@ void Plater::priv::export_gcode(fs::path output_path, bool output_path_on_remova
return;
if (background_process.is_export_scheduled()) {
GUI::show_error(q, _(L("Another export job is currently running.")));
GUI::show_error(q, _L("Another export job is currently running."));
return;
}
@ -3222,7 +3219,7 @@ void Plater::priv::update_sla_scene()
void Plater::priv::reload_from_disk()
{
Plater::TakeSnapshot snapshot(q, _(L("Reload from disk")));
Plater::TakeSnapshot snapshot(q, _L("Reload from disk"));
const Selection& selection = get_selection();
@ -3283,7 +3280,7 @@ void Plater::priv::reload_from_disk()
{
// ask user to select the missing file
fs::path search = missing_input_paths.back();
wxString title = _(L("Please select the file to reload"));
wxString title = _L("Please select the file to reload");
#if defined(__APPLE__)
title += " (" + from_u8(search.filename().string()) + ")";
#endif // __APPLE__
@ -3318,7 +3315,7 @@ void Plater::priv::reload_from_disk()
}
else
{
wxString message = _(L("It is not allowed to change the file to reload")) + " (" + from_u8(search.filename().string()) + ").\n" + _(L("Do you want to retry")) + " ?";
wxString message = _L("It is not allowed to change the file to reload") + " (" + from_u8(search.filename().string()) + ").\n" + _L("Do you want to retry") + " ?";
wxMessageDialog dlg(q, message, wxMessageBoxCaptionStr, wxYES_NO | wxYES_DEFAULT | wxICON_QUESTION);
if (dlg.ShowModal() != wxID_YES)
return;
@ -3336,7 +3333,7 @@ void Plater::priv::reload_from_disk()
const auto& path = input_paths[i].string();
wxBusyCursor wait;
wxBusyInfo info(_(L("Reload from:")) + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
wxBusyInfo info(_L("Reload from:") + " " + from_u8(path), q->get_current_canvas3D()->get_wxglcanvas());
Model new_model;
try
@ -3425,12 +3422,12 @@ void Plater::priv::reload_from_disk()
if (!fail_list.empty())
{
wxString message = _(L("Unable to reload:")) + "\n";
wxString message = _L("Unable to reload:") + "\n";
for (const wxString& s : fail_list)
{
message += s + "\n";
}
wxMessageDialog dlg(q, message, _(L("Error during reload")), wxOK | wxOK_DEFAULT | wxICON_WARNING);
wxMessageDialog dlg(q, message, _L("Error during reload"), wxOK | wxOK_DEFAULT | wxICON_WARNING);
dlg.ShowModal();
}
@ -3449,7 +3446,7 @@ void Plater::priv::reload_all_from_disk()
if (model.objects.empty())
return;
Plater::TakeSnapshot snapshot(q, _(L("Reload all from disk")));
Plater::TakeSnapshot snapshot(q, _L("Reload all from disk"));
Plater::SuppressSnapshots suppress(q);
Selection& selection = get_selection();
@ -3470,7 +3467,7 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* =
if (obj_idx < 0)
return;
Plater::TakeSnapshot snapshot(q, _(L("Fix Throught NetFabb")));
Plater::TakeSnapshot snapshot(q, _L("Fix Throught NetFabb"));
fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx);
this->update();
@ -3669,7 +3666,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
if (error) {
wxString message = evt.GetString();
if (message.IsEmpty())
message = _(L("Export failed"));
message = _L("Export failed");
if (q->m_tracking_popup_menu)
// We don't want to pop-up a message box when tracking a pop-up menu.
// We postpone the error message instead.
@ -3679,7 +3676,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
this->statusbar()->set_status_text(message);
}
if (canceled)
this->statusbar()->set_status_text(_(L("Cancelled")));
this->statusbar()->set_status_text(_L("Cancelled"));
this->sidebar->show_sliced_info_sizer(success);
@ -3742,8 +3739,6 @@ void Plater::priv::on_action_layersediting(SimpleEvent&)
void Plater::priv::on_object_select(SimpleEvent& evt)
{
// this->take_snapshot(_(L("Object Selection")));
wxGetApp().obj_list()->update_selections();
selection_changed();
}
@ -3793,7 +3788,7 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
*/
const MenuIdentifier id = printer_technology == ptSLA ? miObjectSLA : miObjectFFF;
if (wxGetApp().get_mode() == comSimple) {
if (menu->FindItem(_(L("Add instance"))) != wxNOT_FOUND)
if (menu->FindItem(_L("Add instance")) != wxNOT_FOUND)
{
/* Detach an items from the menu, but don't delete them
* so that they can be added back later
@ -3805,7 +3800,7 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
}
}
else {
if (menu->FindItem(_(L("Add instance"))) == wxNOT_FOUND)
if (menu->FindItem(_L("Add instance")) == wxNOT_FOUND)
{
// Prepend items to the menu, if those aren't not there
menu->Prepend(items_set_number_of_copies[id]);
@ -3934,20 +3929,20 @@ void Plater::priv::set_project_filename(const wxString& filename)
bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/)
{
if (is_part) {
append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected object"),
[this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q);
append_menu_item(menu, wxID_ANY, _(L("Reload from disk")), _(L("Reload the selected volumes from disk")),
append_menu_item(menu, wxID_ANY, _L("Reload from disk"), _L("Reload the selected volumes from disk"),
[this](wxCommandEvent&) { q->reload_from_disk(); }, "", menu, [this]() { return can_reload_from_disk(); }, q);
sidebar->obj_list()->append_menu_item_export_stl(menu);
}
else {
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _(L("Add instance")) + "\t+", _(L("Add one more instance of the selected object")),
wxMenuItem* item_increase = append_menu_item(menu, wxID_ANY, _L("Add instance") + "\t+", _L("Add one more instance of the selected object"),
[this](wxCommandEvent&) { q->increase_instances(); }, "add_copies", nullptr, [this]() { return can_increase_instances(); }, q);
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _(L("Remove instance")) + "\t-", _(L("Remove one instance of the selected object")),
wxMenuItem* item_decrease = append_menu_item(menu, wxID_ANY, _L("Remove instance") + "\t-", _L("Remove one instance of the selected object"),
[this](wxCommandEvent&) { q->decrease_instances(); }, "remove_copies", nullptr, [this]() { return can_decrease_instances(); }, q);
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _(L("Set number of instances")) + dots, _(L("Change the number of instances of the selected object")),
wxMenuItem* item_set_number_of_copies = append_menu_item(menu, wxID_ANY, _L("Set number of instances") + dots, _L("Change the number of instances of the selected object"),
[this](wxCommandEvent&) { q->set_number_of_copies(); }, "number_of_copies", nullptr, [this]() { return can_increase_instances(); }, q);
@ -3956,7 +3951,7 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
items_set_number_of_copies.push_back(item_set_number_of_copies);
// Delete menu was moved to be after +/- instace to make it more difficult to be selected by mistake.
append_menu_item(menu, wxID_ANY, _(L("Delete")) + "\tDel", _(L("Remove the selected object")),
append_menu_item(menu, wxID_ANY, _L("Delete") + "\tDel", _L("Remove the selected object"),
[this](wxCommandEvent&) { q->remove_selected(); }, "delete", nullptr, [this]() { return can_delete(); }, q);
menu->AppendSeparator();
@ -3966,10 +3961,10 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
wxMenuItem* menu_item_printable = sidebar->obj_list()->append_menu_item_printable(menu, q);
menu->AppendSeparator();
append_menu_item(menu, wxID_ANY, _(L("Reload from disk")), _(L("Reload the selected object from disk")),
append_menu_item(menu, wxID_ANY, _L("Reload from disk"), _L("Reload the selected object from disk"),
[this](wxCommandEvent&) { reload_from_disk(); }, "", nullptr, [this]() { return can_reload_from_disk(); }, q);
append_menu_item(menu, wxID_ANY, _(L("Export as STL")) + dots, _(L("Export the selected object as STL file")),
append_menu_item(menu, wxID_ANY, _L("Export as STL") + dots, _L("Export the selected object as STL file"),
[this](wxCommandEvent&) { q->export_stl(false, true); }, "", nullptr,
[this]() {
const Selection& selection = get_selection();
@ -3998,14 +3993,14 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
if (mirror_menu == nullptr)
return false;
append_menu_item(mirror_menu, wxID_ANY, _(L("Along X axis")), _(L("Mirror the selected object along the X axis")),
append_menu_item(mirror_menu, wxID_ANY, _L("Along X axis"), _L("Mirror the selected object along the X axis"),
[this](wxCommandEvent&) { mirror(X); }, "mark_X", menu);
append_menu_item(mirror_menu, wxID_ANY, _(L("Along Y axis")), _(L("Mirror the selected object along the Y axis")),
append_menu_item(mirror_menu, wxID_ANY, _L("Along Y axis"), _L("Mirror the selected object along the Y axis"),
[this](wxCommandEvent&) { mirror(Y); }, "mark_Y", menu);
append_menu_item(mirror_menu, wxID_ANY, _(L("Along Z axis")), _(L("Mirror the selected object along the Z axis")),
append_menu_item(mirror_menu, wxID_ANY, _L("Along Z axis"), _L("Mirror the selected object along the Z axis"),
[this](wxCommandEvent&) { mirror(Z); }, "mark_Z", menu);
append_submenu(menu, mirror_menu, wxID_ANY, _(L("Mirror")), _(L("Mirror the selected object")), "",
append_submenu(menu, mirror_menu, wxID_ANY, _L("Mirror"), _L("Mirror the selected object"), "",
[this]() { return can_mirror(); }, q);
return true;
@ -4017,12 +4012,12 @@ bool Plater::priv::complit_init_object_menu()
if (split_menu == nullptr)
return false;
append_menu_item(split_menu, wxID_ANY, _(L("To objects")), _(L("Split the selected object into individual objects")),
append_menu_item(split_menu, wxID_ANY, _L("To objects"), _L("Split the selected object into individual objects"),
[this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", &object_menu, [this]() { return can_split(); }, q);
append_menu_item(split_menu, wxID_ANY, _(L("To parts")), _(L("Split the selected object into individual sub-parts")),
append_menu_item(split_menu, wxID_ANY, _L("To parts"), _L("Split the selected object into individual sub-parts"),
[this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", &object_menu, [this]() { return can_split(); }, q);
append_submenu(&object_menu, split_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object")), "",
append_submenu(&object_menu, split_menu, wxID_ANY, _L("Split"), _L("Split the selected object"), "",
[this]() { return can_split() && wxGetApp().get_mode() > comSimple; }, q);
object_menu.AppendSeparator();
@ -4037,13 +4032,13 @@ bool Plater::priv::complit_init_object_menu()
bool Plater::priv::complit_init_sla_object_menu()
{
append_menu_item(&sla_object_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual objects")),
append_menu_item(&sla_object_menu, wxID_ANY, _L("Split"), _L("Split the selected object into individual objects"),
[this](wxCommandEvent&) { split_object(); }, "split_object_SMALL", nullptr, [this]() { return can_split(); }, q);
sla_object_menu.AppendSeparator();
// Add the automatic rotation sub-menu
append_menu_item(&sla_object_menu, wxID_ANY, _(L("Optimize orientation")), _(L("Optimize the rotation of the object for better print results.")),
append_menu_item(&sla_object_menu, wxID_ANY, _L("Optimize orientation"), _L("Optimize the rotation of the object for better print results."),
[this](wxCommandEvent&) { sla_optimize_rotation(); });
return true;
@ -4051,7 +4046,7 @@ bool Plater::priv::complit_init_sla_object_menu()
bool Plater::priv::complit_init_part_menu()
{
append_menu_item(&part_menu, wxID_ANY, _(L("Split")), _(L("Split the selected object into individual sub-parts")),
append_menu_item(&part_menu, wxID_ANY, _L("Split"), _L("Split the selected object into individual sub-parts"),
[this](wxCommandEvent&) { split_volume(); }, "split_parts_SMALL", nullptr, [this]() { return can_split(); }, q);
part_menu.AppendSeparator();
@ -4417,8 +4412,8 @@ void Plater::priv::undo_redo_to(std::vector<UndoRedo::Snapshot>::const_iterator
if (printer_technology_changed) {
// Switching the printer technology when jumping forwards / backwards in time. Switch to the last active printer profile of the other type.
std::string s_pt = (it_snapshot->snapshot_data.printer_technology == ptFFF) ? "FFF" : "SLA";
if (! wxGetApp().check_unsaved_changes(from_u8((boost::format(_utf8(
L("%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."))) % s_pt).str())))
if (! wxGetApp().check_unsaved_changes(format_wxstr(_L(
"%1% printer was active at the time the target Undo / Redo snapshot was taken. Switching to %1% printer requires reloading of %1% presets."), s_pt)))
// Don't switch the profiles.
return;
}
@ -4594,7 +4589,7 @@ void Plater::load_project(const wxString& filename)
return;
// Take the Undo / Redo snapshot.
Plater::TakeSnapshot snapshot(this, _(L("Load Project")) + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str()));
Plater::TakeSnapshot snapshot(this, _L("Load Project") + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str()));
p->reset();
@ -4622,11 +4617,11 @@ void Plater::add_model()
wxString snapshot_label;
assert(! paths.empty());
if (paths.size() == 1) {
snapshot_label = _(L("Import Object"));
snapshot_label = _L("Import Object");
snapshot_label += ": ";
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
} else {
snapshot_label = _(L("Import Objects"));
snapshot_label = _L("Import Objects");
snapshot_label += ": ";
snapshot_label += wxString::FromUTF8(paths.front().filename().string().c_str());
for (size_t i = 1; i < paths.size(); ++ i) {
@ -4695,7 +4690,7 @@ void Plater::remove(size_t obj_idx) { p->remove(obj_idx); }
void Plater::reset() { p->reset(); }
void Plater::reset_with_confirm()
{
if (wxMessageDialog((wxWindow*)this, _(L("All objects will be removed, continue?")), wxString(SLIC3R_APP_NAME) + " - " + _(L("Delete all")), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES)
if (wxMessageDialog((wxWindow*)this, _L("All objects will be removed, continue?"), wxString(SLIC3R_APP_NAME) + " - " + _L("Delete all"), wxYES_NO | wxCANCEL | wxYES_DEFAULT | wxCENTRE).ShowModal() == wxID_YES)
reset();
}
@ -4703,7 +4698,7 @@ void Plater::delete_object_from_model(size_t obj_idx) { p->delete_object_from_mo
void Plater::remove_selected()
{
Plater::TakeSnapshot snapshot(this, _(L("Delete Selected Objects")));
Plater::TakeSnapshot snapshot(this, _L("Delete Selected Objects"));
this->p->view3D->delete_selected();
}
@ -4711,7 +4706,7 @@ void Plater::increase_instances(size_t num)
{
if (! can_increase_instances()) { return; }
Plater::TakeSnapshot snapshot(this, _(L("Increase Instances")));
Plater::TakeSnapshot snapshot(this, _L("Increase Instances"));
int obj_idx = p->get_selected_object_idx();
@ -4746,7 +4741,7 @@ void Plater::decrease_instances(size_t num)
{
if (! can_decrease_instances()) { return; }
Plater::TakeSnapshot snapshot(this, _(L("Decrease Instances")));
Plater::TakeSnapshot snapshot(this, _L("Decrease Instances"));
int obj_idx = p->get_selected_object_idx();
@ -4777,12 +4772,12 @@ void Plater::set_number_of_copies(/*size_t num*/)
ModelObject* model_object = p->model.objects[obj_idx];
const int num = wxGetNumberFromUser( " ", _(L("Enter the number of copies:")),
_(L("Copies of the selected object")), model_object->instances.size(), 0, 1000, this );
const int num = wxGetNumberFromUser( " ", _L("Enter the number of copies:"),
_L("Copies of the selected object"), model_object->instances.size(), 0, 1000, this );
if (num < 0)
return;
Plater::TakeSnapshot snapshot(this, wxString::Format(_(L("Set numbers of copies to %d")), num));
Plater::TakeSnapshot snapshot(this, wxString::Format(_L("Set numbers of copies to %d"), num));
int diff = num - (int)model_object->instances.size();
if (diff > 0)
@ -4812,7 +4807,7 @@ void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_uppe
return;
}
Plater::TakeSnapshot snapshot(this, _(L("Cut by Plane")));
Plater::TakeSnapshot snapshot(this, _L("Cut by Plane"));
wxBusyCursor wait;
const auto new_objects = object->cut(instance_idx, z, keep_upper, keep_lower, rotate_lower);
@ -4863,7 +4858,7 @@ void Plater::export_gcode(bool prefer_removable)
fs::path output_path;
{
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _(L("Save G-code file as:")) : _(L("Save SL1 file as:")),
wxFileDialog dlg(this, (printer_technology() == ptFFF) ? _L("Save G-code file as:") : _L("Save SL1 file as:"),
start_dir,
from_path(default_output_file.filename()),
GUI::file_wildcards((printer_technology() == ptFFF) ? FT_GCODE : FT_PNGZIP, default_output_file.extension().string()),
@ -4998,7 +4993,7 @@ void Plater::export_stl(bool extended, bool selection_only)
}
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("STL file exported to %s"))) % path).str()));
p->statusbar()->set_status_text(format_wxstr(_L("STL file exported to %s"), path));
}
void Plater::export_amf()
@ -5015,10 +5010,10 @@ void Plater::export_amf()
bool full_pathnames = wxGetApp().app_config->get("export_sources_full_pathnames") == "1";
if (Slic3r::store_amf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames)) {
// Success
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("AMF file exported to %s"))) % path).str()));
p->statusbar()->set_status_text(format_wxstr(_L("AMF file exported to %s"), path));
} else {
// Failure
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("Error exporting AMF file %s"))) % path).str()));
p->statusbar()->set_status_text(format_wxstr(_L("Error exporting AMF file %s"), path));
}
}
@ -5047,12 +5042,12 @@ void Plater::export_3mf(const boost::filesystem::path& output_path)
p->generate_thumbnail(thumbnail_data, THUMBNAIL_SIZE_3MF.first, THUMBNAIL_SIZE_3MF.second, false, true, true, true);
if (Slic3r::store_3mf(path_u8.c_str(), &p->model, export_config ? &cfg : nullptr, full_pathnames, &thumbnail_data)) {
// Success
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("3MF file exported to %s"))) % path).str()));
p->statusbar()->set_status_text(format_wxstr(_L("3MF file exported to %s"), path));
p->set_project_filename(path);
}
else {
// Failure
p->statusbar()->set_status_text(from_u8((boost::format(_utf8(L("Error exporting 3MF file %s"))) % path).str()));
p->statusbar()->set_status_text(format_wxstr(_L("Error exporting 3MF file %s"), path));
}
}
@ -5112,10 +5107,10 @@ void Plater::reslice()
if (p->background_process.running())
{
if (wxGetApp().get_mode() == comSimple)
p->sidebar->set_btn_label(ActionButtonType::abReslice, _(L("Slicing")) + dots);
p->sidebar->set_btn_label(ActionButtonType::abReslice, _L("Slicing") + dots);
else
{
p->sidebar->set_btn_label(ActionButtonType::abReslice, _(L("Slice now")));
p->sidebar->set_btn_label(ActionButtonType::abReslice, _L("Slice now"));
p->show_action_buttons(false);
}
}
@ -5602,7 +5597,7 @@ void Plater::paste_from_clipboard()
if (!can_paste_from_clipboard())
return;
Plater::TakeSnapshot snapshot(this, _(L("Paste From Clipboard")));
Plater::TakeSnapshot snapshot(this, _L("Paste From Clipboard"));
p->view3D->get_canvas3d()->get_selection().paste_from_clipboard();
}

65
src/slic3r/GUI/format.hpp Normal file
View File

@ -0,0 +1,65 @@
#ifndef slic3r_GUI_format_hpp_
#define slic3r_GUI_format_hpp_
// Functional wrapper around boost::format.
// One day we may replace this wrapper with C++20 format
// https://en.cppreference.com/w/cpp/utility/format/format
// though C++20 format uses a different template pattern for position independent parameters.
// This wrapper also manages implicit conversion from wxString to UTF8 and format_wxstr() variants are provided to format into wxString.
#include <libslic3r/format.hpp>
namespace Slic3r {
namespace GUI {
// Format input mixing UTF8 encoded strings (const char*, std::string) and wxStrings, return a wxString.
template<typename... TArgs>
inline wxString format_wxstr(const char* fmt, TArgs&&... args) {
boost::format message(fmt);
return wxString::FromUTF8(Slic3r::internal::format::format_recursive(message, std::forward<TArgs>(args)...).c_str());
}
template<typename... TArgs>
inline wxString format_wxstr(const std::string& fmt, TArgs&&... args) {
boost::format message(fmt);
return wxString::FromUTF8(Slic3r::internal::format::format_recursive(message, std::forward<TArgs>(args)...).c_str());
}
template<typename... TArgs>
inline wxString format_wxstr(const wxString& fmt, TArgs&&... args) {
return format_wxstr(fmt.ToUTF8().data());
}
template<typename... TArgs>
inline std::string format(const wxString& fmt, TArgs&&... args) {
return format(fmt.ToUTF8().data());
}
} // namespace GUI
namespace internal {
namespace format {
// Wrapper around wxScopedCharBuffer to indicate that the content is UTF8 formatted.
struct utf8_buffer {
// wxScopedCharBuffer is reference counted, therefore copying by value is cheap.
wxScopedCharBuffer data;
};
// Accept wxString and convert it to UTF8 to be processed by Slic3r::format().
inline const utf8_buffer cook(const wxString &arg) {
return utf8_buffer { arg.ToUTF8() };
}
}
}
} // namespace Slic3r
namespace boost {
namespace io {
namespace detail {
// Adaptor for boost::format to accept wxString converted to UTF8.
inline std::ostream& operator<<(std::ostream& os, const Slic3r::internal::format::utf8_buffer& str) {
os << str.data.data();
return os;
}
}
}
}
#endif /* slic3r_GUI_format_hpp_ */

View File

@ -17,6 +17,7 @@
#include <wx/msgdlg.h>
#include "libslic3r/libslic3r.h"
#include "libslic3r/format.hpp"
#include "libslic3r/Utils.hpp"
#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/I18N.hpp"
@ -54,7 +55,7 @@ void copy_file_fix(const fs::path &source, const fs::path &target)
{
static const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read; // aka 644
BOOST_LOG_TRIVIAL(debug) << boost::format("PresetUpdater: Copying %1% -> %2%") % source % target;
BOOST_LOG_TRIVIAL(debug) << format("PresetUpdater: Copying %1% -> %2%", source, target);
// Make sure the file has correct permission both before and after we copy over it
if (fs::exists(target)) {
@ -190,12 +191,12 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe
{
bool res = false;
fs::path tmp_path = target_path;
tmp_path += (boost::format(".%1%%2%") % get_current_pid() % TMP_EXTENSION).str();
tmp_path += format(".%1%%2%", get_current_pid(), TMP_EXTENSION);
BOOST_LOG_TRIVIAL(info) << boost::format("Get: `%1%`\n\t-> `%2%`\n\tvia tmp path `%3%`")
% url
% target_path.string()
% tmp_path.string();
BOOST_LOG_TRIVIAL(info) << format("Get: `%1%`\n\t-> `%2%`\n\tvia tmp path `%3%`",
url,
target_path.string(),
tmp_path.string());
Http::get(url)
.on_progress([this](Http::Progress, bool &cancel) {
@ -203,10 +204,10 @@ bool PresetUpdater::priv::get_file(const std::string &url, const fs::path &targe
})
.on_error([&](std::string body, std::string error, unsigned http_status) {
(void)body;
BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%")
% url
% http_status
% error;
BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%",
url,
http_status,
error);
})
.on_complete([&](std::string body, unsigned /* http_status */) {
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
@ -235,7 +236,7 @@ void PresetUpdater::priv::sync_version() const
{
if (! enabled_version_check) { return; }
BOOST_LOG_TRIVIAL(info) << boost::format("Downloading %1% online version from: `%2%`") % SLIC3R_APP_NAME % version_check_url;
BOOST_LOG_TRIVIAL(info) << format("Downloading %1% online version from: `%2%`", SLIC3R_APP_NAME, version_check_url);
Http::get(version_check_url)
.size_limit(SLIC3R_VERSION_BODY_MAX)
@ -244,10 +245,10 @@ void PresetUpdater::priv::sync_version() const
})
.on_error([&](std::string body, std::string error, unsigned http_status) {
(void)body;
BOOST_LOG_TRIVIAL(error) << boost::format("Error getting: `%1%`: HTTP %2%, %3%")
% version_check_url
% http_status
% error;
BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%",
version_check_url,
http_status,
error);
})
.on_complete([&](std::string body, unsigned /* http_status */) {
boost::trim(body);
@ -257,11 +258,11 @@ void PresetUpdater::priv::sync_version() const
}
if (! Semver::parse(body)) {
BOOST_LOG_TRIVIAL(warning) << boost::format("Received invalid contents from `%1%`: Not a correct semver: `%2%`") % SLIC3R_APP_NAME % body;
BOOST_LOG_TRIVIAL(warning) << format("Received invalid contents from `%1%`: Not a correct semver: `%2%`", SLIC3R_APP_NAME, body);
return;
}
BOOST_LOG_TRIVIAL(info) << boost::format("Got %1% online version: `%2%`. Sending to GUI thread...") % SLIC3R_APP_NAME % body;
BOOST_LOG_TRIVIAL(info) << format("Got %1% online version: `%2%`. Sending to GUI thread...", SLIC3R_APP_NAME, body);
wxCommandEvent* evt = new wxCommandEvent(EVT_SLIC3R_VERSION_ONLINE);
evt->SetString(GUI::from_u8(body));
@ -315,11 +316,11 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors)
try {
new_index.load(idx_path_temp);
} catch (const std::exception & /* err */) {
BOOST_LOG_TRIVIAL(error) << boost::format("Could not load downloaded index %1% for vendor %2%: invalid index?") % idx_path_temp % vendor.name;
BOOST_LOG_TRIVIAL(error) << format("Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_temp, vendor.name);
continue;
}
if (new_index.version() < index.version()) {
BOOST_LOG_TRIVIAL(warning) << boost::format("The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.") % idx_path_temp % vendor.name;
BOOST_LOG_TRIVIAL(warning) << format("The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.", idx_path_temp, vendor.name);
continue;
}
Slic3r::rename_file(idx_path_temp, idx_path);
@ -331,22 +332,22 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors)
// See if a there's a new version to download
const auto recommended_it = index.recommended();
if (recommended_it == index.end()) {
BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index?") % vendor.name;
BOOST_LOG_TRIVIAL(error) << format("No recommended version for vendor: %1%, invalid index?", vendor.name);
continue;
}
const auto recommended = recommended_it->config_version;
BOOST_LOG_TRIVIAL(debug) << boost::format("Got index for vendor: %1%: current version: %2%, recommended version: %3%")
% vendor.name
% vendor.config_version.to_string()
% recommended.to_string();
BOOST_LOG_TRIVIAL(debug) << format("Got index for vendor: %1%: current version: %2%, recommended version: %3%",
vendor.name,
vendor.config_version.to_string(),
recommended.to_string());
if (vendor.config_version >= recommended) { continue; }
// Download a fresh bundle
BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for vendor: " << vendor.name;
const auto bundle_url = (boost::format("%1%/%2%.ini") % vendor.config_update_url % recommended.to_string()).str();
const auto bundle_url = format("%1%/%2%.ini", vendor.config_update_url, recommended.to_string());
const auto bundle_path = cache_path / (vendor.id + ".ini");
if (! get_file(bundle_url, bundle_path)) { continue; }
if (cancel) { return; }
@ -394,7 +395,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
auto bundle_path_idx = vendor_path / idx.path().filename();
if (! fs::exists(bundle_path)) {
BOOST_LOG_TRIVIAL(info) << boost::format("Confing bundle not installed for vendor %1%, skipping: ") % idx.vendor();
BOOST_LOG_TRIVIAL(info) << format("Confing bundle not installed for vendor %1%, skipping: ", idx.vendor());
continue;
}
@ -405,7 +406,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
// from the internet, or installed / updated from the installation resources.
auto recommended = idx.recommended();
if (recommended == idx.end()) {
BOOST_LOG_TRIVIAL(error) << boost::format("No recommended version for vendor: %1%, invalid index? Giving up.") % idx.vendor();
BOOST_LOG_TRIVIAL(error) << format("No recommended version for vendor: %1%, invalid index? Giving up.", idx.vendor());
// XXX: what should be done here?
continue;
}
@ -413,15 +414,15 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
const auto ver_current = idx.find(vp.config_version);
const bool ver_current_found = ver_current != idx.end();
BOOST_LOG_TRIVIAL(debug) << boost::format("Vendor: %1%, version installed: %2%%3%, version cached: %4%")
% vp.name
% vp.config_version.to_string()
% (ver_current_found ? "" : " (not found in index!)")
% recommended->config_version.to_string();
BOOST_LOG_TRIVIAL(debug) << format("Vendor: %1%, version installed: %2%%3%, version cached: %4%",
vp.name,
vp.config_version.to_string(),
(ver_current_found ? "" : " (not found in index!)"),
recommended->config_version.to_string());
if (! ver_current_found) {
// Any published config shall be always found in the latest config index.
auto message = (boost::format("Preset bundle `%1%` version not found in index: %2%") % idx.vendor() % vp.config_version.to_string()).str();
auto message = format("Preset bundle `%1%` version not found in index: %2%", idx.vendor(), vp.config_version.to_string());
BOOST_LOG_TRIVIAL(error) << message;
GUI::show_error(nullptr, message);
continue;
@ -440,7 +441,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
}
if (recommended->config_version < vp.config_version) {
BOOST_LOG_TRIVIAL(warning) << (boost::format("Recommended config version for the currently running PrusaSlicer is older than the currently installed config for vendor %1%. This should not happen.") % idx.vendor()).str();
BOOST_LOG_TRIVIAL(warning) << format("Recommended config version for the currently running PrusaSlicer is older than the currently installed config for vendor %1%. This should not happen.", idx.vendor());
continue;
}
@ -482,7 +483,7 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
found = true;
}
} catch (const std::exception &ex) {
BOOST_LOG_TRIVIAL(info) << boost::format("Failed to load the config bundle `%1%`: %2%") % path_in_cache.string() % ex.what();
BOOST_LOG_TRIVIAL(info) << format("Failed to load the config bundle `%1%`: %2%", path_in_cache.string(), ex.what());
}
}
@ -496,13 +497,13 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
try {
rsrc_vp = VendorProfile::from_ini(path_in_rsrc, false);
} catch (const std::exception &ex) {
BOOST_LOG_TRIVIAL(info) << boost::format("Cannot load the config bundle at `%1%`: %2%") % path_in_rsrc.string() % ex.what();
BOOST_LOG_TRIVIAL(info) << format("Cannot load the config bundle at `%1%`: %2%", path_in_rsrc.string(), ex.what());
}
if (rsrc_vp.valid()) {
try {
rsrc_idx.load(path_idx_in_rsrc);
} catch (const std::exception &ex) {
BOOST_LOG_TRIVIAL(info) << boost::format("Cannot load the config index at `%1%`: %2%") % path_idx_in_rsrc.string() % ex.what();
BOOST_LOG_TRIVIAL(info) << format("Cannot load the config index at `%1%`: %2%", path_idx_in_rsrc.string(), ex.what());
}
recommended = rsrc_idx.recommended();
if (recommended != rsrc_idx.end() && recommended->config_version == rsrc_vp.config_version && recommended->config_version > vp.config_version) {
@ -510,8 +511,8 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
bundle_path_idx_to_install = path_idx_in_rsrc;
found = true;
} else {
BOOST_LOG_TRIVIAL(warning) << (boost::format("The recommended config version for vendor `%1%` in resources does not match the recommended\n"
" config version for this version of PrusaSlicer. Corrupted installation?") % idx.vendor()).str();
BOOST_LOG_TRIVIAL(warning) << format("The recommended config version for vendor `%1%` in resources does not match the recommended\n"
" config version for this version of PrusaSlicer. Corrupted installation?", idx.vendor());
}
}
}
@ -529,11 +530,11 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
/*const auto existing_recommended = existing_idx.recommended(old_slic3r_version);
if (existing_recommended != existing_idx.end() && recommended->config_version == existing_recommended->config_version) {
// The user has already seen (and presumably rejected) this update
BOOST_LOG_TRIVIAL(info) << boost::format("Downloaded index for `%1%` is the same as installed one, not offering an update.") % idx.vendor();
BOOST_LOG_TRIVIAL(info) << format("Downloaded index for `%1%` is the same as installed one, not offering an update.",idx.vendor());
continue;
}*/
} catch (const std::exception &err) {
BOOST_LOG_TRIVIAL(error) << boost::format("Cannot load the installed index at `%1%`: %2%") % bundle_path_idx % err.what();
BOOST_LOG_TRIVIAL(error) << format("Cannot load the installed index at `%1%`: %2%", bundle_path_idx, err.what());
}
}
@ -542,10 +543,10 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
{
const auto recommended_snap = SnapshotDB::singleton().snapshot_with_vendor_preset(vp.name, recommended->config_version);
if (recommended_snap != SnapshotDB::singleton().end()) {
BOOST_LOG_TRIVIAL(info) << boost::format("Bundle update %1% %2% already found in snapshot %3%, skipping...")
% vp.name
% recommended->config_version.to_string()
% recommended_snap->id;
BOOST_LOG_TRIVIAL(info) << format("Bundle update %1% %2% already found in snapshot %3%, skipping...",
vp.name,
recommended->config_version.to_string(),
recommended_snap->id);
continue;
}
}
@ -555,9 +556,9 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
// offered updates and to not offer the same update again if it was cancelled by the user.
copy_file_fix(bundle_path_idx_to_install, bundle_path_idx);
} else {
BOOST_LOG_TRIVIAL(warning) << boost::format("Index for vendor %1% indicates update (%2%) but the new bundle was found neither in cache nor resources")
% idx.vendor()
% recommended->config_version.to_string();
BOOST_LOG_TRIVIAL(warning) << format("Index for vendor %1% indicates update (%2%) but the new bundle was found neither in cache nor resources",
idx.vendor(),
recommended->config_version.to_string());
}
}
@ -572,7 +573,7 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
SnapshotDB::singleton().take_snapshot(*GUI::wxGetApp().app_config, Snapshot::SNAPSHOT_DOWNGRADE);
}
BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% incompatible bundles") % updates.incompats.size();
BOOST_LOG_TRIVIAL(info) << format("Deleting %1% incompatible bundles", updates.incompats.size());
for (auto &incompat : updates.incompats) {
BOOST_LOG_TRIVIAL(info) << '\t' << incompat;
@ -587,7 +588,7 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
SnapshotDB::singleton().take_snapshot(*GUI::wxGetApp().app_config, Snapshot::SNAPSHOT_UPGRADE);
}
BOOST_LOG_TRIVIAL(info) << boost::format("Performing %1% updates") % updates.updates.size();
BOOST_LOG_TRIVIAL(info) << format("Performing %1% updates", updates.updates.size());
for (const auto &update : updates.updates) {
BOOST_LOG_TRIVIAL(info) << '\t' << update;
@ -597,8 +598,7 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
PresetBundle bundle;
bundle.load_configbundle(update.source.string(), PresetBundle::LOAD_CFGBNDLE_SYSTEM);
BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% conflicting presets")
% (bundle.prints.size() + bundle.filaments.size() + bundle.printers.size());
BOOST_LOG_TRIVIAL(info) << format("Deleting %1% conflicting presets", bundle.prints.size() + bundle.filaments.size() + bundle.printers.size());
auto preset_remover = [](const Preset &preset) {
BOOST_LOG_TRIVIAL(info) << '\t' << preset.file;
@ -611,8 +611,8 @@ void PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
// Also apply the `obsolete_presets` property, removing obsolete ini files
BOOST_LOG_TRIVIAL(info) << boost::format("Deleting %1% obsolete presets")
% (bundle.obsolete_presets.prints.size() + bundle.obsolete_presets.filaments.size() + bundle.obsolete_presets.printers.size());
BOOST_LOG_TRIVIAL(info) << format("Deleting %1% obsolete presets",
bundle.obsolete_presets.prints.size() + bundle.obsolete_presets.filaments.size() + bundle.obsolete_presets.printers.size());
auto obsolete_remover = [](const char *subdir, const std::string &preset) {
auto path = fs::path(Slic3r::data_dir()) / subdir / preset;
@ -694,7 +694,7 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver &old_slic3
auto updates = p->get_config_updates(old_slic3r_version);
if (updates.incompats.size() > 0) {
BOOST_LOG_TRIVIAL(info) << boost::format("%1% bundles incompatible. Asking for action...") % updates.incompats.size();
BOOST_LOG_TRIVIAL(info) << format("%1% bundles incompatible. Asking for action...", updates.incompats.size());
std::unordered_map<std::string, wxString> incompats_map;
for (const auto &incompat : updates.incompats) {
@ -702,15 +702,14 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver &old_slic3
const auto max_slic3r = incompat.version.max_slic3r_version;
wxString restrictions;
if (min_slic3r != Semver::zero() && max_slic3r != Semver::inf()) {
restrictions = GUI::from_u8((boost::format(_utf8(L("requires min. %s and max. %s")))
% min_slic3r.to_string()
% max_slic3r.to_string()).str()
);
restrictions = GUI::format_wxstr(_L("requires min. %s and max. %s"),
min_slic3r.to_string(),
max_slic3r.to_string());
} else if (min_slic3r != Semver::zero()) {
restrictions = GUI::from_u8((boost::format(_utf8(L("requires min. %s"))) % min_slic3r.to_string()).str());
restrictions = GUI::format_wxstr(_L("requires min. %s"), min_slic3r.to_string());
BOOST_LOG_TRIVIAL(debug) << "Bundle is not downgrade, user will now have to do whole wizard. This should not happen.";
} else {
restrictions = GUI::from_u8((boost::format(_utf8(L("requires max. %s"))) % max_slic3r.to_string()).str());
restrictions = GUI::format_wxstr(_L("requires max. %s"), max_slic3r.to_string());
}
incompats_map.emplace(std::make_pair(incompat.vendor, std::move(restrictions)));
@ -742,13 +741,13 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver &old_slic3
for (const auto& update : updates.updates) {
incompatible_version = (update.forced_update ? true : incompatible_version);
//td::cout << update.forced_update << std::endl;
//BOOST_LOG_TRIVIAL(info) << boost::format("Update requires higher version.");
//BOOST_LOG_TRIVIAL(info) << format("Update requires higher version.");
}
//forced update
if(incompatible_version)
{
BOOST_LOG_TRIVIAL(info) << boost::format("Update of %1% bundles available. At least one requires higher version of Slicer.") % updates.updates.size();
BOOST_LOG_TRIVIAL(info) << format("Update of %1% bundles available. At least one requires higher version of Slicer.", updates.updates.size());
std::vector<GUI::MsgUpdateForced::Update> updates_msg;
for (const auto& update : updates.updates) {
@ -778,7 +777,7 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver &old_slic3
}
// regular update
BOOST_LOG_TRIVIAL(info) << boost::format("Update of %1% bundles available. Asking for confirmation ...") % updates.updates.size();
BOOST_LOG_TRIVIAL(info) << format("Update of %1% bundles available. Asking for confirmation ...", updates.updates.size());
std::vector<GUI::MsgUpdateConfig::Update> updates_msg;
for (const auto &update : updates.updates) {
@ -813,7 +812,7 @@ void PresetUpdater::install_bundles_rsrc(std::vector<std::string> bundles, bool
{
Updates updates;
BOOST_LOG_TRIVIAL(info) << boost::format("Installing %1% bundles from resources ...") % bundles.size();
BOOST_LOG_TRIVIAL(info) << format("Installing %1% bundles from resources ...", bundles.size());
for (const auto &bundle : bundles) {
auto path_in_rsrc = (p->rsrc_path / bundle).replace_extension(".ini");

View File

@ -183,3 +183,5 @@
#include "libslic3r/BoundingBox.hpp"
#include "libslic3r/ClipperUtils.hpp"
#include "libslic3r/libslic3r.h"
#include "GUI/format.hpp"