This commit is contained in:
enricoturri1966 2022-01-29 09:17:30 +01:00
commit 8d94841fa3
11 changed files with 153 additions and 94 deletions

View File

@ -496,7 +496,7 @@ foreach(po_file ${L10N_PO_FILES})
add_custom_command( add_custom_command(
TARGET gettext_merge_po_with_pot PRE_BUILD TARGET gettext_merge_po_with_pot PRE_BUILD
COMMAND msgmerge -N -o ${po_file} ${po_file} "${L10N_DIR}/PrusaSlicer.pot" COMMAND msgmerge -N -o ${po_file} ${po_file} "${L10N_DIR}/PrusaSlicer.pot"
# delete obsolit lines from resulting PO to avoid conflicts after a merging of it with wxWidgets.po # delete obsolete lines from resulting PO to avoid conflicts after a merging of it with wxWidgets.po
COMMAND msgattrib --no-obsolete -o ${po_file} ${po_file} COMMAND msgattrib --no-obsolete -o ${po_file} ${po_file}
DEPENDS ${po_file} DEPENDS ${po_file}
) )
@ -516,7 +516,7 @@ foreach(po_file ${L10N_PO_FILES})
add_custom_command( add_custom_command(
TARGET gettext_concat_wx_po_with_po PRE_BUILD TARGET gettext_concat_wx_po_with_po PRE_BUILD
COMMAND msgcat --use-first -o ${po_file} ${po_file} ${wx_po_file} COMMAND msgcat --use-first -o ${po_file} ${po_file} ${wx_po_file}
# delete obsolit lines from resulting PO # delete obsolete lines from resulting PO
COMMAND msgattrib --no-obsolete -o ${po_file} ${po_file} COMMAND msgattrib --no-obsolete -o ${po_file} ${po_file}
DEPENDS ${po_file} DEPENDS ${po_file}
) )

View File

@ -10,6 +10,7 @@
@ECHO [-PRODUCT ^<product^>] [-DESTDIR ^<directory^>] @ECHO [-PRODUCT ^<product^>] [-DESTDIR ^<directory^>]
@ECHO [-STEPS ^<all^|all-dirty^|app^|app-dirty^|deps^|deps-dirty^>] @ECHO [-STEPS ^<all^|all-dirty^|app^|app-dirty^|deps^|deps-dirty^>]
@ECHO [-RUN ^<console^|custom^|none^|viewer^|window^>] @ECHO [-RUN ^<console^|custom^|none^|viewer^|window^>]
@ECHO [-PRIORITY ^<normal^|low^>]
@ECHO. @ECHO.
@ECHO -a -ARCH Target processor architecture @ECHO -a -ARCH Target processor architecture
@ECHO Default: %PS_ARCH_HOST% @ECHO Default: %PS_ARCH_HOST%
@ -38,6 +39,8 @@
@ECHO -d -DESTDIR Deps destination directory @ECHO -d -DESTDIR Deps destination directory
@ECHO Warning: Changing destdir path will not delete the old destdir. @ECHO Warning: Changing destdir path will not delete the old destdir.
@ECHO Default: %PS_DESTDIR_DEFAULT_MSG% @ECHO Default: %PS_DESTDIR_DEFAULT_MSG%
@ECHO -p -PRIORITY Build CPU priority
@ECHO Default: normal
@ECHO. @ECHO.
@ECHO Examples: @ECHO Examples:
@ECHO. @ECHO.
@ -86,6 +89,7 @@ SET PS_RUN=none
SET PS_DESTDIR= SET PS_DESTDIR=
SET PS_VERSION= SET PS_VERSION=
SET PS_PRODUCT=%PS_PRODUCT_DEFAULT% SET PS_PRODUCT=%PS_PRODUCT_DEFAULT%
SET PS_PRIORITY=normal
CALL :RESOLVE_DESTDIR_CACHE CALL :RESOLVE_DESTDIR_CACHE
REM Set up parameters used by help menu REM Set up parameters used by help menu
@ -99,7 +103,7 @@ SET EXIT_STATUS=1
SET PS_CURRENT_STEP=arguments SET PS_CURRENT_STEP=arguments
SET PARSER_STATE= SET PARSER_STATE=
SET PARSER_FAIL= SET PARSER_FAIL=
FOR %%I in (%*) DO CALL :PARSE_OPTION "ARCH CONFIG DESTDIR STEPS RUN VERSION PRODUCT" PARSER_STATE "%%~I" FOR %%I in (%*) DO CALL :PARSE_OPTION "ARCH CONFIG DESTDIR STEPS RUN VERSION PRODUCT PRIORITY" PARSER_STATE "%%~I"
IF "%PARSER_FAIL%" NEQ "" ( IF "%PARSER_FAIL%" NEQ "" (
@ECHO ERROR: Invalid switch: %PARSER_FAIL% 1>&2 @ECHO ERROR: Invalid switch: %PARSER_FAIL% 1>&2
GOTO :HELP GOTO :HELP
@ -114,6 +118,9 @@ CALL :TOLOWER PS_ARCH
SET PS_ARCH=%PS_ARCH:amd64=x64% SET PS_ARCH=%PS_ARCH:amd64=x64%
CALL :PARSE_OPTION_VALUE %PS_CONFIG_LIST:;= % PS_CONFIG CALL :PARSE_OPTION_VALUE %PS_CONFIG_LIST:;= % PS_CONFIG
IF "%PS_CONFIG%" EQU "" GOTO :HELP IF "%PS_CONFIG%" EQU "" GOTO :HELP
CALL :PARSE_OPTION_VALUE "normal low" PS_PRIORITY
SET PS_PRIORITY=%PS_PRIORITY:normal= %
SET PS_PRIORITY=%PS_PRIORITY:low=-low%
REM RESOLVE_DESTDIR_CACHE must go after PS_ARCH and PS_CONFIG, but before PS STEPS REM RESOLVE_DESTDIR_CACHE must go after PS_ARCH and PS_CONFIG, but before PS STEPS
CALL :RESOLVE_DESTDIR_CACHE CALL :RESOLVE_DESTDIR_CACHE
IF "%PS_STEPS%" EQU "" SET PS_STEPS=%PS_STEPS_DEFAULT% IF "%PS_STEPS%" EQU "" SET PS_STEPS=%PS_STEPS_DEFAULT%
@ -200,7 +207,7 @@ IF %ERRORLEVEL% NEQ 0 IF "%PS_STEPS_DIRTY%" NEQ "" (
(del CMakeCache.txt && cmake.exe .. -DDESTDIR="%PS_DESTDIR%") || GOTO :END (del CMakeCache.txt && cmake.exe .. -DDESTDIR="%PS_DESTDIR%") || GOTO :END
) ELSE GOTO :END ) ELSE GOTO :END
(echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE%" (echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE%"
msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% /v:quiet || GOTO :END msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% /v:quiet %PS_PRIORITY% || GOTO :END
cd ..\.. cd ..\..
IF /I "%PS_STEPS:~0,4%" EQU "deps" GOTO :RUN_APP IF /I "%PS_STEPS:~0,4%" EQU "deps" GOTO :RUN_APP
@ -223,7 +230,7 @@ IF %ERRORLEVEL% NEQ 0 IF "%PS_STEPS_DIRTY%" NEQ "" (
(del CMakeCache.txt && cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" -DCMAKE_CONFIGURATION_TYPES=%PS_CONFIG_LIST%) || GOTO :END (del CMakeCache.txt && cmake.exe .. -DCMAKE_PREFIX_PATH="%PS_DESTDIR%\usr\local" -DCMAKE_CONFIGURATION_TYPES=%PS_CONFIG_LIST%) || GOTO :END
) ELSE GOTO :END ) ELSE GOTO :END
REM Skip the build step if we're using the undocumented app-cmake to regenerate the full config from inside devenv REM Skip the build step if we're using the undocumented app-cmake to regenerate the full config from inside devenv
IF "%PS_STEPS%" NEQ "app-cmake" msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% /v:quiet || GOTO :END IF "%PS_STEPS%" NEQ "app-cmake" msbuild /m ALL_BUILD.vcxproj /p:Configuration=%PS_CONFIG% /v:quiet %PS_PRIORITY% || GOTO :END
(echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE_FOR_CONFIG%" (echo %PS_DESTDIR%)> "%PS_DEPS_PATH_FILE_FOR_CONFIG%"
REM Run app REM Run app

View File

@ -24,11 +24,11 @@ const void unescape_extended_search_mode(std::string &s)
GCodeFindReplace::GCodeFindReplace(const std::vector<std::string> &gcode_substitutions) GCodeFindReplace::GCodeFindReplace(const std::vector<std::string> &gcode_substitutions)
{ {
if ((gcode_substitutions.size() % 3) != 0) if ((gcode_substitutions.size() % 4) != 0)
throw RuntimeError("Invalid length of gcode_substitutions parameter"); throw RuntimeError("Invalid length of gcode_substitutions parameter");
m_substitutions.reserve(gcode_substitutions.size() / 3); m_substitutions.reserve(gcode_substitutions.size() / 4);
for (size_t i = 0; i < gcode_substitutions.size(); i += 3) { for (size_t i = 0; i < gcode_substitutions.size(); i += 4) {
Substitution out; Substitution out;
try { try {
out.plain_pattern = gcode_substitutions[i]; out.plain_pattern = gcode_substitutions[i];

View File

@ -1709,7 +1709,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
}; };
auto extract_move_id = [&biased_seams_ids](size_t id) { auto extract_move_id = [&biased_seams_ids](size_t id) {
size_t new_id = -1; size_t new_id = size_t(-1);
auto it = std::lower_bound(biased_seams_ids.begin(), biased_seams_ids.end(), id); auto it = std::lower_bound(biased_seams_ids.begin(), biased_seams_ids.end(), id);
if (it == biased_seams_ids.end()) if (it == biased_seams_ids.end())
new_id = id + biased_seams_ids.size(); new_id = id + biased_seams_ids.size();
@ -1719,7 +1719,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessorResult& gcode_result)
else if (it != biased_seams_ids.begin()) else if (it != biased_seams_ids.begin())
new_id = id + std::distance(biased_seams_ids.begin(), it); new_id = id + std::distance(biased_seams_ids.begin(), it);
} }
return (new_id == -1) ? id : new_id; return (new_id == size_t(-1)) ? id : new_id;
}; };
const size_t vertex_size_floats = t_buffer.vertices.vertex_size_floats(); const size_t vertex_size_floats = t_buffer.vertices.vertex_size_floats();

View File

@ -770,7 +770,9 @@ void GUI_App::post_init()
// This is ugly but I honestly found no better way to do it. // This is ugly but I honestly found no better way to do it.
// Neither wxShowEvent nor wxWindowCreateEvent work reliably. // Neither wxShowEvent nor wxWindowCreateEvent work reliably.
if (this->preset_updater) { // G-Code Viewer does not initialize preset_updater. if (this->preset_updater) { // G-Code Viewer does not initialize preset_updater.
this->check_updates(false); if (! this->check_updates(false))
// Configuration is not compatible and reconfigure was refused by the user. Application is closing.
return;
CallAfter([this] { CallAfter([this] {
bool cw_showed = this->config_wizard_startup(); bool cw_showed = this->config_wizard_startup();
this->preset_updater->sync(preset_bundle); this->preset_updater->sync(preset_bundle);
@ -789,6 +791,10 @@ void GUI_App::post_init()
}); });
} }
// Set PrusaSlicer version and save to PrusaSlicer.ini or PrusaSlicerGcodeViewer.ini.
app_config->set("version", SLIC3R_VERSION);
app_config->save();
#ifdef _WIN32 #ifdef _WIN32
// Sets window property to mainframe so other instances can indentify it. // Sets window property to mainframe so other instances can indentify it.
OtherInstanceMessageHandler::init_windows_properties(mainframe, m_instance_hash_int); OtherInstanceMessageHandler::init_windows_properties(mainframe, m_instance_hash_int);
@ -1033,6 +1039,8 @@ bool GUI_App::OnInit()
} }
} }
static bool update_gui_after_init = true;
bool GUI_App::on_init_inner() bool GUI_App::on_init_inner()
{ {
// Set initialization of image handlers before any UI actions - See GH issue #7469 // Set initialization of image handlers before any UI actions - See GH issue #7469
@ -1178,12 +1186,10 @@ bool GUI_App::on_init_inner()
// supplied as argument to --datadir; in that case we should still run the wizard // supplied as argument to --datadir; in that case we should still run the wizard
preset_bundle->setup_directories(); preset_bundle->setup_directories();
if (! older_data_dir_path.empty()) if (! older_data_dir_path.empty()) {
preset_bundle->import_newer_configs(older_data_dir_path); preset_bundle->import_newer_configs(older_data_dir_path);
app_config->save();
// Save PrusaSlicer.ini after possibly copying the config from the alternate location and after all the configs from the alternate location were copied. }
app_config->set("version", SLIC3R_VERSION);
app_config->save();
if (is_editor()) { if (is_editor()) {
#ifdef __WXMSW__ #ifdef __WXMSW__
@ -1299,13 +1305,8 @@ bool GUI_App::on_init_inner()
if (! plater_) if (! plater_)
return; return;
if (app_config->dirty() && app_config->get("autosave") == "1")
app_config->save();
this->obj_manipul()->update_if_dirty(); this->obj_manipul()->update_if_dirty();
static bool update_gui_after_init = true;
// An ugly solution to GH #5537 in which GUI_App::init_opengl (normally called from events wxEVT_PAINT // An ugly solution to GH #5537 in which GUI_App::init_opengl (normally called from events wxEVT_PAINT
// and wxEVT_SET_FOCUS before GUI_App::post_init is called) wasn't called before GUI_App::post_init and OpenGL wasn't initialized. // and wxEVT_SET_FOCUS before GUI_App::post_init is called) wasn't called before GUI_App::post_init and OpenGL wasn't initialized.
#ifdef __linux__ #ifdef __linux__
@ -1319,6 +1320,9 @@ bool GUI_App::on_init_inner()
#endif #endif
this->post_init(); this->post_init();
} }
if (! update_gui_after_init && app_config->dirty() && app_config->get("autosave") == "1")
app_config->save();
}); });
m_initialized = true; m_initialized = true;
@ -1404,6 +1408,7 @@ void GUI_App::init_label_colours()
m_color_highlight_label_default = is_dark_mode ? wxColour(230, 230, 230): wxSystemSettings::GetColour(/*wxSYS_COLOUR_HIGHLIGHTTEXT*/wxSYS_COLOUR_WINDOWTEXT); m_color_highlight_label_default = is_dark_mode ? wxColour(230, 230, 230): wxSystemSettings::GetColour(/*wxSYS_COLOUR_HIGHLIGHTTEXT*/wxSYS_COLOUR_WINDOWTEXT);
m_color_highlight_default = is_dark_mode ? wxColour(78, 78, 78) : wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); m_color_highlight_default = is_dark_mode ? wxColour(78, 78, 78) : wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT);
m_color_hovered_btn_label = is_dark_mode ? wxColour(253, 111, 40) : wxColour(252, 77, 1); m_color_hovered_btn_label = is_dark_mode ? wxColour(253, 111, 40) : wxColour(252, 77, 1);
m_color_default_btn_label = is_dark_mode ? wxColour(255, 181, 100): wxColour(203, 61, 0);
m_color_selected_btn_bg = is_dark_mode ? wxColour(95, 73, 62) : wxColour(228, 220, 216); m_color_selected_btn_bg = is_dark_mode ? wxColour(95, 73, 62) : wxColour(228, 220, 216);
#else #else
m_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); m_color_label_default = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
@ -1438,12 +1443,22 @@ static bool is_focused(HWND hWnd)
HWND hFocusedWnd = ::GetFocus(); HWND hFocusedWnd = ::GetFocus();
return hFocusedWnd && hWnd == hFocusedWnd; return hFocusedWnd && hWnd == hFocusedWnd;
} }
static bool is_default(wxWindow* win)
{
wxTopLevelWindow* tlw = find_toplevel_parent(win);
if (!tlw)
return false;
return win == tlw->GetDefaultItem();
}
#endif #endif
void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool just_font/* = false*/) void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool just_font/* = false*/)
{ {
#ifdef _WIN32 #ifdef _WIN32
bool is_focused_button = false; bool is_focused_button = false;
bool is_default_button = false;
if (wxButton* btn = dynamic_cast<wxButton*>(window)) { if (wxButton* btn = dynamic_cast<wxButton*>(window)) {
if (!(btn->GetWindowStyle() & wxNO_BORDER)) { if (!(btn->GetWindowStyle() & wxNO_BORDER)) {
btn->SetWindowStyle(btn->GetWindowStyle() | wxNO_BORDER); btn->SetWindowStyle(btn->GetWindowStyle() | wxNO_BORDER);
@ -1455,7 +1470,7 @@ void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool ju
if (btn->GetLabel().IsEmpty()) if (btn->GetLabel().IsEmpty())
btn->SetBackgroundColour(mark ? m_color_selected_btn_bg : highlited ? m_color_highlight_default : m_color_window_default); btn->SetBackgroundColour(mark ? m_color_selected_btn_bg : highlited ? m_color_highlight_default : m_color_window_default);
else else
btn->SetForegroundColour(mark ? m_color_hovered_btn_label : m_color_label_default); btn->SetForegroundColour(mark ? m_color_hovered_btn_label : (is_default(btn) ? m_color_default_btn_label : m_color_label_default));
btn->Refresh(); btn->Refresh();
btn->Update(); btn->Update();
}; };
@ -1467,8 +1482,10 @@ void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool ju
btn->Bind(wxEVT_SET_FOCUS, [mark_button](wxFocusEvent& event) { mark_button(true); event.Skip(); }); btn->Bind(wxEVT_SET_FOCUS, [mark_button](wxFocusEvent& event) { mark_button(true); event.Skip(); });
btn->Bind(wxEVT_KILL_FOCUS, [mark_button](wxFocusEvent& event) { mark_button(false); event.Skip(); }); btn->Bind(wxEVT_KILL_FOCUS, [mark_button](wxFocusEvent& event) { mark_button(false); event.Skip(); });
if (is_focused_button = is_focused(btn->GetHWND())) is_focused_button = is_focused(btn->GetHWND());
mark_button(true); is_default_button = is_default(btn);
if (is_focused_button || is_default_button)
mark_button(is_focused_button);
} }
} }
else if (wxTextCtrl* text = dynamic_cast<wxTextCtrl*>(window)) { else if (wxTextCtrl* text = dynamic_cast<wxTextCtrl*>(window)) {
@ -1490,7 +1507,7 @@ void GUI_App::UpdateDarkUI(wxWindow* window, bool highlited/* = false*/, bool ju
if (!just_font) if (!just_font)
window->SetBackgroundColour(highlited ? m_color_highlight_default : m_color_window_default); window->SetBackgroundColour(highlited ? m_color_highlight_default : m_color_window_default);
if (!is_focused_button) if (!is_focused_button && !is_default_button)
window->SetForegroundColour(m_color_label_default); window->SetForegroundColour(m_color_label_default);
#endif #endif
} }
@ -3003,13 +3020,15 @@ bool GUI_App::config_wizard_startup()
return false; return false;
} }
void GUI_App::check_updates(const bool verbose) bool GUI_App::check_updates(const bool verbose)
{ {
PresetUpdater::UpdateResult updater_result; PresetUpdater::UpdateResult updater_result;
try { try {
updater_result = preset_updater->config_update(app_config->orig_version(), verbose ? PresetUpdater::UpdateParams::SHOW_TEXT_BOX : PresetUpdater::UpdateParams::SHOW_NOTIFICATION); updater_result = preset_updater->config_update(app_config->orig_version(), verbose ? PresetUpdater::UpdateParams::SHOW_TEXT_BOX : PresetUpdater::UpdateParams::SHOW_NOTIFICATION);
if (updater_result == PresetUpdater::R_INCOMPAT_EXIT) { if (updater_result == PresetUpdater::R_INCOMPAT_EXIT) {
mainframe->Close(); mainframe->Close();
// Applicaiton is closing.
return false;
} }
else if (updater_result == PresetUpdater::R_INCOMPAT_CONFIGURED) { else if (updater_result == PresetUpdater::R_INCOMPAT_CONFIGURED) {
m_app_conf_exists = true; m_app_conf_exists = true;
@ -3022,6 +3041,8 @@ void GUI_App::check_updates(const bool verbose)
catch (const std::exception & ex) { catch (const std::exception & ex) {
show_error(nullptr, ex.what()); show_error(nullptr, ex.what());
} }
// Applicaiton will continue.
return true;
} }
bool GUI_App::open_browser_with_warning_dialog(const wxString& url, wxWindow* parent/* = nullptr*/, bool force_remember_choice /*= true*/, int flags/* = 0*/) bool GUI_App::open_browser_with_warning_dialog(const wxString& url, wxWindow* parent/* = nullptr*/, bool force_remember_choice /*= true*/, int flags/* = 0*/)

View File

@ -124,6 +124,7 @@ private:
#ifdef _WIN32 #ifdef _WIN32
wxColour m_color_highlight_label_default; wxColour m_color_highlight_label_default;
wxColour m_color_hovered_btn_label; wxColour m_color_hovered_btn_label;
wxColour m_color_default_btn_label;
wxColour m_color_highlight_default; wxColour m_color_highlight_default;
wxColour m_color_selected_btn_bg; wxColour m_color_selected_btn_bg;
bool m_force_colors_update { false }; bool m_force_colors_update { false };
@ -352,7 +353,9 @@ private:
bool select_language(); bool select_language();
bool config_wizard_startup(); bool config_wizard_startup();
void check_updates(const bool verbose); // Returns true if the configuration is fine.
// Returns true if the configuration is not compatible and the user decided to rather close the slicer instead of reconfiguring.
bool check_updates(const bool verbose);
bool m_datadir_redefined { false }; bool m_datadir_redefined { false };
}; };

View File

@ -14,6 +14,7 @@
#include "libslic3r/Config.hpp" #include "libslic3r/Config.hpp"
#include "libslic3r/PrintConfig.hpp" #include "libslic3r/PrintConfig.hpp"
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <boost/nowide/fstream.hpp> #include <boost/nowide/fstream.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
@ -342,6 +343,9 @@ void HintDatabase::load_hints_from_file(const boost::filesystem::path& path)
//unescape text1 //unescape text1
unescape_string_cstyle(dict["text"], fulltext); unescape_string_cstyle(dict["text"], fulltext);
fulltext = _utf8(fulltext); fulltext = _utf8(fulltext);
#ifdef __APPLE__
boost::replace_all(fulltext, "Ctrl+", "");
#endif //__APPLE__
// replace <b> and </b> for imgui markers // replace <b> and </b> for imgui markers
std::string marker_s(1, ImGui::ColorMarkerStart); std::string marker_s(1, ImGui::ColorMarkerStart);
std::string marker_e(1, ImGui::ColorMarkerEnd); std::string marker_e(1, ImGui::ColorMarkerEnd);

View File

@ -37,7 +37,8 @@ static const char *CONFIG_KEY_PATH = "printhost_path";
static const char *CONFIG_KEY_GROUP = "printhost_group"; static const char *CONFIG_KEY_GROUP = "printhost_group";
PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups) 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:")) : MsgDialog(static_cast<wxWindow*>(wxGetApp().mainframe), _L("Send G-Code to printer host"), _L("Upload to Printer Host with the following filename:"), 0) // Set style = 0 to avoid default creation of the "OK" button.
// All buttons will be added later in this constructor
, txt_filename(new wxTextCtrl(this, wxID_ANY)) , txt_filename(new wxTextCtrl(this, wxID_ANY))
, combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr) , combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr)
, post_upload_action(PrintHostPostUploadAction::None) , post_upload_action(PrintHostPostUploadAction::None)
@ -74,7 +75,6 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
const auto stem_len = stem.Length(); const auto stem_len = stem.Length();
txt_filename->SetValue(recent_path); txt_filename->SetValue(recent_path);
txt_filename->SetFocus();
if (size_t extension_start = recent_path.find_last_of('.'); extension_start != std::string::npos) if (size_t extension_start = recent_path.find_last_of('.'); extension_start != std::string::npos)
m_valid_suffix = recent_path.substr(extension_start); m_valid_suffix = recent_path.substr(extension_start);
@ -88,6 +88,15 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
return true; return true;
}; };
auto* btn_ok = add_button(wxID_OK, true, _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);
}
});
txt_filename->SetFocus();
if (post_actions.has(PrintHostPostUploadAction::StartPrint)) { if (post_actions.has(PrintHostPostUploadAction::StartPrint)) {
auto* btn_print = add_button(wxID_YES, false, _L("Upload and Print")); auto* btn_print = add_button(wxID_YES, false, _L("Upload and Print"));
btn_print->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) { btn_print->Bind(wxEVT_BUTTON, [this, validate_path](wxCommandEvent&) {
@ -110,16 +119,6 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
} }
add_button(wxID_CANCEL); 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(); finalize();
#ifdef __linux__ #ifdef __linux__
@ -137,6 +136,7 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo
// Another similar case where the function only works with EVT_SHOW + CallAfter, // Another similar case where the function only works with EVT_SHOW + CallAfter,
// this time on Mac. // this time on Mac.
CallAfter([=]() { CallAfter([=]() {
txt_filename->SetInsertionPoint(0);
txt_filename->SetSelection(recent_path_len, recent_path_len + stem_len); txt_filename->SetSelection(recent_path_len, recent_path_len + stem_len);
}); });
}); });

View File

@ -1661,7 +1661,7 @@ void TabPrint::build()
optgroup = page->new_optgroup(L("Other")); optgroup = page->new_optgroup(L("Other"));
create_line_with_widget(optgroup.get(), "gcode_substitutions", "", [this](wxWindow* parent) { create_line_with_widget(optgroup.get(), "gcode_substitutions", "g-code-substitutions_301694", [this](wxWindow* parent) {
return create_manage_substitution_widget(parent); return create_manage_substitution_widget(parent);
}); });
line = { "", "" }; line = { "", "" };
@ -3866,17 +3866,17 @@ void SubstitutionManager::init(DynamicPrintConfig* config, wxWindow* parent, wxF
void SubstitutionManager::validate_lenth() void SubstitutionManager::validate_lenth()
{ {
std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values; std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values;
if ((substitutions.size() % 3) != 0) { if ((substitutions.size() % 4) != 0) {
WarningDialog(m_parent, "Value of gcode_substitutions parameter will be cut to valid length", WarningDialog(m_parent, "Value of gcode_substitutions parameter will be cut to valid length",
"Invalid length of gcode_substitutions parameter").ShowModal(); "Invalid length of gcode_substitutions parameter").ShowModal();
substitutions.resize(substitutions.size() - (substitutions.size() % 3)); substitutions.resize(substitutions.size() - (substitutions.size() % 4));
} }
} }
bool SubstitutionManager::is_compatibile_with_ui() bool SubstitutionManager::is_compatibile_with_ui()
{ {
const std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values; const std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values;
if (int(substitutions.size() / 3) != m_grid_sizer->GetEffectiveRowsCount() - 1) { if (int(substitutions.size() / 4) != m_grid_sizer->GetEffectiveRowsCount() - 1) {
ErrorDialog(m_parent, "Invalid compatibility between UI and BE", false).ShowModal(); ErrorDialog(m_parent, "Invalid compatibility between UI and BE", false).ShowModal();
return false; return false;
} }
@ -3886,7 +3886,7 @@ bool SubstitutionManager::is_compatibile_with_ui()
bool SubstitutionManager::is_valid_id(int substitution_id, const wxString& message) bool SubstitutionManager::is_valid_id(int substitution_id, const wxString& message)
{ {
const std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values; const std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values;
if (int(substitutions.size() / 3) < substitution_id) { if (int(substitutions.size() / 4) < substitution_id) {
ErrorDialog(m_parent, message, false).ShowModal(); ErrorDialog(m_parent, message, false).ShowModal();
return false; return false;
} }
@ -3899,11 +3899,14 @@ void SubstitutionManager::create_legend()
return; return;
// name of the first column is empty // name of the first column is empty
m_grid_sizer->Add(new wxStaticText(m_parent, wxID_ANY, wxEmptyString)); m_grid_sizer->Add(new wxStaticText(m_parent, wxID_ANY, wxEmptyString));
// Legend for another columns // Legend for another columns
for (const std::string col : { L("Find"), L("Replace with"), L("Options") }) { auto legend_sizer = new wxBoxSizer(wxHORIZONTAL); // "Find", "Replace", "Notes"
auto temp = new wxStaticText(m_parent, wxID_ANY, _(col), wxDefaultPosition, wxDefaultSize, wxST_ELLIPSIZE_MIDDLE); legend_sizer->Add(new wxStaticText(m_parent, wxID_ANY, _L("Find")), 3, wxEXPAND);
m_grid_sizer->Add(temp); legend_sizer->Add(new wxStaticText(m_parent, wxID_ANY, _L("Replace with")), 3, wxEXPAND);
} legend_sizer->Add(new wxStaticText(m_parent, wxID_ANY, _L("Notes")), 2, wxEXPAND);
m_grid_sizer->Add(legend_sizer, 1, wxEXPAND);
} }
// delete substitution_id from substitutions // delete substitution_id from substitutions
@ -3915,7 +3918,7 @@ void SubstitutionManager::delete_substitution(int substitution_id)
// delete substitution // delete substitution
std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values; std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values;
substitutions.erase(std::next(substitutions.begin(), substitution_id * 3), std::next(substitutions.begin(), substitution_id * 3 + 3)); substitutions.erase(std::next(substitutions.begin(), substitution_id * 4), std::next(substitutions.begin(), substitution_id * 4 + 4));
call_ui_update(); call_ui_update();
// update grid_sizer // update grid_sizer
@ -3923,7 +3926,11 @@ void SubstitutionManager::delete_substitution(int substitution_id)
} }
// Add substitution line // Add substitution line
void SubstitutionManager::add_substitution(int substitution_id, const std::string& plain_pattern, const std::string& format, const std::string& params) void SubstitutionManager::add_substitution( int substitution_id,
const std::string& plain_pattern,
const std::string& format,
const std::string& params,
const std::string& notes)
{ {
bool call_after_layout = false; bool call_after_layout = false;
@ -3937,7 +3944,7 @@ void SubstitutionManager::add_substitution(int substitution_id, const std::strin
// create new substitution // create new substitution
// it have to be added to config too // it have to be added to config too
std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values; std::vector<std::string>& substitutions = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values;
for (size_t i = 0; i < 3; i ++) for (size_t i = 0; i < 4; i ++)
substitutions.push_back(std::string()); substitutions.push_back(std::string());
call_after_layout = true; call_after_layout = true;
@ -3948,9 +3955,10 @@ void SubstitutionManager::add_substitution(int substitution_id, const std::strin
delete_substitution(substitution_id); delete_substitution(substitution_id);
}); });
m_grid_sizer->Add(del_btn, 0, wxRIGHT | wxLEFT, m_em); m_grid_sizer->Add(del_btn, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT | wxLEFT, int(0.5*m_em));
auto add_text_editor = [substitution_id, this](const wxString& value, int opt_pos) { auto top_sizer = new wxBoxSizer(wxHORIZONTAL);
auto add_text_editor = [substitution_id, top_sizer, this](const wxString& value, int opt_pos, int proportion) {
auto editor = new wxTextCtrl(m_parent, wxID_ANY, value, wxDefaultPosition, wxSize(15 * m_em, wxDefaultCoord), wxTE_PROCESS_ENTER auto editor = new wxTextCtrl(m_parent, wxID_ANY, value, wxDefaultPosition, wxSize(15 * m_em, wxDefaultCoord), wxTE_PROCESS_ENTER
#ifdef _WIN32 #ifdef _WIN32
| wxBORDER_SIMPLE | wxBORDER_SIMPLE
@ -3959,7 +3967,7 @@ void SubstitutionManager::add_substitution(int substitution_id, const std::strin
editor->SetFont(wxGetApp().normal_font()); editor->SetFont(wxGetApp().normal_font());
wxGetApp().UpdateDarkUI(editor); wxGetApp().UpdateDarkUI(editor);
m_grid_sizer->Add(editor, 0, wxALIGN_CENTER_VERTICAL); top_sizer->Add(editor, proportion, wxALIGN_CENTER_VERTICAL | wxEXPAND| wxRIGHT, m_em);
editor->Bind(wxEVT_TEXT_ENTER, [this, editor, substitution_id, opt_pos](wxEvent& e) { editor->Bind(wxEVT_TEXT_ENTER, [this, editor, substitution_id, opt_pos](wxEvent& e) {
#if !defined(__WXGTK__) #if !defined(__WXGTK__)
@ -3974,8 +3982,9 @@ void SubstitutionManager::add_substitution(int substitution_id, const std::strin
}); });
}; };
add_text_editor(from_u8(plain_pattern), 0); add_text_editor(from_u8(plain_pattern), 0, 3);
add_text_editor(from_u8(format), 1); add_text_editor(from_u8(format), 1, 3);
add_text_editor(from_u8(notes), 3, 2);
auto params_sizer = new wxBoxSizer(wxHORIZONTAL); auto params_sizer = new wxBoxSizer(wxHORIZONTAL);
bool regexp = strchr(params.c_str(), 'r') != nullptr || strchr(params.c_str(), 'R') != nullptr; bool regexp = strchr(params.c_str(), 'r') != nullptr || strchr(params.c_str(), 'R') != nullptr;
@ -4020,7 +4029,10 @@ void SubstitutionManager::add_substitution(int substitution_id, const std::strin
}); });
} }
m_grid_sizer->Add(params_sizer); auto v_sizer = new wxBoxSizer(wxVERTICAL);
v_sizer->Add(top_sizer, 1, wxEXPAND);
v_sizer->Add(params_sizer, 1, wxEXPAND|wxTOP|wxBOTTOM, int(0.5* m_em));
m_grid_sizer->Add(v_sizer, 1, wxALIGN_CENTER_VERTICAL | wxEXPAND);
if (call_after_layout) { if (call_after_layout) {
m_parent->GetParent()->Layout(); m_parent->GetParent()->Layout();
@ -4034,14 +4046,16 @@ void SubstitutionManager::update_from_config()
m_grid_sizer->Clear(true); m_grid_sizer->Clear(true);
std::vector<std::string>& subst = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values; std::vector<std::string>& subst = m_config->option<ConfigOptionStrings>("gcode_substitutions")->values;
if (!subst.empty()) if (subst.empty())
hide_delete_all_btn();
else
create_legend(); create_legend();
validate_lenth(); validate_lenth();
int subst_id = 0; int subst_id = 0;
for (size_t i = 0; i < subst.size(); i += 3) for (size_t i = 0; i < subst.size(); i += 4)
add_substitution(subst_id++, subst[i], subst[i + 1], subst[i + 2]); add_substitution(subst_id++, subst[i], subst[i + 1], subst[i + 2], subst[i + 3]);
m_parent->GetParent()->Layout(); m_parent->GetParent()->Layout();
} }
@ -4065,7 +4079,7 @@ void SubstitutionManager::edit_substitution(int substitution_id, int opt_pos, co
if(!is_compatibile_with_ui() || !is_valid_id(substitution_id, "Invalid substitution_id to edit")) if(!is_compatibile_with_ui() || !is_valid_id(substitution_id, "Invalid substitution_id to edit"))
return; return;
substitutions[substitution_id * 3 + opt_pos] = value; substitutions[substitution_id * 4 + opt_pos] = value;
call_ui_update(); call_ui_update();
} }
@ -4108,20 +4122,21 @@ wxSizer* TabPrint::create_manage_substitution_widget(wxWindow* parent)
// Return a callback to create a TabPrint widget to edit G-code substitutions // Return a callback to create a TabPrint widget to edit G-code substitutions
wxSizer* TabPrint::create_substitutions_widget(wxWindow* parent) wxSizer* TabPrint::create_substitutions_widget(wxWindow* parent)
{ {
wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(4, 5, wxGetApp().em_unit()); // delete_button, "Old val", "New val", "Params" wxFlexGridSizer* grid_sizer = new wxFlexGridSizer(2, 5, wxGetApp().em_unit()); // delete_button, edit column contains "Find", "Replace", "Notes"
grid_sizer->SetFlexibleDirection(wxHORIZONTAL); grid_sizer->SetFlexibleDirection(wxBOTH);
grid_sizer->AddGrowableCol(1);
m_subst_manager.init(m_config, parent, grid_sizer); m_subst_manager.init(m_config, parent, grid_sizer);
m_subst_manager.set_cb_edited_substitution([this]() { m_subst_manager.set_cb_edited_substitution([this]() {
update_dirty(); update_dirty();
wxGetApp().mainframe->on_config_changed(m_config); // invalidate print wxGetApp().mainframe->on_config_changed(m_config); // invalidate print
}); });
m_subst_manager.set_cb_hide_delete_all_btn([this]() {
auto sizer = new wxBoxSizer(wxHORIZONTAL); m_del_all_substitutions_btn->Hide();
sizer->Add(grid_sizer, 0, wxALIGN_CENTER_VERTICAL); });
parent->GetParent()->Layout(); parent->GetParent()->Layout();
return sizer; return grid_sizer;
} }
// Return a callback to create a TabPrinter widget to edit bed shape // Return a callback to create a TabPrinter widget to edit bed shape

View File

@ -54,14 +54,15 @@ class SubstitutionManager
int m_em{10}; int m_em{10};
std::function<void()> m_cb_edited_substitution{ nullptr }; std::function<void()> m_cb_edited_substitution{ nullptr };
std::function<void()> m_cb_hide_delete_all_btn{ nullptr };
void validate_lenth(); void validate_lenth();
bool is_compatibile_with_ui(); bool is_compatibile_with_ui();
bool is_valid_id(int substitution_id, const wxString& message); bool is_valid_id(int substitution_id, const wxString& message);
public: public:
SubstitutionManager() {}; SubstitutionManager() = default;
~SubstitutionManager() {}; ~SubstitutionManager() = default;
void init(DynamicPrintConfig* config, wxWindow* parent, wxFlexGridSizer* grid_sizer); void init(DynamicPrintConfig* config, wxWindow* parent, wxFlexGridSizer* grid_sizer);
void create_legend(); void create_legend();
@ -69,7 +70,8 @@ public:
void add_substitution( int substitution_id = -1, void add_substitution( int substitution_id = -1,
const std::string& plain_pattern = std::string(), const std::string& plain_pattern = std::string(),
const std::string& format = std::string(), const std::string& format = std::string(),
const std::string& params = std::string()); const std::string& params = std::string(),
const std::string& notes = std::string());
void update_from_config(); void update_from_config();
void delete_all(); void delete_all();
void edit_substitution(int substitution_id, void edit_substitution(int substitution_id,
@ -82,6 +84,13 @@ public:
if (m_cb_edited_substitution) if (m_cb_edited_substitution)
m_cb_edited_substitution(); m_cb_edited_substitution();
} }
void set_cb_hide_delete_all_btn(std::function<void()> cb_hide_delete_all_btn) {
m_cb_hide_delete_all_btn = cb_hide_delete_all_btn;
}
void hide_delete_all_btn() {
if (m_cb_hide_delete_all_btn)
m_cb_hide_delete_all_btn();
}
bool is_empty_substitutions(); bool is_empty_substitutions();
}; };

View File

@ -15,7 +15,7 @@ SCENARIO("Find/Replace with plain text", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; infill\n" "G1 X13 Y32 Z1; infill\n"
"G1 X13 Y32 Z1; wipe\n"; "G1 X13 Y32 Z1; wipe\n";
WHEN("Replace \"move up\" with \"move down\", case sensitive") { WHEN("Replace \"move up\" with \"move down\", case sensitive") {
GCodeFindReplace find_replace({ "move up", "move down", "" }); GCodeFindReplace find_replace({ "move up", "move down", "", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -25,7 +25,7 @@ SCENARIO("Find/Replace with plain text", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; wipe\n"); "G1 X13 Y32 Z1; wipe\n");
} }
WHEN("Replace \"move up\" with \"move down\", case insensitive") { WHEN("Replace \"move up\" with \"move down\", case insensitive") {
GCodeFindReplace find_replace({ "move up", "move down", "i" }); GCodeFindReplace find_replace({ "move up", "move down", "i", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -35,7 +35,7 @@ SCENARIO("Find/Replace with plain text", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; wipe\n"); "G1 X13 Y32 Z1; wipe\n");
} }
WHEN("Replace \"move UP\" with \"move down\", case insensitive") { WHEN("Replace \"move UP\" with \"move down\", case insensitive") {
GCodeFindReplace find_replace({ "move UP", "move down", "i" }); GCodeFindReplace find_replace({ "move UP", "move down", "i", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -45,13 +45,13 @@ SCENARIO("Find/Replace with plain text", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; wipe\n"); "G1 X13 Y32 Z1; wipe\n");
} }
WHEN("Replace \"move up\" with \"move down\", case sensitive") { WHEN("Replace \"move up\" with \"move down\", case sensitive") {
GCodeFindReplace find_replace({ "move UP", "move down", "" }); GCodeFindReplace find_replace({ "move UP", "move down", "", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
// Whole word // Whole word
WHEN("Replace \"move up\" with \"move down\", whole word") { WHEN("Replace \"move up\" with \"move down\", whole word") {
GCodeFindReplace find_replace({ "move up", "move down", "w" }); GCodeFindReplace find_replace({ "move up", "move down", "w", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -61,17 +61,17 @@ SCENARIO("Find/Replace with plain text", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; wipe\n"); "G1 X13 Y32 Z1; wipe\n");
} }
WHEN("Replace \"move u\" with \"move down\", whole word") { WHEN("Replace \"move u\" with \"move down\", whole word") {
GCodeFindReplace find_replace({ "move u", "move down", "w" }); GCodeFindReplace find_replace({ "move u", "move down", "w", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
WHEN("Replace \"ove up\" with \"move down\", whole word") { WHEN("Replace \"ove up\" with \"move down\", whole word") {
GCodeFindReplace find_replace({ "move u", "move down", "w" }); GCodeFindReplace find_replace({ "move u", "move down", "w", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
// Multi-line replace // Multi-line replace
WHEN("Replace \"move up\\nG1 X0 \" with \"move down\\nG0 X1 \"") { WHEN("Replace \"move up\\nG1 X0 \" with \"move down\\nG0 X1 \"") {
GCodeFindReplace find_replace({ "move up\\nG1 X0 ", "move down\\nG0 X1 ", "" }); GCodeFindReplace find_replace({ "move up\\nG1 X0 ", "move down\\nG0 X1 ", "", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -82,7 +82,7 @@ SCENARIO("Find/Replace with plain text", "[GCodeFindReplace]") {
} }
// Multi-line replace, whole word. // Multi-line replace, whole word.
WHEN("Replace \"move up\\nG1 X0\" with \"move down\\nG0 X1\", whole word") { WHEN("Replace \"move up\\nG1 X0\" with \"move down\\nG0 X1\", whole word") {
GCodeFindReplace find_replace({ "move up\\nG1 X0", "move down\\nG0 X1", "w" }); GCodeFindReplace find_replace({ "move up\\nG1 X0", "move down\\nG0 X1", "w", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -93,7 +93,7 @@ SCENARIO("Find/Replace with plain text", "[GCodeFindReplace]") {
} }
// Multi-line replace, whole word, fails. // Multi-line replace, whole word, fails.
WHEN("Replace \"move up\\nG1 X\" with \"move down\\nG0 X\", whole word") { WHEN("Replace \"move up\\nG1 X\" with \"move down\\nG0 X\", whole word") {
GCodeFindReplace find_replace({ "move up\\nG1 X", "move down\\nG0 X", "w" }); GCodeFindReplace find_replace({ "move up\\nG1 X", "move down\\nG0 X", "w", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
} }
@ -104,7 +104,7 @@ SCENARIO("Find/Replace with plain text", "[GCodeFindReplace]") {
"G1 Z1.21; move up\n" "G1 Z1.21; move up\n"
"G1 X0 Y.33 Z.431 E1.2; perimeter\n"; "G1 X0 Y.33 Z.431 E1.2; perimeter\n";
WHEN("Regular expression NOT processed in non-regex mode") { WHEN("Regular expression NOT processed in non-regex mode") {
GCodeFindReplace find_replace({ "( [XYZEF]-?)\\.([0-9]+)", "\\10.\\2", "" }); GCodeFindReplace find_replace({ "( [XYZEF]-?)\\.([0-9]+)", "\\10.\\2", "", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
} }
@ -119,7 +119,7 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; infill\n" "G1 X13 Y32 Z1; infill\n"
"G1 X13 Y32 Z1; wipe\n"; "G1 X13 Y32 Z1; wipe\n";
WHEN("Replace \"move up\" with \"move down\", case sensitive") { WHEN("Replace \"move up\" with \"move down\", case sensitive") {
GCodeFindReplace find_replace({ "move up", "move down", "r" }); GCodeFindReplace find_replace({ "move up", "move down", "r", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -129,7 +129,7 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; wipe\n"); "G1 X13 Y32 Z1; wipe\n");
} }
WHEN("Replace \"move up\" with \"move down\", case insensitive") { WHEN("Replace \"move up\" with \"move down\", case insensitive") {
GCodeFindReplace find_replace({ "move up", "move down", "ri" }); GCodeFindReplace find_replace({ "move up", "move down", "ri", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -139,7 +139,7 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; wipe\n"); "G1 X13 Y32 Z1; wipe\n");
} }
WHEN("Replace \"move UP\" with \"move down\", case insensitive") { WHEN("Replace \"move UP\" with \"move down\", case insensitive") {
GCodeFindReplace find_replace({ "move UP", "move down", "ri" }); GCodeFindReplace find_replace({ "move UP", "move down", "ri", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -149,13 +149,13 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; wipe\n"); "G1 X13 Y32 Z1; wipe\n");
} }
WHEN("Replace \"move up\" with \"move down\", case sensitive") { WHEN("Replace \"move up\" with \"move down\", case sensitive") {
GCodeFindReplace find_replace({ "move UP", "move down", "r" }); GCodeFindReplace find_replace({ "move UP", "move down", "r", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
// Whole word // Whole word
WHEN("Replace \"move up\" with \"move down\", whole word") { WHEN("Replace \"move up\" with \"move down\", whole word") {
GCodeFindReplace find_replace({ "move up", "move down", "rw" }); GCodeFindReplace find_replace({ "move up", "move down", "rw", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -165,17 +165,17 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
"G1 X13 Y32 Z1; wipe\n"); "G1 X13 Y32 Z1; wipe\n");
} }
WHEN("Replace \"move u\" with \"move down\", whole word") { WHEN("Replace \"move u\" with \"move down\", whole word") {
GCodeFindReplace find_replace({ "move u", "move down", "rw" }); GCodeFindReplace find_replace({ "move u", "move down", "rw", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
WHEN("Replace \"ove up\" with \"move down\", whole word") { WHEN("Replace \"ove up\" with \"move down\", whole word") {
GCodeFindReplace find_replace({ "move u", "move down", "rw" }); GCodeFindReplace find_replace({ "move u", "move down", "rw", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
// Multi-line replace // Multi-line replace
WHEN("Replace \"move up\\nG1 X0 \" with \"move down\\nG0 X1 \"") { WHEN("Replace \"move up\\nG1 X0 \" with \"move down\\nG0 X1 \"") {
GCodeFindReplace find_replace({ "move up\\nG1 X0 ", "move down\\nG0 X1 ", "r" }); GCodeFindReplace find_replace({ "move up\\nG1 X0 ", "move down\\nG0 X1 ", "r", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -186,7 +186,7 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
} }
// Multi-line replace, whole word. // Multi-line replace, whole word.
WHEN("Replace \"move up\\nG1 X0\" with \"move down\\nG0 X1\", whole word") { WHEN("Replace \"move up\\nG1 X0\" with \"move down\\nG0 X1\", whole word") {
GCodeFindReplace find_replace({ "move up\\nG1 X0", "move down\\nG0 X1", "rw" }); GCodeFindReplace find_replace({ "move up\\nG1 X0", "move down\\nG0 X1", "rw", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0; home\n" "G1 Z0; home\n"
// substituted // substituted
@ -197,7 +197,7 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
} }
// Multi-line replace, whole word, fails. // Multi-line replace, whole word, fails.
WHEN("Replace \"move up\\nG1 X\" with \"move down\\nG0 X\", whole word") { WHEN("Replace \"move up\\nG1 X\" with \"move down\\nG0 X\", whole word") {
GCodeFindReplace find_replace({ "move up\\nG1 X", "move down\\nG0 X", "rw" }); GCodeFindReplace find_replace({ "move up\\nG1 X", "move down\\nG0 X", "rw", "" });
REQUIRE(find_replace.process_layer(gcode) == gcode); REQUIRE(find_replace.process_layer(gcode) == gcode);
} }
} }
@ -208,7 +208,7 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
"G1 Z1.21; move up\n" "G1 Z1.21; move up\n"
"G1 X0 Y.33 Z.431 E1.2; perimeter\n"; "G1 X0 Y.33 Z.431 E1.2; perimeter\n";
WHEN("Missing zeros before dot filled in") { WHEN("Missing zeros before dot filled in") {
GCodeFindReplace find_replace({ "( [XYZEF]-?)\\.([0-9]+)", "\\10.\\2", "r" }); GCodeFindReplace find_replace({ "( [XYZEF]-?)\\.([0-9]+)", "\\10.\\2", "r", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z0.123; home\n" "G1 Z0.123; home\n"
"G1 Z1.21; move up\n" "G1 Z1.21; move up\n"
@ -237,7 +237,7 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
";TYPE:External perimeter\n" ";TYPE:External perimeter\n"
"G1 X1 Y.3 Z.431 E0.1\n"; "G1 X1 Y.3 Z.431 E0.1\n";
WHEN("Change extrusion rate of top solid infill, single line modifier") { WHEN("Change extrusion rate of top solid infill, single line modifier") {
GCodeFindReplace find_replace({ "(;TYPE:Top solid infill\\n)(.*?)(;TYPE:[^T][^o][^p][^ ][^s]|$)", "${1}M221 S98\\n${2}M221 S95\\n${3}", "rs" }); GCodeFindReplace find_replace({ "(;TYPE:Top solid infill\\n)(.*?)(;TYPE:[^T][^o][^p][^ ][^s]|$)", "${1}M221 S98\\n${2}M221 S95\\n${3}", "rs", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z1.21; move up\n" "G1 Z1.21; move up\n"
";TYPE:Infill\n" ";TYPE:Infill\n"
@ -262,7 +262,7 @@ SCENARIO("Find/Replace with regexp", "[GCodeFindReplace]") {
"G1 X1 Y.3 Z.431 E0.1\n"); "G1 X1 Y.3 Z.431 E0.1\n");
} }
WHEN("Change extrusion rate of top solid infill, no single line modifier (incorrect)") { WHEN("Change extrusion rate of top solid infill, no single line modifier (incorrect)") {
GCodeFindReplace find_replace({ "(;TYPE:Top solid infill\\n)(.*?)(;TYPE:[^T][^o][^p][^ ][^s]|$)", "${1}M221 S98\\n${2}\\nM221 S95${3}", "r" }); GCodeFindReplace find_replace({ "(;TYPE:Top solid infill\\n)(.*?)(;TYPE:[^T][^o][^p][^ ][^s]|$)", "${1}M221 S98\\n${2}\\nM221 S95${3}", "r", "" });
REQUIRE(find_replace.process_layer(gcode) == REQUIRE(find_replace.process_layer(gcode) ==
"G1 Z1.21; move up\n" "G1 Z1.21; move up\n"
";TYPE:Infill\n" ";TYPE:Infill\n"