diff --git a/resources/images/notification_eject_sd.svg b/resources/images/notification_eject_sd.svg
new file mode 100644
index 0000000000..692c50d03b
--- /dev/null
+++ b/resources/images/notification_eject_sd.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/resources/images/notification_eject_sd_hover.svg b/resources/images/notification_eject_sd_hover.svg
new file mode 100644
index 0000000000..d41e03f097
--- /dev/null
+++ b/resources/images/notification_eject_sd_hover.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt
index 07be68a79c..1408ccc849 100644
--- a/src/slic3r/CMakeLists.txt
+++ b/src/slic3r/CMakeLists.txt
@@ -253,8 +253,8 @@ set(SLIC3R_GUI_SOURCES
GUI/wxExtensions.hpp
GUI/WipeTowerDialog.cpp
GUI/WipeTowerDialog.hpp
- #GUI/RemovableDriveManager.cpp
- #GUI/RemovableDriveManager.hpp
+ GUI/RemovableDriveManager.cpp
+ GUI/RemovableDriveManager.hpp
GUI/SendSystemInfoDialog.cpp
GUI/SendSystemInfoDialog.hpp
GUI/ImGuiWrapper.hpp
@@ -387,8 +387,8 @@ if (APPLE)
list(APPEND SLIC3R_GUI_SOURCES
Utils/RetinaHelperImpl.mm
Utils/MacDarkMode.mm
- #GUI/RemovableDriveManagerMM.mm
- #GUI/RemovableDriveManagerMM.h
+ GUI/RemovableDriveManagerMM.mm
+ GUI/RemovableDriveManagerMM.h
GUI/Mouse3DHandlerMac.mm
#GUI/InstanceCheckMac.mm
#GUI/InstanceCheckMac.h
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 61fdbe29fa..0b19e9bdb8 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -65,7 +65,7 @@
#include "SysInfoDialog.hpp"
#include "UpdateDialogs.hpp"
#include "Mouse3DController.hpp"
-//#include "RemovableDriveManager.hpp"
+#include "RemovableDriveManager.hpp"
#include "InstanceCheck.hpp"
#include "NotificationManager.hpp"
#include "UnsavedChangesDialog.hpp"
@@ -1119,7 +1119,7 @@ GUI_App::GUI_App()
, m_em_unit(10)
, m_imgui(new ImGuiWrapper())
, hms_query(new HMSQuery())
- //, m_removable_drive_manager(std::make_unique())
+ , m_removable_drive_manager(std::make_unique())
//, m_other_instance_message_handler(std::make_unique())
{
//app config initializes early becasuse it is used in instance checking in BambuStudio.cpp
diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp
index 2cacc0cc26..8f189f0952 100644
--- a/src/slic3r/GUI/GUI_App.hpp
+++ b/src/slic3r/GUI/GUI_App.hpp
@@ -49,7 +49,7 @@ class NetworkAgent;
namespace GUI{
-//class RemovableDriveManager;
+class RemovableDriveManager;
class OtherInstanceMessageHandler;
class MainFrame;
class Sidebar;
@@ -244,7 +244,7 @@ private:
const wxLanguageInfo *m_language_info_best = nullptr;
OpenGLManager m_opengl_mgr;
- //std::unique_ptr m_removable_drive_manager;
+ std::unique_ptr m_removable_drive_manager;
std::unique_ptr m_imgui;
//std::unique_ptr m_other_instance_message_handler;
@@ -479,7 +479,7 @@ public:
std::vector tabs_list;
std::vector model_tabs_list;
- //RemovableDriveManager* removable_drive_manager() { return m_removable_drive_manager.get(); }
+ RemovableDriveManager* removable_drive_manager() { return m_removable_drive_manager.get(); }
//OtherInstanceMessageHandler* other_instance_message_handler() { return m_other_instance_message_handler.get(); }
//wxSingleInstanceChecker* single_instance_checker() {return m_single_instance_checker.get();}
diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp
index 7c497219ef..9d7ec10142 100644
--- a/src/slic3r/GUI/ImGuiWrapper.cpp
+++ b/src/slic3r/GUI/ImGuiWrapper.cpp
@@ -71,8 +71,8 @@ static const std::map font_icons_large = {
{ImGui::CloseNotifButton , "notification_close" },
{ImGui::CloseNotifHoverButton , "notification_close_hover" },
//BBS removed
- //{ImGui::EjectButton , "notification_eject_sd" },
- //{ImGui::EjectHoverButton , "notification_eject_sd_hover" },
+ {ImGui::EjectButton , "notification_eject_sd" },
+ {ImGui::EjectHoverButton , "notification_eject_sd_hover" },
//{ImGui::WarningMarker , "notification_warning" },
//{ImGui::ErrorMarker , "notification_error" },
{ImGui::CancelButton , "notification_cancel" },
diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp
index 5ee129c3b9..d0532cca09 100644
--- a/src/slic3r/GUI/NotificationManager.cpp
+++ b/src/slic3r/GUI/NotificationManager.cpp
@@ -34,7 +34,7 @@ static constexpr int FADING_OUT_TIMEOUT = 100;
namespace Slic3r {
namespace GUI {
-//wxDEFINE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
+wxDEFINE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
wxDEFINE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
wxDEFINE_EVENT(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, PresetUpdateAvailableClickedEvent);
@@ -801,11 +801,11 @@ void NotificationManager::ExportFinishedNotification::render_text(ImGuiWrapper&
void NotificationManager::ExportFinishedNotification::render_close_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
PopNotification::render_close_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
- //if(m_to_removable && ! m_eject_pending)
- // render_eject_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
+ if (m_to_removable && !m_eject_pending)
+ render_eject_button(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
-/*void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
+void NotificationManager::ExportFinishedNotification::render_eject_button(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
ImVec2 win_size(win_size_x, win_size_y);
ImVec2 win_pos(win_pos_x, win_pos_y);
@@ -818,23 +818,25 @@ void NotificationManager::ExportFinishedNotification::render_close_button(ImGuiW
std::string button_text;
button_text = ImGui::EjectButton;
- if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - m_line_height * 5.f, win_pos.y),
+ if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - m_line_height * 5.f, win_pos.y),
ImVec2(win_pos.x - m_line_height * 2.5f, win_pos.y + win_size.y),
true))
{
button_text = ImGui::EjectHoverButton;
- // tooltip
+ //tooltip
+
long time_now = wxGetLocalTime();
if (m_hover_time > 0 && m_hover_time < time_now) {
ImGui::PushStyleColor(ImGuiCol_PopupBg, ImGuiWrapper::COL_WINDOW_BACKGROUND);
- ImGui::BeginTooltip();
- imgui.text(_u8L("Eject drive") + " " + GUI::shortkey_ctrl_prefix() + "T");
- ImGui::EndTooltip();
+ //ImGui::BeginTooltip();
+ //imgui.text(_u8L("Eject drive") + " " + GUI::shortkey_ctrl_prefix() + "T");
+ //ImGui::EndTooltip();
ImGui::PopStyleColor();
}
if (m_hover_time == 0)
m_hover_time = time_now;
- } else
+ }
+ else
m_hover_time = 0;
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
@@ -850,7 +852,7 @@ void NotificationManager::ExportFinishedNotification::render_close_button(ImGuiW
}
//invisible large button
- ImGui::SetCursorPosX(win_size.x - m_line_height * 4.625f);
+ ImGui::SetCursorPosX(win_size.x - m_line_height * 4.625f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.f, win_size.y))
{
@@ -860,7 +862,8 @@ void NotificationManager::ExportFinishedNotification::render_close_button(ImGuiW
on_eject_click();
}
ImGui::PopStyleColor(5);
-}*/
+}
+
bool NotificationManager::ExportFinishedNotification::on_text_click()
{
open_folder(m_export_dir_path);
diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp
index d758dbe061..a731c551a9 100644
--- a/src/slic3r/GUI/NotificationManager.hpp
+++ b/src/slic3r/GUI/NotificationManager.hpp
@@ -21,8 +21,8 @@
namespace Slic3r {
namespace GUI {
-//using EjectDriveNotificationClickedEvent = SimpleEvent;
-//wxDECLARE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
+using EjectDriveNotificationClickedEvent = SimpleEvent;
+wxDECLARE_EVENT(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, EjectDriveNotificationClickedEvent);
using ExportGcodeNotificationClickedEvent = SimpleEvent;
wxDECLARE_EVENT(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, ExportGcodeNotificationClickedEvent);
using PresetUpdateAvailableClickedEvent = SimpleEvent;
@@ -690,9 +690,9 @@ private:
void render_close_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
const float win_pos_x, const float win_pos_y) override;
- /*void render_eject_button(ImGuiWrapper& imgui,
+ void render_eject_button(ImGuiWrapper& imgui,
const float win_size_x, const float win_size_y,
- const float win_pos_x, const float win_pos_y);*/
+ const float win_pos_x, const float win_pos_y);
void render_minimize_button(ImGuiWrapper& imgui, const float win_pos_x, const float win_pos_y) override
{ m_minimize_b_visible = false; }
bool on_text_click() override;
diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp
index fe0938ad84..f7b7a6b349 100644
--- a/src/slic3r/GUI/Plater.cpp
+++ b/src/slic3r/GUI/Plater.cpp
@@ -91,7 +91,7 @@
#include "../Utils/UndoRedo.hpp"
#include "../Utils/PresetUpdater.hpp"
#include "../Utils/Process.hpp"
-//#include "RemovableDriveManager.hpp"
+#include "RemovableDriveManager.hpp"
#include "InstanceCheck.hpp"
#include "NotificationManager.hpp"
#include "PresetComboBoxes.hpp"
@@ -2240,12 +2240,11 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
//notification_manager = new NotificationManager(this->q);
if (wxGetApp().is_editor()) {
- //this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); });
+ this->q->Bind(EVT_EJECT_DRIVE_NOTIFICAION_CLICKED, [this](EjectDriveNotificationClickedEvent&) { this->q->eject_drive(); });
this->q->Bind(EVT_EXPORT_GCODE_NOTIFICAION_CLICKED, [this](ExportGcodeNotificationClickedEvent&) { this->q->export_gcode(true); });
this->q->Bind(EVT_PRESET_UPDATE_AVAILABLE_CLICKED, [](PresetUpdateAvailableClickedEvent&) { wxGetApp().get_preset_updater()->on_update_notification_confirm(); });
/* BBS do not handle removeable driver event */
- /*
this->q->Bind(EVT_REMOVABLE_DRIVE_EJECTED, [this](RemovableDriveEjectEvent &evt) {
if (evt.data.second) {
// BBS
@@ -2268,14 +2267,13 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
// Close notification ExportingFinished but only if last export was to removable
notification_manager->device_ejected();
});
- */
// Start the background thread and register this window as a target for update events.
- //wxGetApp().removable_drive_manager()->init(this->q);
-//#ifdef _WIN32
- // Trigger enumeration of removable media on Win32 notification.
- //this->q->Bind(EVT_VOLUME_ATTACHED, [this](VolumeAttachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
- //this->q->Bind(EVT_VOLUME_DETACHED, [this](VolumeDetachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
-//#endif /* _WIN32 */
+ wxGetApp().removable_drive_manager()->init(this->q);
+#ifdef _WIN32
+ //Trigger enumeration of removable media on Win32 notification.
+ this->q->Bind(EVT_VOLUME_ATTACHED, [this](VolumeAttachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
+ this->q->Bind(EVT_VOLUME_DETACHED, [this](VolumeDetachedEvent &evt) { wxGetApp().removable_drive_manager()->volumes_changed(); });
+#endif /* _WIN32 */
}
// Initialize the Undo / Redo stack with a first snapshot.
@@ -5382,16 +5380,16 @@ void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
notification_manager->close_notification_of_type(NotificationType::ExportOngoing);
}
// If writing to removable drive was scheduled, show notification with eject button
- /*if (exporting_status == ExportingStatus::EXPORTING_TO_REMOVABLE && !has_error) {
+ if (exporting_status == ExportingStatus::EXPORTING_TO_REMOVABLE && !has_error) {
//show_action_buttons(ready_to_slice);
this->main_frame->update_slice_print_status(MainFrame::eEventSliceUpdate, ready_to_slice, true);
notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path,
// Don't offer the "Eject" button on ChromeOS, the Linux side has no control over it.
platform_flavor() != PlatformFlavor::LinuxOnChromium);
- //wxGetApp().removable_drive_manager()->set_exporting_finished(true);
- }else */
- //if (exporting_status == ExportingStatus::EXPORTING_TO_LOCAL && !has_error)
- // notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path, false);
+ wxGetApp().removable_drive_manager()->set_exporting_finished(true);
+ }else
+ if (exporting_status == ExportingStatus::EXPORTING_TO_LOCAL && !has_error)
+ notification_manager->push_exporting_finished_notification(last_output_path, last_output_dir_path, false);
}
exporting_status = ExportingStatus::NOT_EXPORTING;
@@ -8172,16 +8170,16 @@ void Plater::export_gcode(bool prefer_removable)
}
default_output_file = fs::path(Slic3r::fold_utf8_to_ascii(default_output_file.string()));
AppConfig &appconfig = *wxGetApp().app_config;
- //RemovableDriveManager &removable_drive_manager = *wxGetApp().removable_drive_manager();
+ RemovableDriveManager &removable_drive_manager = *wxGetApp().removable_drive_manager();
// Get a last save path, either to removable media or to an internal media.
std::string start_dir = appconfig.get_last_output_dir(default_output_file.parent_path().string(), prefer_removable);
- /*if (prefer_removable) {
+ if (prefer_removable) {
// Returns a path to a removable media if it exists, prefering start_dir. Update the internal removable drives database.
start_dir = removable_drive_manager.get_removable_drive_path(start_dir);
if (start_dir.empty())
// Direct user to the last internal media.
start_dir = appconfig.get_last_output_dir(default_output_file.parent_path().string(), false);
- }*/
+ }
fs::path output_path;
{
@@ -8209,8 +8207,8 @@ void Plater::export_gcode(bool prefer_removable)
}
if (! output_path.empty()) {
- //bool path_on_removable_media = removable_drive_manager.set_and_verify_last_save_path(output_path.string());
- bool path_on_removable_media = false;
+ bool path_on_removable_media = removable_drive_manager.set_and_verify_last_save_path(output_path.string());
+ //bool path_on_removable_media = false;
p->notification_manager->new_export_began(path_on_removable_media);
p->exporting_status = path_on_removable_media ? ExportingStatus::EXPORTING_TO_REMOVABLE : ExportingStatus::EXPORTING_TO_LOCAL;
p->last_output_path = output_path.string();
@@ -8279,13 +8277,20 @@ void Plater::export_gcode_3mf()
p->notification_manager->new_export_began(path_on_removable_media);
p->exporting_status = path_on_removable_media ? ExportingStatus::EXPORTING_TO_REMOVABLE : ExportingStatus::EXPORTING_TO_LOCAL;
//BBS do not save last output path
- //p->last_output_path = output_path.string();
+ p->last_output_path = output_path.string();
p->last_output_dir_path = output_path.parent_path().string();
int curr_plate_idx = get_partplate_list().get_curr_plate_index();
export_3mf(output_path, SaveStrategy::Silence | SaveStrategy::SplitModel | SaveStrategy::WithGcode | SaveStrategy::SkipModel, curr_plate_idx); // BBS: silence
- // update lost output dir
+
+ RemovableDriveManager& removable_drive_manager = *wxGetApp().removable_drive_manager();
+
+
+ bool on_removable = removable_drive_manager.is_path_on_removable_drive(p->last_output_dir_path);
+
+
+ // update last output dir
appconfig.update_last_output_dir(output_path.parent_path().string(), false);
- p->notification_manager->push_exporting_finished_notification(output_path.string(), p->last_output_dir_path, false);
+ p->notification_manager->push_exporting_finished_notification(output_path.string(), p->last_output_dir_path, on_removable);
}
}
@@ -8925,11 +8930,12 @@ void Plater::print_job_finished(wxCommandEvent &evt)
}
// Called when the Eject button is pressed.
-/*void Plater::eject_drive()
+void Plater::eject_drive()
{
- wxBusyCursor wait;
- wxGetApp().removable_drive_manager()->eject_drive();
-}*/
+ wxBusyCursor wait;
+ wxGetApp().removable_drive_manager()->set_and_verify_last_save_path(p->last_output_dir_path);
+ wxGetApp().removable_drive_manager()->eject_drive();
+}
void Plater::take_snapshot(const std::string &snapshot_name) { p->take_snapshot(snapshot_name); }
//void Plater::take_snapshot(const wxString &snapshot_name) { p->take_snapshot(snapshot_name); }
diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp
index 2d24bae3a9..5460ffcdd1 100644
--- a/src/slic3r/GUI/Plater.hpp
+++ b/src/slic3r/GUI/Plater.hpp
@@ -332,7 +332,7 @@ public:
int export_config_3mf(int plate_idx = -1, Export3mfProgressFn proFn = nullptr);
//BBS jump to nonitor after print job finished
void print_job_finished(wxCommandEvent &evt);
- //void eject_drive();
+ void eject_drive();
void take_snapshot(const std::string &snapshot_name);
//void take_snapshot(const wxString &snapshot_name);
diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp
index 74e3bd371e..10c692a69b 100644
--- a/src/slic3r/GUI/RemovableDriveManager.cpp
+++ b/src/slic3r/GUI/RemovableDriveManager.cpp
@@ -442,7 +442,14 @@ bool RemovableDriveManager::set_and_verify_last_save_path(const std::string &pat
#ifndef REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
this->update();
#endif // REMOVABLE_DRIVE_MANAGER_OS_CALLBACKS
+
+#ifdef __APPLE__
+ m_last_save_path = path;
+#else
m_last_save_path = this->get_removable_drive_from_path(path);
+#endif
+
+
m_exporting_finished = false;
return ! m_last_save_path.empty();
}
diff --git a/src/slic3r/GUI/RemovableDriveManager.hpp b/src/slic3r/GUI/RemovableDriveManager.hpp
index 29363647c8..ea8b4e83a7 100644
--- a/src/slic3r/GUI/RemovableDriveManager.hpp
+++ b/src/slic3r/GUI/RemovableDriveManager.hpp
@@ -49,7 +49,7 @@ public:
RemovableDriveManager() = default;
RemovableDriveManager(RemovableDriveManager const&) = delete;
void operator=(RemovableDriveManager const&) = delete;
- ~RemovableDriveManager() { assert(! m_initialized); }
+ ~RemovableDriveManager() { /*assert(! m_initialized);*/ }
// Start the background thread and register this window as a target for update events.
// Register for OSX notifications.