ENH: Open Prinables.com Links and Zip Archives (#3823)

* Enable ability to open `prusaslicer://` links

* Add needed function to miniz

* Import Zip Functionality

Allows zip file to be drag and dropped or imported via the menu option

Based on prusa3d/PrusaSlicer@ce38e57 and current master branch files

* Update dialog style to match Orca

* Ensure link is from printables

* add toggle option in preferences

doesn't actually control anything yet

* Add Downloader classes

As-is from PS master

* Create Orca Styled Variant of Icons

* Add Icons to ImGui

* Use PS's Downloader impl for `prusaslicer://` links

* Implement URL Registering on Windows

* Implement prusaslicer:// link on macOS

* Remove unnecessary class name qualifier in Plater.hpp

* Add downloader desktop integration registration and undo

* Revert Info.plist

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
This commit is contained in:
Ocraftyone 2024-05-21 22:52:34 -04:00 committed by GitHub
parent 0dbf610226
commit a764d836e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 3109 additions and 41 deletions

View file

@ -1283,6 +1283,219 @@ void NotificationManager::UpdatedItemsInfoNotification::add_type(InfoItemType ty
update(data);
}
//------URLDownloadNotification----------------
void NotificationManager::URLDownloadNotification::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)
{
if (m_percentage < 0.f || m_percentage >= 1.f) {
render_close_button_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
if (m_percentage >= 1.f)
render_open_button_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
} else
render_pause_cancel_buttons_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
void NotificationManager::URLDownloadNotification::render_close_button_inner(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);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text;
// Orca: Change based on dark mode
button_text = m_is_dark ? ImGui::CloseNotifDarkButton : ImGui::CloseNotifButton;
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)),
true))
{
// Orca: Change based on dark mode
button_text = m_is_dark ? ImGui::CloseNotifHoverDarkButton : ImGui::CloseNotifHoverButton;
}
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
close();
}
//invisible large button
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)))
{
close();
}
ImGui::PopStyleColor(5);
}
void NotificationManager::URLDownloadNotification::render_pause_cancel_buttons_inner(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
render_cancel_button_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
render_pause_button_inner(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
}
void NotificationManager::URLDownloadNotification::render_pause_button_inner(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);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::wstring button_text;
// Orca: Change based on dark mode
button_text = m_is_dark ? (m_download_paused ? ImGui::PlayDarkButton : ImGui::PauseDarkButton) : (m_download_paused ? ImGui::PlayButton : ImGui::PauseButton);
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))
{
// Orca: Change based on dark mode
button_text = m_is_dark ? (m_download_paused ? ImGui::PlayHoverDarkButton : ImGui::PauseHoverDarkButton) : (m_download_paused ? ImGui::PlayHoverButton : ImGui::PauseHoverButton);
}
ImVec2 button_pic_size = ImGui::CalcTextSize(boost::nowide::narrow(button_text).c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(win_size.x - m_line_height * 5.0f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
trigger_user_action_callback(m_download_paused ? DownloaderUserAction::DownloadUserContinued : DownloaderUserAction::DownloadUserPaused);
}
//invisible large button
ImGui::SetCursorPosX(win_size.x - m_line_height * 4.625f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.f, win_size.y))
{
trigger_user_action_callback(m_download_paused ? DownloaderUserAction::DownloadUserContinued : DownloaderUserAction::DownloadUserPaused);
}
ImGui::PopStyleColor(5);
}
void NotificationManager::URLDownloadNotification::render_open_button_inner(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);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::wstring button_text;
// Orca: Change based on dark mode
button_text = m_is_dark ? ImGui::OpenDarkButton : ImGui::OpenButton;
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))
{
// Orca: Change based on dark mode
button_text = m_is_dark ? ImGui::OpenHoverDarkButton : ImGui::OpenHoverButton;
}
ImVec2 button_pic_size = ImGui::CalcTextSize(boost::nowide::narrow(button_text).c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(win_size.x - m_line_height * 5.0f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
trigger_user_action_callback(DownloaderUserAction::DownloadUserOpenedFolder);
}
//invisible large button
ImGui::SetCursorPosX(win_size.x - m_line_height * 4.625f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.f, win_size.y))
{
trigger_user_action_callback(DownloaderUserAction::DownloadUserOpenedFolder);
}
ImGui::PopStyleColor(5);
}
void NotificationManager::URLDownloadNotification::render_cancel_button_inner(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);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(.0f, .0f, .0f, .0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(.0f, .0f, .0f, .0f));
push_style_color(ImGuiCol_Text, ImVec4(1.f, 1.f, 1.f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
push_style_color(ImGuiCol_TextSelectedBg, ImVec4(0, .75f, .75f, 1.f), m_state == EState::FadingOut, m_current_fade_opacity);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(.0f, .0f, .0f, .0f));
std::string button_text;
button_text = ImGui::CancelButton;
if (ImGui::IsMouseHoveringRect(ImVec2(win_pos.x - win_size.x / 10.f, win_pos.y),
ImVec2(win_pos.x, win_pos.y + win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)),
true))
{
button_text = ImGui::CancelHoverButton;
}
ImVec2 button_pic_size = ImGui::CalcTextSize(button_text.c_str());
ImVec2 button_size(button_pic_size.x * 1.25f, button_pic_size.y * 1.25f);
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.75f);
ImGui::SetCursorPosY(win_size.y / 2 - button_size.y);
if (imgui.button(button_text.c_str(), button_size.x, button_size.y))
{
trigger_user_action_callback(DownloaderUserAction::DownloadUserCanceled);
}
//invisible large button
ImGui::SetCursorPosX(win_size.x - m_line_height * 2.35f);
ImGui::SetCursorPosY(0);
if (imgui.button(" ", m_line_height * 2.125, win_size.y - (m_minimize_b_visible ? 2 * m_line_height : 0)))
{
trigger_user_action_callback(DownloaderUserAction::DownloadUserCanceled);
}
ImGui::PopStyleColor(5);
}
void NotificationManager::URLDownloadNotification::trigger_user_action_callback(DownloaderUserAction action)
{
if (m_user_action_callback) {
if (m_user_action_callback(action, m_download_id)) {}
}
}
void NotificationManager::URLDownloadNotification::render_bar(ImGuiWrapper& imgui, const float win_size_x, const float win_size_y, const float win_pos_x, const float win_pos_y)
{
ProgressBarNotification::render_bar(imgui, win_size_x, win_size_y, win_pos_x, win_pos_y);
std::string text;
if (m_percentage < 0.f) {
text = _u8L("ERROR") + ": " + m_error_message;
} else if (m_percentage >= 1.f) {
text = _u8L("COMPLETED");
} else {
std::stringstream stream;
stream << std::fixed << std::setprecision(2) << (int)(m_percentage * 100) << "%";
text = stream.str();
}
ImGui::SetCursorPosX(m_left_indentation);
ImGui::SetCursorPosY(win_size_y / 2 + win_size_y / 6 - (m_multiline ? 0 : m_line_height / 4));
imgui.text(text.c_str());
}
void NotificationManager::URLDownloadNotification::count_spaces()
{
ProgressBarNotification::count_spaces();
m_window_width_offset = m_line_height * 6;
}
//------PrintHostUploadNotification----------------
void NotificationManager::PrintHostUploadNotification::init()
{
@ -1841,6 +2054,81 @@ void NotificationManager::push_import_finished_notification(const std::string& p
set_slicing_progress_hidden();
}
void NotificationManager::push_download_URL_progress_notification(size_t id, const std::string& text, std::function<bool(DownloaderUserAction, int)> user_action_callback)
{
// If already exists
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::URLDownload && dynamic_cast<URLDownloadNotification*>(notification.get())->get_download_id() == id) {
return;
}
}
// push new one
NotificationData data{ NotificationType::URLDownload, NotificationLevel::ProgressBarNotificationLevel, 5, _u8L("Download") + ": " + text };
push_notification_data(std::make_unique<NotificationManager::URLDownloadNotification>(data, m_id_provider, m_evt_handler, id, user_action_callback), 0);
}
void NotificationManager::set_download_URL_progress(size_t id, float percentage)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::URLDownload) {
URLDownloadNotification* ntf = dynamic_cast<URLDownloadNotification*>(notification.get());
if (ntf->get_download_id() != id)
continue;
// if this changes the percentage, it should be shown now
float percent_b4 = ntf->get_percentage();
ntf->set_percentage(percentage);
ntf->set_paused(false);
if (ntf->get_percentage() != percent_b4)
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
return;
}
}
}
void NotificationManager::set_download_URL_paused(size_t id)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::URLDownload) {
URLDownloadNotification* ntf = dynamic_cast<URLDownloadNotification*>(notification.get());
if (ntf->get_download_id() != id)
continue;
ntf->set_paused(true);
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
return;
}
}
}
void NotificationManager::set_download_URL_canceled(size_t id)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::URLDownload) {
URLDownloadNotification* ntf = dynamic_cast<URLDownloadNotification*>(notification.get());
if (ntf->get_download_id() != id)
continue;
ntf->close();
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
return;
}
}
}
void NotificationManager::set_download_URL_error(size_t id, const std::string& text)
{
for (std::unique_ptr<PopNotification>& notification : m_pop_notifications) {
if (notification->get_type() == NotificationType::URLDownload) {
URLDownloadNotification* ntf = dynamic_cast<URLDownloadNotification*>(notification.get());
if (ntf->get_download_id() != id)
continue;
float percent_b4 = ntf->get_percentage();
ntf->set_percentage(-1.f);
ntf->set_error_message(text);
if (ntf->get_percentage() != percent_b4)
wxGetApp().plater()->get_current_canvas3D()->schedule_extra_frame(0);
return;
}
}
}
void NotificationManager::push_upload_job_notification(int id, float filesize, const std::string& filename, const std::string& host, float percentage)
{
// find if upload with same id was not already in notification