starting prusaslicer from gcode viewer and vice versa, by menus or by stl drop on icon. Bring gcode viewer forward after start.
This commit is contained in:
parent
92b2d624a4
commit
4b224359ef
@ -838,7 +838,6 @@ bool GUI_App::on_init_inner()
|
||||
if (! plater_)
|
||||
return;
|
||||
|
||||
//m_other_instance_message_handler->report();
|
||||
|
||||
if (app_config->dirty() && app_config->get("autosave") == "1")
|
||||
app_config->save();
|
||||
@ -861,6 +860,7 @@ bool GUI_App::on_init_inner()
|
||||
static bool once = true;
|
||||
if (once) {
|
||||
once = false;
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if (preset_updater != nullptr) {
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
@ -904,6 +904,10 @@ bool GUI_App::on_init_inner()
|
||||
|
||||
update_mode(); // update view mode after fix of the object_list size
|
||||
|
||||
#ifdef __APPLE__
|
||||
other_instance_message_handler()->bring_instance_forward();
|
||||
#endif //__APPLE__
|
||||
|
||||
m_initialized = true;
|
||||
return true;
|
||||
}
|
||||
@ -1714,6 +1718,10 @@ void GUI_App::OSXStoreOpenFiles(const wxArrayString &fileNames)
|
||||
// Opening PrusaSlicer by drag & dropping a G-Code onto PrusaSlicer icon in Finder,
|
||||
// just G-codes were passed. Switch to G-code viewer mode.
|
||||
m_app_mode = EAppMode::GCodeViewer;
|
||||
if(app_config != nullptr)
|
||||
delete app_config;
|
||||
app_config = nullptr;
|
||||
init_app_config();
|
||||
}
|
||||
wxApp::OSXStoreOpenFiles(fileNames);
|
||||
}
|
||||
@ -1722,18 +1730,24 @@ void GUI_App::MacOpenFiles(const wxArrayString &fileNames)
|
||||
{
|
||||
std::vector<std::string> files;
|
||||
std::vector<wxString> gcode_files;
|
||||
std::vector<wxString> non_gcode_files;
|
||||
for (const auto& filename : fileNames) {
|
||||
wxString fn = filename.Upper();
|
||||
if (fn.EndsWith(".G") || fn.EndsWith(".GCODE"))
|
||||
gcode_files.emplace_back(filename);
|
||||
else
|
||||
else {
|
||||
files.emplace_back(into_u8(filename));
|
||||
non_gcode_files.emplace_back(filename);
|
||||
}
|
||||
}
|
||||
if (m_app_mode == EAppMode::GCodeViewer) {
|
||||
// Running in G-code viewer.
|
||||
// Load the first G-code into the G-code viewer.
|
||||
// Or if no G-codes, send other files to slicer.
|
||||
if (! gcode_files.empty())
|
||||
this->plater()->load_gcode(gcode_files.front());
|
||||
if (!non_gcode_files.empty())
|
||||
start_new_slicer(non_gcode_files, true);
|
||||
} else {
|
||||
if (! files.empty())
|
||||
this->plater()->load_files(files, true, true);
|
||||
|
@ -89,6 +89,8 @@ private:
|
||||
void unregister_for_messages();
|
||||
// Opaque pointer to RemovableDriveManagerMM
|
||||
void* m_impl_osx;
|
||||
public:
|
||||
void bring_instance_forward();
|
||||
#endif //__APPLE__
|
||||
|
||||
};
|
||||
|
@ -5,4 +5,5 @@
|
||||
-(instancetype) init;
|
||||
-(void) add_observer:(NSString *)version;
|
||||
-(void) message_update:(NSNotification *)note;
|
||||
-(void) bring_forward;
|
||||
@end
|
||||
|
@ -20,6 +20,13 @@
|
||||
-(void)message_update:(NSNotification *)msg
|
||||
{
|
||||
//NSLog(@"recieved msg %@", msg);
|
||||
[self bring_forward];
|
||||
//pass message
|
||||
Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(std::string([msg.userInfo[@"data"] UTF8String]));
|
||||
}
|
||||
|
||||
-(void) bring_forward
|
||||
{
|
||||
//demiaturize all windows
|
||||
for(NSWindow* win in [NSApp windows])
|
||||
{
|
||||
@ -30,8 +37,6 @@
|
||||
}
|
||||
//bring window to front
|
||||
[[NSApplication sharedApplication] activateIgnoringOtherApps : YES];
|
||||
//pass message
|
||||
Slic3r::GUI::wxGetApp().other_instance_message_handler()->handle_message(std::string([msg.userInfo[@"data"] UTF8String]));
|
||||
}
|
||||
|
||||
@end
|
||||
@ -67,6 +72,13 @@ void OtherInstanceMessageHandler::unregister_for_messages()
|
||||
NSLog(@"warning: unregister instance InstanceCheck notifications not required");
|
||||
}
|
||||
}
|
||||
|
||||
void OtherInstanceMessageHandler::bring_instance_forward()
|
||||
{
|
||||
if (m_impl_osx) {
|
||||
[m_impl_osx bring_forward];
|
||||
}
|
||||
}
|
||||
}//namespace GUI
|
||||
}//namespace Slicer
|
||||
|
||||
|
@ -68,15 +68,15 @@ class GCodeViewerTaskBarIcon : public wxTaskBarIcon
|
||||
{
|
||||
public:
|
||||
GCodeViewerTaskBarIcon(wxTaskBarIconType iconType = wxTBI_DEFAULT_TYPE) : wxTaskBarIcon(iconType) {}
|
||||
#if 0
|
||||
wxMenu *CreatePopupMenu() override {
|
||||
wxMenu *menu = new wxMenu;
|
||||
int id;
|
||||
auto *item = menu->Append(id = wxNewId(), "&Test menu");
|
||||
menu->Bind(wxEVT_MENU, [this](wxCommandEvent &) { wxMessageBox("Test menu - GCode Viewer"); }, id);
|
||||
//int id;
|
||||
//auto *item = menu->Append(id = wxNewId(), "&Test menu");
|
||||
//menu->Bind(wxEVT_MENU, [this](wxCommandEvent &) { wxMessageBox("Test menu - GCode Viewer"); }, id);
|
||||
append_menu_item(menu, wxID_ANY, _(L("Open PrusaSlicer")), _(L("")),
|
||||
[this](wxCommandEvent&) { start_new_slicer(nullptr, true); }, "", nullptr);
|
||||
return menu;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#endif // __APPLE__
|
||||
|
||||
@ -1258,7 +1258,8 @@ void MainFrame::init_menubar()
|
||||
|
||||
windowMenu->AppendSeparator();
|
||||
append_menu_item(windowMenu, wxID_ANY, _(L("Open new instance")) + "\tCtrl+I", _(L("Open a new PrusaSlicer instance")),
|
||||
[this](wxCommandEvent&) { start_new_slicer(); }, "", nullptr);
|
||||
[this](wxCommandEvent&) { start_new_slicer(); }, "", nullptr, [this]() {return m_plater != nullptr && wxGetApp().app_config->get("single_instance") != "1"; }, this);
|
||||
|
||||
}
|
||||
|
||||
// View menu
|
||||
@ -1392,6 +1393,9 @@ void MainFrame::init_menubar_as_gcodeviewer()
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Export &toolpaths as OBJ") + dots, _L("Export toolpaths as OBJ"),
|
||||
[this](wxCommandEvent&) { if (m_plater != nullptr) m_plater->export_toolpaths_to_obj(); }, "export_plater", nullptr,
|
||||
[this]() {return can_export_toolpaths(); }, this);
|
||||
append_menu_item(fileMenu, wxID_ANY, _L("Open &PrusaSlicer") + dots, _L("Open PrusaSlicer"),
|
||||
[this](wxCommandEvent&) { start_new_slicer(); }, "", nullptr,
|
||||
[this]() {return true; }, this);
|
||||
fileMenu->AppendSeparator();
|
||||
append_menu_item(fileMenu, wxID_EXIT, _L("&Quit"), wxString::Format(_L("Quit %s"), SLIC3R_APP_NAME),
|
||||
[this](wxCommandEvent&) { Close(false); });
|
||||
|
@ -1409,7 +1409,7 @@ bool PlaterDropTarget::OnDropFiles(wxCoord x, wxCoord y, const wxArrayString &fi
|
||||
else if (paths.size() == 1) {
|
||||
plater->load_gcode(from_path(paths.front()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
@ -1759,6 +1759,8 @@ struct Plater::priv
|
||||
|
||||
void msw_rescale_object_menu();
|
||||
|
||||
void bring_instance_forward() const;
|
||||
|
||||
// returns the path to project file with the given extension (none if extension == wxEmptyString)
|
||||
// extension should contain the leading dot, i.e.: ".3mf"
|
||||
wxString get_project_filename(const wxString& extension = wxEmptyString) const;
|
||||
@ -2040,23 +2042,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
this->load_files(evt.data, true, true);
|
||||
});
|
||||
this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent &) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "prusaslicer window going forward";
|
||||
//this code maximize app window on Fedora
|
||||
{
|
||||
wxGetApp().mainframe->Iconize(false);
|
||||
if (wxGetApp().mainframe->IsMaximized())
|
||||
wxGetApp().mainframe->Maximize(true);
|
||||
else
|
||||
wxGetApp().mainframe->Maximize(false);
|
||||
}
|
||||
//this code maximize window on Ubuntu
|
||||
{
|
||||
wxGetApp().mainframe->Restore();
|
||||
wxGetApp().GetTopWindow()->SetFocus(); // focus on my window
|
||||
wxGetApp().GetTopWindow()->Raise(); // bring window to front
|
||||
wxGetApp().GetTopWindow()->Show(true); // show the window
|
||||
}
|
||||
|
||||
bring_instance_forward();
|
||||
});
|
||||
wxGetApp().other_instance_message_handler()->init(this->q);
|
||||
|
||||
@ -4545,6 +4531,34 @@ void Plater::priv::update_after_undo_redo(const UndoRedo::Snapshot& snapshot, bo
|
||||
BOOST_LOG_TRIVIAL(info) << "Undo / Redo snapshot reloaded. Undo / Redo stack memory: " << Slic3r::format_memsize_MB(this->undo_redo_stack().memsize()) << log_memory_info();
|
||||
}
|
||||
|
||||
void Plater::priv::bring_instance_forward() const
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
wxGetApp().other_instance_message_handler()->bring_instance_forward();
|
||||
return;
|
||||
#endif //__APPLE__
|
||||
if (main_frame == nullptr) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "Couldnt bring instance forward - mainframe is null";
|
||||
return;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << "prusaslicer window going forward";
|
||||
//this code maximize app window on Fedora
|
||||
{
|
||||
main_frame->Iconize(false);
|
||||
if (main_frame->IsMaximized())
|
||||
main_frame->Maximize(true);
|
||||
else
|
||||
main_frame->Maximize(false);
|
||||
}
|
||||
//this code maximize window on Ubuntu
|
||||
{
|
||||
main_frame->Restore();
|
||||
wxGetApp().GetTopWindow()->SetFocus(); // focus on my window
|
||||
wxGetApp().GetTopWindow()->Raise(); // bring window to front
|
||||
wxGetApp().GetTopWindow()->Show(true); // show the window
|
||||
}
|
||||
}
|
||||
|
||||
void Sidebar::set_btn_label(const ActionButtonType btn_type, const wxString& label) const
|
||||
{
|
||||
switch (btn_type)
|
||||
@ -6016,6 +6030,10 @@ bool Plater::PopupMenu(wxMenu *menu, const wxPoint& pos)
|
||||
}
|
||||
return out;
|
||||
}
|
||||
void Plater::bring_instance_forward()
|
||||
{
|
||||
p->bring_instance_forward();
|
||||
}
|
||||
|
||||
SuppressBackgroundProcessingUpdate::SuppressBackgroundProcessingUpdate() :
|
||||
m_was_scheduled(wxGetApp().plater()->is_background_process_update_scheduled())
|
||||
|
@ -333,6 +333,8 @@ public:
|
||||
const NotificationManager* get_notification_manager() const;
|
||||
NotificationManager* get_notification_manager();
|
||||
|
||||
void bring_instance_forward();
|
||||
|
||||
// ROII wrapper for suppressing the Undo / Redo snapshot to be taken.
|
||||
class SuppressSnapshots
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ enum class NewSlicerInstanceType {
|
||||
|
||||
// Start a new Slicer process instance either in a Slicer mode or in a G-code mode.
|
||||
// Optionally load a 3MF, STL or a G-code on start.
|
||||
static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance_type, const wxString *path_to_open)
|
||||
static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance_type, const std::vector<wxString> paths_to_open, bool single_instance)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
wxString path;
|
||||
@ -41,10 +41,14 @@ static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance
|
||||
path += "\\";
|
||||
path += (instance_type == NewSlicerInstanceType::Slicer) ? "prusa-slicer.exe" : "prusa-gcodeviewer.exe";
|
||||
std::vector<const wchar_t*> args;
|
||||
args.reserve(3);
|
||||
args.reserve(4);
|
||||
args.emplace_back(path.wc_str());
|
||||
if (path_to_open != nullptr)
|
||||
args.emplace_back(path_to_open->wc_str());
|
||||
if (!paths_to_open.empty()) {
|
||||
for (const auto& file : paths_to_open)
|
||||
args.emplace_back(file);
|
||||
}
|
||||
if (instance_type == NewSlicerInstanceType::Slicer && single_instance)
|
||||
args.emplace_back(L"--single-instance");
|
||||
args.emplace_back(nullptr);
|
||||
BOOST_LOG_TRIVIAL(info) << "Trying to spawn a new slicer \"" << into_u8(path) << "\"";
|
||||
// Don't call with wxEXEC_HIDE_CONSOLE, PrusaSlicer in GUI mode would just show the splash screen. It would not open the main window though, it would
|
||||
@ -53,72 +57,92 @@ static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << into_u8(path);
|
||||
#else
|
||||
// Own executable path.
|
||||
boost::filesystem::path bin_path = into_path(wxStandardPaths::Get().GetExecutablePath());
|
||||
#if defined(__APPLE__)
|
||||
boost::filesystem::path bin_path = into_path(wxStandardPaths::Get().GetExecutablePath());
|
||||
#if defined(__APPLE__)
|
||||
{
|
||||
// Maybe one day we will be able to run PrusaGCodeViewer, but for now the Apple notarization
|
||||
// process refuses Apps with multiple binaries and Vojtech does not know any workaround.
|
||||
// ((instance_type == NewSlicerInstanceType::Slicer) ? "PrusaSlicer" : "PrusaGCodeViewer");
|
||||
// Just run PrusaSlicer and give it a --gcodeviewer parameter.
|
||||
bin_path = bin_path.parent_path() / "PrusaSlicer";
|
||||
bin_path = bin_path.parent_path() / "PrusaSlicer";
|
||||
// On Apple the wxExecute fails, thus we use boost::process instead.
|
||||
BOOST_LOG_TRIVIAL(info) << "Trying to spawn a new slicer \"" << bin_path.string() << "\"";
|
||||
try {
|
||||
std::vector<std::string> args;
|
||||
if (instance_type == NewSlicerInstanceType::GCodeViewer)
|
||||
args.emplace_back("--gcodeviewer");
|
||||
if (path_to_open)
|
||||
args.emplace_back(into_u8(*path_to_open));
|
||||
boost::process::spawn(bin_path, args);
|
||||
} catch (const std::exception &ex) {
|
||||
std::vector<std::string> args;
|
||||
if (instance_type == NewSlicerInstanceType::GCodeViewer)
|
||||
args.emplace_back("--gcodeviewer");
|
||||
if (!paths_to_open.empty()) {
|
||||
for (const auto& file : paths_to_open)
|
||||
args.emplace_back(into_u8(file));
|
||||
}
|
||||
if (instance_type == NewSlicerInstanceType::Slicer && single_instance)
|
||||
args.emplace_back("--single-instance");
|
||||
boost::process::spawn(bin_path, args);
|
||||
}
|
||||
catch (const std::exception& ex) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << bin_path.string() << "\": " << ex.what();
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // Linux or Unix
|
||||
#else // Linux or Unix
|
||||
{
|
||||
std::vector<const char*> args;
|
||||
args.reserve(3);
|
||||
#ifdef __linux
|
||||
static const char *gcodeviewer_param = "--gcodeviewer";
|
||||
{
|
||||
args.reserve(3);
|
||||
#ifdef __linux
|
||||
static const char* gcodeviewer_param = "--gcodeviewer";
|
||||
{
|
||||
// If executed by an AppImage, start the AppImage, not the main process.
|
||||
// see https://docs.appimage.org/packaging-guide/environment-variables.html#id2
|
||||
const char *appimage_binary = std::getenv("APPIMAGE");
|
||||
const char* appimage_binary = std::getenv("APPIMAGE");
|
||||
if (appimage_binary) {
|
||||
args.emplace_back(appimage_binary);
|
||||
if (instance_type == NewSlicerInstanceType::GCodeViewer)
|
||||
args.emplace_back(gcodeviewer_param);
|
||||
}
|
||||
}
|
||||
#endif // __linux
|
||||
#endif // __linux
|
||||
std::string my_path;
|
||||
if (args.empty()) {
|
||||
// Binary path was not set to the AppImage in the Linux specific block above, call the application directly.
|
||||
my_path = (bin_path.parent_path() / ((instance_type == NewSlicerInstanceType::Slicer) ? "prusa-slicer" : "prusa-gcodeviewer")).string();
|
||||
args.emplace_back(my_path.c_str());
|
||||
}
|
||||
std::string to_open;
|
||||
if (path_to_open) {
|
||||
to_open = into_u8(*path_to_open);
|
||||
args.emplace_back(to_open.c_str());
|
||||
}
|
||||
args.emplace_back(nullptr);
|
||||
std::string to_open;
|
||||
if (!paths_to_open.empty()) {
|
||||
for (const auto& file : paths_to_open) {
|
||||
to_open = into_u8(file);
|
||||
args.emplace_back(to_open.c_str());
|
||||
}
|
||||
}
|
||||
if (instance_type == NewSlicerInstanceType::Slicer && single_instance)
|
||||
args.emplace_back("--single-instance");
|
||||
args.emplace_back(nullptr);
|
||||
BOOST_LOG_TRIVIAL(info) << "Trying to spawn a new slicer \"" << args[0] << "\"";
|
||||
if (wxExecute(const_cast<char**>(args.data()), wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER) <= 0)
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << args[0];
|
||||
if (wxExecute(const_cast<char**>(args.data()), wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER) <= 0)
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to spawn a new slicer \"" << args[0];
|
||||
}
|
||||
#endif // Linux or Unix
|
||||
#endif // Linux or Unix
|
||||
#endif // Win32
|
||||
}
|
||||
|
||||
void start_new_slicer(const wxString *path_to_open)
|
||||
static void start_new_slicer_or_gcodeviewer(const NewSlicerInstanceType instance_type, const wxString* path_to_open, bool single_instance)
|
||||
{
|
||||
start_new_slicer_or_gcodeviewer(NewSlicerInstanceType::Slicer, path_to_open);
|
||||
std::vector<wxString> paths;
|
||||
if (path_to_open != nullptr)
|
||||
paths.emplace_back(path_to_open->wc_str());
|
||||
start_new_slicer_or_gcodeviewer(instance_type, paths, single_instance);
|
||||
}
|
||||
|
||||
void start_new_slicer(const wxString *path_to_open, bool single_instance)
|
||||
{
|
||||
start_new_slicer_or_gcodeviewer(NewSlicerInstanceType::Slicer, path_to_open, single_instance);
|
||||
}
|
||||
void start_new_slicer(const std::vector<wxString>& files, bool single_instance)
|
||||
{
|
||||
start_new_slicer_or_gcodeviewer(NewSlicerInstanceType::Slicer, files, single_instance);
|
||||
}
|
||||
|
||||
void start_new_gcodeviewer(const wxString *path_to_open)
|
||||
{
|
||||
start_new_slicer_or_gcodeviewer(NewSlicerInstanceType::GCodeViewer, path_to_open);
|
||||
start_new_slicer_or_gcodeviewer(NewSlicerInstanceType::GCodeViewer, path_to_open, false);
|
||||
}
|
||||
|
||||
void start_new_gcodeviewer_open_file(wxWindow *parent)
|
||||
|
@ -8,7 +8,9 @@ namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
// Start a new slicer instance, optionally with a file to open.
|
||||
void start_new_slicer(const wxString *path_to_open = nullptr);
|
||||
void start_new_slicer(const wxString *path_to_open = nullptr, bool single_instance = false);
|
||||
void start_new_slicer(const std::vector<wxString>& files, bool single_instance = false);
|
||||
|
||||
// Start a new G-code viewer instance, optionally with a file to open.
|
||||
void start_new_gcodeviewer(const wxString *path_to_open = nullptr);
|
||||
// Open a file dialog, ask the user to select a new G-code to open, start a new G-code viewer.
|
||||
|
Loading…
Reference in New Issue
Block a user