Merge branch 'master' into fs_emboss_temp
This commit is contained in:
commit
6a04d037f9
@ -237,14 +237,14 @@ documentation_link = https://help.prusa3d.com/article/prusaslicer-printables-com
|
||||
weight = 3
|
||||
|
||||
[hint:Cut tool]
|
||||
text = Cut tool\nDid you know that you can cut a model at any angle and even create aligning pins with the updated Cut tool? Learn more in the documentation.
|
||||
text = Cut tool\nDid you know that you can cut a model at any angle and even create aligning pins with the updated <a>Cut tool</a>? Learn more in the documentation.
|
||||
documentation_link = https://help.prusa3d.com/article/cut-tool_1779
|
||||
hypertext_type = gizmo
|
||||
hypertext_gizmo_item = cut
|
||||
weight = 3
|
||||
|
||||
[hint:Measurement tool]
|
||||
text = Measurement tool\nDid you know that you can measure the distances between points, edges and planes, the radius of a hole or the angle between edges or planes? Learn more in the documentation.
|
||||
text = Measurement tool\nDid you know that you can <a>measure</a> the distances between points, edges and planes, the radius of a hole or the angle between edges or planes? Learn more in the documentation.
|
||||
documentation_link = https://help.prusa3d.com/article/measurement-tool_399451
|
||||
hypertext_type = gizmo
|
||||
hypertext_gizmo_item = measure
|
||||
|
@ -1315,10 +1315,12 @@ PageUpdate::PageUpdate(ConfigWizard *parent)
|
||||
box_presets->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent &event) { this->preset_update = event.IsChecked(); });
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace DownloaderUtils
|
||||
{
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
|
||||
wxString get_downloads_path()
|
||||
{
|
||||
wxString ret;
|
||||
@ -1330,7 +1332,6 @@ namespace DownloaderUtils
|
||||
CoTaskMemFree(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#elif __APPLE__
|
||||
wxString get_downloads_path()
|
||||
{
|
||||
@ -1348,9 +1349,8 @@ namespace DownloaderUtils
|
||||
}
|
||||
return wxString();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
Worker::Worker(wxWindow* parent)
|
||||
: wxBoxSizer(wxHORIZONTAL)
|
||||
, m_parent(parent)
|
||||
@ -1432,16 +1432,16 @@ PageDownloader::PageDownloader(ConfigWizard* parent)
|
||||
)));
|
||||
#endif
|
||||
|
||||
box_allow_downloads->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& event) { this->downloader->allow(event.IsChecked()); });
|
||||
box_allow_downloads->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& event) { this->m_downloader->allow(event.IsChecked()); });
|
||||
|
||||
downloader = new DownloaderUtils::Worker(this);
|
||||
append(downloader);
|
||||
downloader->allow(box_allow_value);
|
||||
m_downloader = new DownloaderUtils::Worker(this);
|
||||
append(m_downloader);
|
||||
m_downloader->allow(box_allow_value);
|
||||
}
|
||||
|
||||
bool PageDownloader::on_finish_downloader() const
|
||||
{
|
||||
return downloader->on_finish();
|
||||
return m_downloader->on_finish();
|
||||
}
|
||||
|
||||
bool DownloaderUtils::Worker::perform_register(const std::string& path_override/* = {}*/)
|
||||
@ -3035,9 +3035,11 @@ bool ConfigWizard::priv::apply_config(AppConfig *app_config, PresetBundle *prese
|
||||
|
||||
#ifdef __linux__
|
||||
// Desktop integration on Linux
|
||||
BOOST_LOG_TRIVIAL(debug) << "ConfigWizard::priv::apply_config integrate_desktop" << page_welcome->integrate_desktop() << " perform_registration_linux " << page_downloader->downloader->get_perform_registration_linux();
|
||||
if (page_welcome->integrate_desktop() || page_downloader->downloader->get_perform_registration_linux())
|
||||
DesktopIntegrationDialog::perform_desktop_integration(page_downloader->downloader->get_perform_registration_linux());
|
||||
BOOST_LOG_TRIVIAL(debug) << "ConfigWizard::priv::apply_config integrate_desktop" << page_welcome->integrate_desktop() << " perform_registration_linux " << page_downloader->m_downloader->get_perform_registration_linux();
|
||||
if (page_welcome->integrate_desktop())
|
||||
DesktopIntegrationDialog::perform_desktop_integration();
|
||||
if (page_downloader->m_downloader->get_perform_registration_linux())
|
||||
DesktopIntegrationDialog::perform_downloader_desktop_integration();
|
||||
#endif
|
||||
|
||||
// Decide whether to create snapshot based on run_reason and the reset profile checkbox
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <memory>
|
||||
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
#include "GUI_Utils.hpp"
|
||||
|
||||
@ -14,6 +16,36 @@ class PresetUpdater;
|
||||
|
||||
namespace GUI {
|
||||
|
||||
namespace DownloaderUtils {
|
||||
class Worker : public wxBoxSizer
|
||||
{
|
||||
wxWindow* m_parent{ nullptr };
|
||||
wxTextCtrl* m_input_path{ nullptr };
|
||||
bool downloader_checked{ false };
|
||||
#ifdef __linux__
|
||||
bool perform_registration_linux{ false };
|
||||
#endif // __linux__
|
||||
|
||||
void deregister();
|
||||
|
||||
public:
|
||||
Worker(wxWindow* parent);
|
||||
~Worker() {}
|
||||
|
||||
void allow(bool allow_) { downloader_checked = allow_; }
|
||||
bool is_checked() const { return downloader_checked; }
|
||||
wxString path_name() const { return m_input_path ? m_input_path->GetValue() : wxString(); }
|
||||
|
||||
void set_path_name(wxString name);
|
||||
void set_path_name(const std::string& name);
|
||||
|
||||
bool on_finish();
|
||||
bool perform_register(const std::string& path_override = {});
|
||||
#ifdef __linux__
|
||||
bool get_perform_registration_linux() { return perform_registration_linux; }
|
||||
#endif // __linux__
|
||||
};
|
||||
}
|
||||
|
||||
class ConfigWizard: public DPIDialog
|
||||
{
|
||||
|
@ -10,12 +10,10 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/listbox.h>
|
||||
#include <wx/checklst.h>
|
||||
#include <wx/radiobut.h>
|
||||
@ -418,44 +416,10 @@ struct PageUpdate: ConfigWizardPage
|
||||
PageUpdate(ConfigWizard *parent);
|
||||
};
|
||||
|
||||
namespace DownloaderUtils {
|
||||
wxString get_downloads_path();
|
||||
|
||||
class Worker : public wxBoxSizer
|
||||
{
|
||||
wxWindow* m_parent {nullptr};
|
||||
wxTextCtrl* m_input_path {nullptr};
|
||||
bool downloader_checked {false};
|
||||
#ifdef __linux__
|
||||
bool perform_registration_linux { false };
|
||||
#endif // __linux__
|
||||
|
||||
void deregister();
|
||||
|
||||
public:
|
||||
Worker(wxWindow* parent);
|
||||
~Worker(){}
|
||||
|
||||
void allow(bool allow_) { downloader_checked = allow_; }
|
||||
bool is_checked() const { return downloader_checked; }
|
||||
wxString path_name() const { return m_input_path ? m_input_path->GetValue() : wxString(); }
|
||||
|
||||
void set_path_name(wxString name);
|
||||
void set_path_name(const std::string& name);
|
||||
|
||||
bool on_finish();
|
||||
bool perform_register(const std::string& path_override = {});
|
||||
#ifdef __linux__
|
||||
bool get_perform_registration_linux() { return perform_registration_linux; }
|
||||
#endif // __linux__
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct PageDownloader : ConfigWizardPage
|
||||
{
|
||||
DownloaderUtils::Worker* downloader{ nullptr };
|
||||
DownloaderUtils::Worker* m_downloader { nullptr };
|
||||
|
||||
PageDownloader(ConfigWizard* parent);
|
||||
|
||||
|
@ -218,9 +218,9 @@ bool DesktopIntegrationDialog::integration_possible()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
void DesktopIntegrationDialog::perform_desktop_integration(bool perform_downloader)
|
||||
void DesktopIntegrationDialog::perform_desktop_integration()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "performing desktop integration. With downloader integration: " << perform_downloader;
|
||||
BOOST_LOG_TRIVIAL(debug) << "performing desktop integration.";
|
||||
// Path to appimage
|
||||
const char *appimage_env = std::getenv("APPIMAGE");
|
||||
std::string excutable_path;
|
||||
@ -423,38 +423,6 @@ void DesktopIntegrationDialog::perform_desktop_integration(bool perform_download
|
||||
show_error(nullptr, _L("Performing desktop integration failed - could not create Gcodeviewer desktop file. PrusaSlicer desktop file was probably created successfully."));
|
||||
}
|
||||
}
|
||||
|
||||
if (perform_downloader)
|
||||
{
|
||||
std::string desktop_file_downloader = GUI::format(
|
||||
"[Desktop Entry]\n"
|
||||
"Name=PrusaSlicer URL Protocol%1%\n"
|
||||
"Exec=\"%3%\" --single-instance %%u\n"
|
||||
"Icon=PrusaSlicer%4%\n"
|
||||
"Terminal=false\n"
|
||||
"Type=Application\n"
|
||||
"MimeType=x-scheme-handler/prusaslicer;\n"
|
||||
"StartupNotify=false\n"
|
||||
, name_suffix, version_suffix, excutable_path, version_suffix);
|
||||
|
||||
// desktop file for downloader as part of main app
|
||||
std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerURLProtocol%2%.desktop", target_dir_desktop, version_suffix);
|
||||
if (create_desktop_file(desktop_path, desktop_file_downloader)) {
|
||||
// save path to desktop file
|
||||
app_config->set("desktop_integration_URL_path", desktop_path);
|
||||
// finish registration on mime type
|
||||
std::string command = GUI::format("xdg-mime default PrusaSlicerURLProtocol%1%.desktop x-scheme-handler/prusaslicer", version_suffix);
|
||||
BOOST_LOG_TRIVIAL(debug) << "system command: " << command;
|
||||
int r = system(command.c_str());
|
||||
BOOST_LOG_TRIVIAL(debug) << "system result: " << r;
|
||||
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create URL Protocol desktop file";
|
||||
show_error(nullptr, _L("Performing desktop integration failed - could not create URL Protocol desktop file."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationSuccess);
|
||||
}
|
||||
void DesktopIntegrationDialog::undo_desktop_intgration()
|
||||
@ -487,15 +455,162 @@ void DesktopIntegrationDialog::undo_desktop_intgration()
|
||||
std::remove(path.c_str());
|
||||
}
|
||||
}
|
||||
// URL Protocol
|
||||
path = std::string(app_config->get("desktop_integration_URL_path"));
|
||||
if (!path.empty()) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "removing " << path;
|
||||
std::remove(path.c_str());
|
||||
}
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::UndoDesktopIntegrationSuccess);
|
||||
}
|
||||
void DesktopIntegrationDialog::perform_downloader_desktop_integration()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(debug) << "performing downloader desktop integration.";
|
||||
// Path to appimage
|
||||
const char* appimage_env = std::getenv("APPIMAGE");
|
||||
std::string excutable_path;
|
||||
if (appimage_env) {
|
||||
try {
|
||||
excutable_path = boost::filesystem::canonical(boost::filesystem::path(appimage_env)).string();
|
||||
}
|
||||
catch (std::exception&) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing downloader desktop integration failed - boost::filesystem::canonical did not return appimage path.";
|
||||
show_error(nullptr, _L("Performing downloader desktop integration failed - boost::filesystem::canonical did not return appimage path."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// not appimage - find executable
|
||||
excutable_path = boost::dll::program_location().string();
|
||||
//excutable_path = wxStandardPaths::Get().GetExecutablePath().string();
|
||||
BOOST_LOG_TRIVIAL(debug) << "non-appimage path to executable: " << excutable_path;
|
||||
if (excutable_path.empty())
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing downloader desktop integration failed - no executable found.";
|
||||
show_error(nullptr, _L("Performing downloader desktop integration failed - Could not find executable."));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Escape ' characters in appimage, other special symbols will be esacaped in desktop file by 'excutable_path'
|
||||
//boost::replace_all(excutable_path, "'", "'\\''");
|
||||
excutable_path = escape_string(excutable_path);
|
||||
|
||||
// Find directories icons and applications
|
||||
// $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored.
|
||||
// If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used.
|
||||
// $XDG_DATA_DIRS defines the preference-ordered set of base directories to search for data files in addition to the $XDG_DATA_HOME base directory.
|
||||
// The directories in $XDG_DATA_DIRS should be seperated with a colon ':'.
|
||||
// If $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used.
|
||||
std::vector<std::string>target_candidates;
|
||||
resolve_path_from_var("XDG_DATA_HOME", target_candidates);
|
||||
resolve_path_from_var("XDG_DATA_DIRS", target_candidates);
|
||||
|
||||
AppConfig* app_config = wxGetApp().app_config;
|
||||
// suffix string to create different desktop file for alpha, beta.
|
||||
|
||||
std::string version_suffix;
|
||||
std::string name_suffix;
|
||||
std::string version(SLIC3R_VERSION);
|
||||
if (version.find("alpha") != std::string::npos)
|
||||
{
|
||||
version_suffix = "-alpha";
|
||||
name_suffix = " - alpha";
|
||||
}
|
||||
else if (version.find("beta") != std::string::npos)
|
||||
{
|
||||
version_suffix = "-beta";
|
||||
name_suffix = " - beta";
|
||||
}
|
||||
|
||||
// theme path to icon destination
|
||||
std::string icon_theme_path;
|
||||
std::string icon_theme_dirs;
|
||||
|
||||
if (platform_flavor() == PlatformFlavor::LinuxOnChromium) {
|
||||
icon_theme_path = "hicolor/96x96/apps/";
|
||||
icon_theme_dirs = "/hicolor/96x96/apps";
|
||||
}
|
||||
|
||||
std::string target_dir_desktop;
|
||||
|
||||
// desktop file
|
||||
// iterate thru target_candidates to find applications folder
|
||||
|
||||
std::string desktop_file_downloader = GUI::format(
|
||||
"[Desktop Entry]\n"
|
||||
"Name=PrusaSlicer URL Protocol%1%\n"
|
||||
"Exec=\"%2%\" --single-instance %%u\n"
|
||||
"Terminal=false\n"
|
||||
"Type=Application\n"
|
||||
"MimeType=x-scheme-handler/prusaslicer;\n"
|
||||
"StartupNotify=false\n"
|
||||
"NoDisplay=true\n"
|
||||
, name_suffix, excutable_path);
|
||||
|
||||
// desktop file for downloader as part of main app
|
||||
std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerURLProtocol%2%.desktop", target_dir_desktop, version_suffix);
|
||||
if (create_desktop_file(desktop_path, desktop_file_downloader)) {
|
||||
// save path to desktop file
|
||||
app_config->set("desktop_integration_URL_path", desktop_path);
|
||||
// finish registration on mime type
|
||||
std::string command = GUI::format("xdg-mime default PrusaSlicerURLProtocol%1%.desktop x-scheme-handler/prusaslicer", version_suffix);
|
||||
BOOST_LOG_TRIVIAL(debug) << "system command: " << command;
|
||||
int r = system(command.c_str());
|
||||
BOOST_LOG_TRIVIAL(debug) << "system result: " << r;
|
||||
|
||||
}
|
||||
|
||||
bool candidate_found = false;
|
||||
for (size_t i = 0; i < target_candidates.size(); ++i) {
|
||||
if (contains_path_dir(target_candidates[i], "applications")) {
|
||||
target_dir_desktop = target_candidates[i];
|
||||
// Write slicer desktop file
|
||||
std::string path = GUI::format("%1%/applications/PrusaSlicerURLProtocol%2%.desktop", target_dir_desktop, version_suffix);
|
||||
if (create_desktop_file(path, desktop_file_downloader)) {
|
||||
app_config->set("desktop_integration_URL_path", path);
|
||||
candidate_found = true;
|
||||
BOOST_LOG_TRIVIAL(debug) << "PrusaSlicerURLProtocol.desktop file installation success.";
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// write failed - try another path
|
||||
BOOST_LOG_TRIVIAL(debug) << "Attempt to PrusaSlicerURLProtocol.desktop file installation failed. failed path: " << target_candidates[i];
|
||||
target_dir_desktop.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
// if all failed - try creating default home folder
|
||||
if (!candidate_found) {
|
||||
// create $HOME/.local/share
|
||||
create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/applications");
|
||||
// create desktop file
|
||||
target_dir_desktop = GUI::format("%1%/.local/share", wxFileName::GetHomeDir());
|
||||
std::string path = GUI::format("%1%/applications/PrusaSlicerURLProtocol%2%.desktop", target_dir_desktop, version_suffix);
|
||||
if (contains_path_dir(target_dir_desktop, "applications")) {
|
||||
if (!create_desktop_file(path, desktop_file_downloader)) {
|
||||
// Desktop file not written - end desktop integration
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing downloader desktop integration failed - could not create desktop file.";
|
||||
return;
|
||||
}
|
||||
app_config->set("desktop_integration_URL_path", path);
|
||||
}
|
||||
else {
|
||||
// Desktop file not written - end desktop integration
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing downloader desktop integration failed because the application directory was not found.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(!target_dir_desktop.empty());
|
||||
if (target_dir_desktop.empty()) {
|
||||
// Desktop file not written - end desktop integration
|
||||
BOOST_LOG_TRIVIAL(error) << "Performing downloader desktop integration failed because the application directory was not found.";
|
||||
show_error(nullptr, _L("Performing downloader desktop integration failed because the application directory was not found."));
|
||||
return;
|
||||
}
|
||||
|
||||
// finish registration on mime type
|
||||
std::string command = GUI::format("xdg-mime default PrusaSlicerURLProtocol%1%.desktop x-scheme-handler/prusaslicer", version_suffix);
|
||||
BOOST_LOG_TRIVIAL(debug) << "system command: " << command;
|
||||
int r = system(command.c_str());
|
||||
BOOST_LOG_TRIVIAL(debug) << "system result: " << r;
|
||||
|
||||
wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationSuccess);
|
||||
}
|
||||
void DesktopIntegrationDialog::undo_downloader_registration()
|
||||
{
|
||||
const AppConfig *app_config = wxGetApp().app_config;
|
||||
@ -532,7 +647,7 @@ DesktopIntegrationDialog::DesktopIntegrationDialog(wxWindow *parent)
|
||||
wxButton *btn_perform = new wxButton(this, wxID_ANY, _L("Perform"));
|
||||
btn_szr->Add(btn_perform, 0, wxALL, 10);
|
||||
|
||||
btn_perform->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { DesktopIntegrationDialog::perform_desktop_integration(false); EndModal(wxID_ANY); });
|
||||
btn_perform->Bind(wxEVT_BUTTON, [this](wxCommandEvent &) { DesktopIntegrationDialog::perform_desktop_integration(); EndModal(wxID_ANY); });
|
||||
|
||||
if (can_undo){
|
||||
wxButton *btn_undo = new wxButton(this, wxID_ANY, _L("Undo"));
|
||||
|
@ -29,10 +29,11 @@ public:
|
||||
// if perform_downloader:
|
||||
// Creates Destktop files for PrusaSlicer downloader feature
|
||||
// Regiters PrusaSlicer to start on prusaslicer:// URL
|
||||
static void perform_desktop_integration(bool perform_downloader);
|
||||
static void perform_desktop_integration();
|
||||
// Deletes Desktop files and icons for both PrusaSlicer and GcodeViewer at paths stored in App Config.
|
||||
static void undo_desktop_intgration();
|
||||
|
||||
static void perform_downloader_desktop_integration();
|
||||
static void undo_downloader_registration();
|
||||
private:
|
||||
|
||||
|
@ -137,13 +137,30 @@ void FileGet::priv::get_perform()
|
||||
std::string extension = boost::filesystem::extension(dest_path);
|
||||
std::string just_filename = m_filename.substr(0, m_filename.size() - extension.size());
|
||||
std::string final_filename = just_filename;
|
||||
|
||||
size_t version = 0;
|
||||
while (boost::filesystem::exists(m_dest_folder / (final_filename + extension)) || boost::filesystem::exists(m_dest_folder / (final_filename + extension + "." + std::to_string(get_current_pid()) + ".download")))
|
||||
// Find unsed filename
|
||||
try {
|
||||
size_t version = 0;
|
||||
while (boost::filesystem::exists(m_dest_folder / (final_filename + extension)) || boost::filesystem::exists(m_dest_folder / (final_filename + extension + "." + std::to_string(get_current_pid()) + ".download")))
|
||||
{
|
||||
++version;
|
||||
if (version > 999) {
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
|
||||
evt->SetString(GUI::format_wxstr(L"Failed to find suitable filename. Last name: %1%." , (m_dest_folder / (final_filename + extension)).string()));
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
return;
|
||||
}
|
||||
final_filename = GUI::format("%1%(%2%)", just_filename, std::to_string(version));
|
||||
}
|
||||
} catch (const boost::filesystem::filesystem_error& e)
|
||||
{
|
||||
++version;
|
||||
final_filename = just_filename + "(" + std::to_string(version) + ")";
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_DWNLDR_FILE_ERROR);
|
||||
evt->SetString(e.what());
|
||||
evt->SetInt(m_id);
|
||||
m_evt_handler->QueueEvent(evt);
|
||||
return;
|
||||
}
|
||||
|
||||
m_filename = final_filename + extension;
|
||||
|
||||
m_tmp_path = m_dest_folder / (m_filename + "." + std::to_string(get_current_pid()) + ".download");
|
||||
|
@ -172,16 +172,20 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
||||
wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX)
|
||||
, m_selected_paths (selected_paths)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wxGetApp().UpdateDarkUI(this);
|
||||
#else
|
||||
SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
||||
#endif
|
||||
|
||||
int em = em_unit();
|
||||
|
||||
wxBoxSizer* topSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
|
||||
m_avc = new ArchiveViewCtrl(this, wxSize(60 * em, 30 * em));
|
||||
m_avc->AppendToggleColumn(L"\u2714", 0, wxDATAVIEW_CELL_ACTIVATABLE, 6 * em);
|
||||
m_avc = new ArchiveViewCtrl(this, wxSize(45 * em, 30 * em));
|
||||
wxDataViewColumn* toggle_column = m_avc->AppendToggleColumn(L"\u2714", 0, wxDATAVIEW_CELL_ACTIVATABLE, 6 * em);
|
||||
m_avc->AppendTextColumn("filename", 1);
|
||||
|
||||
|
||||
std::vector<std::shared_ptr<ArchiveViewNode>> stack;
|
||||
|
||||
std::function<void(std::vector<std::shared_ptr<ArchiveViewNode> >&, size_t)> reduce_stack = [] (std::vector<std::shared_ptr<ArchiveViewNode>>& stack, size_t size) {
|
||||
@ -233,40 +237,51 @@ FileArchiveDialog::FileArchiveDialog(wxWindow* parent_window, mz_zip_archive* ar
|
||||
}
|
||||
// sorting files will help adjust_stack function to not create multiple same folders
|
||||
std::sort(filtered_entries.begin(), filtered_entries.end(), [](const boost::filesystem::path& p1, const boost::filesystem::path& p2){ return p1.string() > p2.string(); });
|
||||
size_t entry_count = 0;
|
||||
size_t depth = 1;
|
||||
for (const boost::filesystem::path& path : filtered_entries)
|
||||
{
|
||||
std::shared_ptr<ArchiveViewNode> parent(nullptr);
|
||||
|
||||
adjust_stack(path, stack);
|
||||
depth = std::max(depth, adjust_stack(path, stack));
|
||||
if (!stack.empty())
|
||||
parent = stack.back();
|
||||
if (std::regex_match(path.extension().string(), pattern_drop)) { // this leaves out non-compatible files
|
||||
m_avc->get_model()->AddFile(parent, GUI::format_wxstr(path.filename().string()), false)->set_fullpath(/*std::move(path)*/path); // filename string to wstring?
|
||||
entry_count++;
|
||||
}
|
||||
}
|
||||
if (entry_count == 1)
|
||||
on_all_button();
|
||||
|
||||
toggle_column->SetWidth((4 + depth) * em);
|
||||
|
||||
wxBoxSizer* btn_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxButton* btn_all = new wxButton(this, wxID_ANY, "All");
|
||||
wxButton* btn_all = new wxButton(this, wxID_ANY, _L("All"));
|
||||
btn_all->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) { on_all_button(); });
|
||||
btn_sizer->Add(btn_all, 0, wxLeft);
|
||||
btn_sizer->Add(btn_all, 0);
|
||||
|
||||
wxButton* btn_none = new wxButton(this, wxID_ANY, "None");
|
||||
wxButton* btn_none = new wxButton(this, wxID_ANY, _L("None"));
|
||||
btn_none->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) { on_none_button(); });
|
||||
btn_sizer->Add(btn_none, 0, wxLeft);
|
||||
btn_sizer->Add(btn_none, 0, wxLEFT, em);
|
||||
|
||||
btn_sizer->AddStretchSpacer();
|
||||
wxButton* btn_run = new wxButton(this, wxID_OK, "Open");
|
||||
wxButton* btn_run = new wxButton(this, wxID_OK, _L("Open"));
|
||||
btn_run->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) { on_open_button(); });
|
||||
btn_sizer->Add(btn_run, 0, wxRIGHT);
|
||||
btn_sizer->Add(btn_run, 0, wxRIGHT, em);
|
||||
|
||||
wxButton* cancel_btn = new wxButton(this, wxID_CANCEL, "Cancel");
|
||||
wxButton* cancel_btn = new wxButton(this, wxID_CANCEL, _L("Cancel"));
|
||||
cancel_btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& evt) { this->EndModal(wxID_CANCEL); });
|
||||
btn_sizer->Add(cancel_btn, 0, wxRIGHT);
|
||||
btn_sizer->Add(cancel_btn, 0, wxRIGHT, em);
|
||||
|
||||
topSizer->Add(m_avc, 1, wxEXPAND | wxALL, 10);
|
||||
topSizer->Add(btn_sizer, 0, wxEXPAND | wxALL, 10);
|
||||
this->SetMinSize(wxSize(80 * em, 30 * em));
|
||||
this->SetSizer(topSizer);
|
||||
SetMinSize(wxSize(40 * em, 30 * em));
|
||||
|
||||
for (const wxString& id : {_L("All"), _L("None"), _L("Open"), _L("Cancel") })
|
||||
wxGetApp().UpdateDarkUI(static_cast<wxButton*>(FindWindowByLabel(id, this)));
|
||||
}
|
||||
|
||||
void FileArchiveDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
@ -277,9 +292,8 @@ void FileArchiveDialog::on_dpi_changed(const wxRect& suggested_rect)
|
||||
//for (auto btn : { m_save_btn, m_transfer_btn, m_discard_btn })
|
||||
// if (btn) btn->msw_rescale();
|
||||
|
||||
const wxSize& size = wxSize(70 * em, 30 * em);
|
||||
SetMinSize(size);
|
||||
|
||||
const wxSize& size = wxSize(45 * em, 40 * em);
|
||||
SetSize(size);
|
||||
//m_tree->Rescale(em);
|
||||
|
||||
Fit();
|
||||
|
@ -7055,7 +7055,7 @@ void GLCanvas3D::GizmoHighlighter::init(GLGizmosManager* manager, GLGizmosManage
|
||||
{
|
||||
if (m_timer.IsRunning())
|
||||
invalidate();
|
||||
if (!gizmo || !canvas)
|
||||
if (gizmo == GLGizmosManager::EType::Undefined || !canvas)
|
||||
return;
|
||||
|
||||
m_timer.Start(300, false);
|
||||
|
@ -79,7 +79,6 @@
|
||||
#include "DesktopIntegrationDialog.hpp"
|
||||
#include "SendSystemInfoDialog.hpp"
|
||||
#include "Downloader.hpp"
|
||||
#include "ConfigWizard_private.hpp"
|
||||
|
||||
#include "BitmapCache.hpp"
|
||||
#include "Notebook.hpp"
|
||||
@ -2890,6 +2889,7 @@ void GUI_App::MacOpenURL(const wxString& url)
|
||||
{
|
||||
if (app_config && !app_config->get_bool("downloader_url_registered"))
|
||||
{
|
||||
notification_manager()->push_notification(NotificationType::URLNotRegistered);
|
||||
BOOST_LOG_TRIVIAL(error) << "Recieved command to open URL, but it is not allowed in app configuration. URL: " << url;
|
||||
return;
|
||||
}
|
||||
@ -3081,11 +3081,11 @@ void GUI_App::show_downloader_registration_dialog()
|
||||
), SLIC3R_APP_NAME, SLIC3R_VERSION)
|
||||
, true, wxYES_NO);
|
||||
if (msg.ShowModal() == wxID_YES) {
|
||||
auto downloader = new DownloaderUtils::Worker(nullptr);
|
||||
downloader->perform_register(app_config->get("url_downloader_dest"));
|
||||
auto downloader_worker = new DownloaderUtils::Worker(nullptr);
|
||||
downloader_worker->perform_register(app_config->get("url_downloader_dest"));
|
||||
#ifdef __linux__
|
||||
if (downloader->get_perform_registration_linux())
|
||||
DesktopIntegrationDialog::perform_desktop_integration(true);
|
||||
if (downloader_worker->get_perform_registration_linux())
|
||||
DesktopIntegrationDialog::perform_downloader_desktop_integration();
|
||||
#endif // __linux__
|
||||
} else {
|
||||
app_config->set("downloader_url_registered", "0");
|
||||
|
@ -306,8 +306,8 @@ public:
|
||||
Plater* plater();
|
||||
const Plater* plater() const;
|
||||
Model& model();
|
||||
NotificationManager * notification_manager();
|
||||
GalleryDialog * gallery_dialog();
|
||||
NotificationManager* notification_manager();
|
||||
GalleryDialog * gallery_dialog();
|
||||
Downloader* downloader();
|
||||
|
||||
// Parameters extracted from the command line to be passed to GUI after initialization.
|
||||
|
@ -244,7 +244,7 @@ std::string GLGizmoCut3D::get_tooltip() const
|
||||
if (m_hover_id == Z || (m_dragging && m_hover_id == CutPlane)) {
|
||||
double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0;
|
||||
std::string unit_str = " " + (m_imperial_units ? _u8L("inch") : _u8L("mm"));
|
||||
const BoundingBoxf3 tbb = transformed_bounding_box(m_plane_center);
|
||||
const BoundingBoxf3& tbb = m_transformed_bounding_box;
|
||||
if (tbb.max.z() >= 0.0) {
|
||||
double top = (tbb.min.z() <= 0.0 ? tbb.max.z() : tbb.size().z()) * koef;
|
||||
tooltip += format(top, 2) + " " + unit_str + " (" + _u8L("Top part") + ")";
|
||||
@ -401,7 +401,7 @@ bool GLGizmoCut3D::is_looking_forward() const
|
||||
|
||||
void GLGizmoCut3D::update_clipper()
|
||||
{
|
||||
BoundingBoxf3 box = bounding_box();
|
||||
BoundingBoxf3 box = m_bounding_box;
|
||||
|
||||
// update cut_normal
|
||||
Vec3d beg, end = beg = m_plane_center;
|
||||
@ -549,7 +549,7 @@ bool GLGizmoCut3D::render_slider_double_input(const std::string& label, float& v
|
||||
return !is_approx(old_val, value);
|
||||
};
|
||||
|
||||
const BoundingBoxf3 bbox = bounding_box();
|
||||
const BoundingBoxf3 bbox = m_bounding_box;
|
||||
const float mean_size = float((bbox.size().x() + bbox.size().y() + bbox.size().z()) / 9.0) * (m_imperial_units ? f_mm_to_in : 1.f);
|
||||
|
||||
ImGuiWrapper::text(label);
|
||||
@ -795,7 +795,7 @@ void GLGizmoCut3D::render_cut_plane_grabbers()
|
||||
|
||||
const Transform3d view_matrix = wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
|
||||
|
||||
const double mean_size = get_grabber_mean_size(bounding_box());
|
||||
const double mean_size = get_grabber_mean_size(m_bounding_box);
|
||||
double size;
|
||||
|
||||
const bool dragging_by_cut_plane = m_dragging && m_hover_id == CutPlane;
|
||||
@ -1033,7 +1033,7 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform()
|
||||
else if (!cut_line_processing()){
|
||||
const Transform3d trafo = translation_transform(m_plane_center) * m_rotation_m;
|
||||
|
||||
const BoundingBoxf3 box = bounding_box();
|
||||
const BoundingBoxf3 box = m_bounding_box;
|
||||
|
||||
const double size = get_half_size(get_grabber_mean_size(box));
|
||||
Vec3d scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
|
||||
@ -1183,7 +1183,11 @@ void GLGizmoCut3D::dragging_grabber_xy(const GLGizmoBase::UpdateData &data)
|
||||
|
||||
Vec3d rotation = Vec3d::Zero();
|
||||
rotation[m_hover_id] = theta;
|
||||
m_rotation_m = m_start_dragging_m * rotation_transform(rotation);
|
||||
|
||||
const Transform3d rotation_tmp = m_start_dragging_m * rotation_transform(rotation);
|
||||
if (m_rotation_m.rotation() != rotation_tmp.rotation())
|
||||
m_transformed_bounding_box = transformed_bounding_box(m_plane_center);
|
||||
m_rotation_m = rotation_tmp;
|
||||
|
||||
m_angle = theta;
|
||||
while (m_angle > two_pi)
|
||||
@ -1245,9 +1249,13 @@ void GLGizmoCut3D::on_stop_dragging()
|
||||
|
||||
void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool force/* = false*/)
|
||||
{
|
||||
if (m_plane_center == center_pos)
|
||||
return;
|
||||
|
||||
bool can_set_center_pos = force;
|
||||
BoundingBoxf3 tbb;
|
||||
if (!can_set_center_pos) {
|
||||
const BoundingBoxf3 tbb = transformed_bounding_box(center_pos);
|
||||
tbb = transformed_bounding_box(center_pos);
|
||||
if (tbb.max.z() > -1. && tbb.min.z() < 1.)
|
||||
can_set_center_pos = true;
|
||||
else {
|
||||
@ -1260,6 +1268,7 @@ void GLGizmoCut3D::set_center_pos(const Vec3d& center_pos, bool force/* = false*
|
||||
}
|
||||
|
||||
if (can_set_center_pos) {
|
||||
m_transformed_bounding_box = tbb;
|
||||
m_plane_center = center_pos;
|
||||
m_center_offset = m_plane_center - m_bb_center;
|
||||
}
|
||||
@ -1279,7 +1288,7 @@ BoundingBoxf3 GLGizmoCut3D::bounding_box() const
|
||||
return ret;
|
||||
}
|
||||
|
||||
BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(const Vec3d& plane_center, bool revert_move /*= false*/) const
|
||||
BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(const Vec3d& plane_center) const
|
||||
{
|
||||
// #ysFIXME !!!
|
||||
BoundingBoxf3 ret;
|
||||
@ -1299,10 +1308,7 @@ BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(const Vec3d& plane_center,
|
||||
Vec3d cut_center_offset = plane_center - instance_offset;
|
||||
cut_center_offset[Z] -= sel_info->get_sla_shift();
|
||||
|
||||
const auto move = translation_transform(-cut_center_offset);
|
||||
const auto move2 = translation_transform(plane_center);
|
||||
|
||||
const auto cut_matrix = (revert_move ? move2 : Transform3d::Identity()) * m_rotation_m.inverse() * move;
|
||||
const auto cut_matrix = Transform3d::Identity() * m_rotation_m.inverse() * translation_transform(-cut_center_offset);
|
||||
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||
@ -1335,6 +1341,8 @@ bool GLGizmoCut3D::update_bb()
|
||||
const BoundingBoxf3 box = bounding_box();
|
||||
if (m_max_pos != box.max || m_min_pos != box.min) {
|
||||
|
||||
m_bounding_box = box;
|
||||
|
||||
invalidate_cut_plane();
|
||||
|
||||
m_max_pos = box.max;
|
||||
@ -1388,7 +1396,7 @@ void GLGizmoCut3D::init_picking_models()
|
||||
}
|
||||
|
||||
if (!m_plane.model.is_initialized() && !m_hide_cut_plane && !m_connectors_editing) {
|
||||
const double cp_width = 0.02 * get_grabber_mean_size(bounding_box());
|
||||
const double cp_width = 0.02 * get_grabber_mean_size(m_bounding_box);
|
||||
indexed_triangle_set its = its_make_frustum_dowel((double)m_cut_plane_radius_koef * m_radius, cp_width, m_cut_plane_as_circle ? 180 : 4);
|
||||
m_plane.model.init_from(its);
|
||||
m_plane.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
|
||||
@ -1631,9 +1639,8 @@ void GLGizmoCut3D::render_build_size()
|
||||
{
|
||||
double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0;
|
||||
wxString unit_str = " " + (m_imperial_units ? _L("in") : _L("mm"));
|
||||
const BoundingBoxf3 tbb = transformed_bounding_box(m_plane_center);
|
||||
|
||||
Vec3d tbb_sz = tbb.size();
|
||||
Vec3d tbb_sz = m_transformed_bounding_box.size();
|
||||
wxString size = "X: " + double_to_string(tbb_sz.x() * koef, 2) + unit_str +
|
||||
", Y: " + double_to_string(tbb_sz.y() * koef, 2) + unit_str +
|
||||
", Z: " + double_to_string(tbb_sz.z() * koef, 2) + unit_str;
|
||||
@ -1646,7 +1653,7 @@ void GLGizmoCut3D::render_build_size()
|
||||
|
||||
void GLGizmoCut3D::reset_cut_plane()
|
||||
{
|
||||
set_center(bounding_box().center());
|
||||
set_center(m_bb_center);
|
||||
m_rotation_m = Transform3d::Identity();
|
||||
m_angle_arc.reset();
|
||||
update_clipper();
|
||||
@ -1746,7 +1753,7 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
||||
|
||||
const bool has_connectors = !connectors.empty();
|
||||
|
||||
const bool is_cut_plane_init = m_rotation_m.isApprox(Transform3d::Identity()) && bounding_box().center() == m_plane_center;
|
||||
const bool is_cut_plane_init = m_rotation_m.isApprox(Transform3d::Identity()) && m_bb_center == m_plane_center;
|
||||
m_imgui->disabled_begin(is_cut_plane_init);
|
||||
if (render_reset_button("cut_plane", _u8L("Reset cutting plane")))
|
||||
reset_cut_plane();
|
||||
@ -1838,10 +1845,9 @@ void GLGizmoCut3D::render_cut_plane_input_window(CutConnectors &connectors)
|
||||
add_vertical_scaled_interval(0.75f);
|
||||
|
||||
m_imgui->disabled_begin(has_connectors);
|
||||
add_horizontal_shift(m_imgui->scaled(/*1*/.2f));
|
||||
ImGuiWrapper::text(_L("Cut to") + ":");
|
||||
|
||||
ImGui::SameLine();
|
||||
add_horizontal_scaled_interval(1.2f);
|
||||
if (m_imgui->radio_button(_L("Objects"), !m_keep_as_parts))
|
||||
m_keep_as_parts = false;
|
||||
ImGui::SameLine();
|
||||
@ -1990,38 +1996,6 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
|
||||
render_debug_input_window(x);
|
||||
}
|
||||
|
||||
// get volume transformation regarding to the "border". Border is related from the size of connectors
|
||||
Transform3d GLGizmoCut3D::get_volume_transformation(const ModelVolume* volume) const
|
||||
{
|
||||
bool is_prizm_dowel = m_connector_type == CutConnectorType::Dowel && m_connector_style == size_t(CutConnectorStyle::Prizm);
|
||||
#if ENABLE_WORLD_COORDINATE
|
||||
const Transform3d connector_trafo = is_prizm_dowel ?
|
||||
Geometry::translation_transform(-m_connector_depth_ratio * Vec3d::UnitZ()) * m_rotation_m * Geometry::scale_transform({ 0.5 * m_connector_size, 0.5 * m_connector_size, 2 * m_connector_depth_ratio }) :
|
||||
m_rotation_m * Geometry::scale_transform({ 0.5 * m_connector_size, 0.5 * m_connector_size, m_connector_depth_ratio });
|
||||
|
||||
#else
|
||||
const Transform3d connector_trafo = assemble_transform(
|
||||
is_prizm_dowel ? Vec3d(0.0, 0.0, -m_connector_depth_ratio) : Vec3d::Zero(),
|
||||
Transformation(m_rotation_m).get_rotation(),
|
||||
Vec3d(0.5*m_connector_size, 0.5*m_connector_size, is_prizm_dowel ? 2 * m_connector_depth_ratio : m_connector_depth_ratio),
|
||||
Vec3d::Ones());
|
||||
#endif // ENABLE_WORLD_COORDINATE
|
||||
const Vec3d connector_bb = m_connector_mesh.transformed_bounding_box(connector_trafo).size();
|
||||
|
||||
const Vec3d bb = volume->mesh().bounding_box().size();
|
||||
|
||||
// calculate an unused border - part of the the volume, where we can't put connectors
|
||||
const Vec3d border_scale(connector_bb.x() / bb.x(), connector_bb.y() / bb.y(), connector_bb.z() / bb.z());
|
||||
|
||||
const Transform3d vol_matrix = volume->get_matrix();
|
||||
const Vec3d vol_trans = vol_matrix.translation();
|
||||
// offset of the volume will be changed after scaling, so calculate the needed offset and set it to a volume_trafo
|
||||
const Vec3d offset(vol_trans.x() * border_scale.x(), vol_trans.y() * border_scale.y(), vol_trans.z() * border_scale.z());
|
||||
|
||||
// scale and translate volume to suppress to put connectors too close to the border
|
||||
return translation_transform(offset) * scale_transform(Vec3d::Ones() - border_scale) * vol_matrix;
|
||||
}
|
||||
|
||||
bool GLGizmoCut3D::is_outside_of_cut_contour(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos)
|
||||
{
|
||||
// check if connector pos is out of clipping plane
|
||||
@ -2072,7 +2046,7 @@ bool GLGizmoCut3D::is_conflict_for_connector(size_t idx, const CutConnectors& co
|
||||
const BoundingBoxf3 cur_tbb = m_shapes[cur_connector.attribs].model.get_bounding_box().transformed(matrix);
|
||||
|
||||
// check if connector's bounding box is inside the object's bounding box
|
||||
if (!bounding_box().contains(cur_tbb)) {
|
||||
if (!m_bounding_box.contains(cur_tbb)) {
|
||||
m_info_stats.outside_bb++;
|
||||
return true;
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ class GLGizmoCut3D : public GLGizmoBase
|
||||
Vec3d m_bb_center{ Vec3d::Zero() };
|
||||
Vec3d m_center_offset{ Vec3d::Zero() };
|
||||
|
||||
BoundingBoxf3 m_bounding_box;
|
||||
BoundingBoxf3 m_transformed_bounding_box;
|
||||
|
||||
// values from RotationGizmo
|
||||
double m_radius{ 0.0 };
|
||||
double m_grabber_radius{ 0.0 };
|
||||
@ -193,7 +196,7 @@ public:
|
||||
void invalidate_cut_plane();
|
||||
|
||||
BoundingBoxf3 bounding_box() const;
|
||||
BoundingBoxf3 transformed_bounding_box(const Vec3d& plane_center, bool revert_move = false) const;
|
||||
BoundingBoxf3 transformed_bounding_box(const Vec3d& plane_center) const;
|
||||
|
||||
protected:
|
||||
bool on_init() override;
|
||||
@ -263,7 +266,6 @@ private:
|
||||
void render_connect_mode_radio_button(CutConnectorMode mode);
|
||||
bool render_reset_button(const std::string& label_id, const std::string& tooltip) const;
|
||||
bool render_connect_type_radio_button(CutConnectorType type);
|
||||
Transform3d get_volume_transformation(const ModelVolume* volume) const;
|
||||
bool is_outside_of_cut_contour(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos);
|
||||
bool is_conflict_for_connector(size_t idx, const CutConnectors& connectors, const Vec3d cur_pos);
|
||||
void render_connectors();
|
||||
|
@ -521,7 +521,7 @@ void GLGizmoFdmSupports::auto_generate()
|
||||
{
|
||||
std::string err = wxGetApp().plater()->fff_print().validate();
|
||||
if (!err.empty()) {
|
||||
MessageDialog dlg(GUI::wxGetApp().plater(), _L("Automatic painting requires valid print setup. \n") + err, _L("Warning"), wxOK);
|
||||
MessageDialog dlg(GUI::wxGetApp().plater(), _L("Automatic painting requires valid print setup. \n") + from_u8(err), _L("Warning"), wxOK);
|
||||
dlg.ShowModal();
|
||||
return;
|
||||
}
|
||||
|
@ -740,6 +740,7 @@ void GLGizmosManager::render_arrow(const GLCanvas3D& parent, EType highlighted_t
|
||||
const float icons_size_x = 2.0f * m_layout.scaled_icons_size() * inv_cnv_w;
|
||||
const float icons_size_y = 2.0f * m_layout.scaled_icons_size() * inv_cnv_h;
|
||||
const float stride_y = 2.0f * m_layout.scaled_stride_y() * inv_cnv_h;
|
||||
top_y -= stride_y;
|
||||
|
||||
for (size_t idx : selectable_idxs) {
|
||||
if (idx == highlighted_type) {
|
||||
|
@ -120,7 +120,9 @@ enum class NotificationType
|
||||
// Short meesage to fill space between start and finish of export
|
||||
ExportOngoing,
|
||||
// Progressbar of download from prusaslicer:// url
|
||||
URLDownload
|
||||
URLDownload,
|
||||
// MacOS specific - PS comes forward even when downloader is not allowed
|
||||
URLNotRegistered,
|
||||
};
|
||||
|
||||
class NotificationManager
|
||||
@ -916,6 +918,16 @@ private:
|
||||
{NotificationType::UndoDesktopIntegrationFail, NotificationLevel::WarningNotificationLevel, 10,
|
||||
_u8L("Undo desktop integration failed.") },
|
||||
{NotificationType::ExportOngoing, NotificationLevel::RegularNotificationLevel, 0, _u8L("Exporting.") },
|
||||
{NotificationType::URLNotRegistered
|
||||
, NotificationLevel::RegularNotificationLevel
|
||||
, 10
|
||||
, _u8L("PrusaSlicer recieved a download request from Printables.com, but it's not allowed. You can allow it")
|
||||
, _u8L("here.")
|
||||
, [](wxEvtHandler* evnthndlr) {
|
||||
wxGetApp().open_preferences("downloader_url_registered", "Other");
|
||||
return true;
|
||||
} },
|
||||
|
||||
//{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotificationLevel, 20, _u8L("New version is available."), _u8L("See Releases page."), [](wxEvtHandler* evnthndlr) {
|
||||
// wxGetApp().open_browser_with_warning_dialog("https://github.com/prusa3d/PrusaSlicer/releases"); return true; }},
|
||||
//{NotificationType::NewAppAvailable, NotificationLevel::ImportantNotificationLevel, 20, _u8L("New vesion of PrusaSlicer is available.", _u8L("Download page.") },
|
||||
|
@ -10,7 +10,7 @@
|
||||
#include "ButtonsDescription.hpp"
|
||||
#include "OG_CustomCtrl.hpp"
|
||||
#include "GLCanvas3D.hpp"
|
||||
#include "ConfigWizard_private.hpp"
|
||||
#include "ConfigWizard.hpp"
|
||||
|
||||
#include <boost/dll/runtime_symbol_info.hpp>
|
||||
|
||||
@ -712,7 +712,7 @@ void PreferencesDialog::accept(wxEvent&)
|
||||
return;
|
||||
#ifdef __linux__
|
||||
if( downloader->get_perform_registration_linux())
|
||||
DesktopIntegrationDialog::perform_desktop_integration(true);
|
||||
DesktopIntegrationDialog::perform_downloader_desktop_integration();
|
||||
#endif // __linux__
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ class PreferencesDialog : public DPIDialog
|
||||
wxColourPickerCtrl* m_mode_advanced { nullptr };
|
||||
wxColourPickerCtrl* m_mode_expert { nullptr };
|
||||
|
||||
DownloaderUtils::Worker* downloader{ nullptr };
|
||||
DownloaderUtils::Worker* downloader { nullptr };
|
||||
|
||||
wxBookCtrlBase* tabs {nullptr};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user