#include "pch.h" #include "legacy_brush_package_export_services.h" #include "app.h" #include "legacy_ui_overlay_services.h" #include "node_dialog_export_ppbr.h" #include "node_panel_brush.h" #include #include #include #include #include #include #include namespace pp::panopainter { namespace { class LegacyBrushPackageWorker final { public: LegacyBrushPackageWorker() : worker_([this](std::stop_token stop_token) { run(stop_token); }) { } ~LegacyBrushPackageWorker() { shutdown(); } void post(std::function task) { { std::lock_guard lock(mutex_); if (stopping_) return; tasks_.push_back(std::move(task)); } cv_.notify_one(); } private: void shutdown() { { std::lock_guard lock(mutex_); stopping_ = true; } cv_.notify_all(); } void run(std::stop_token stop_token) { for (;;) { std::function task; { std::unique_lock lock(mutex_); cv_.wait(lock, [&] { return stopping_ || stop_token.stop_requested() || !tasks_.empty(); }); if ((stopping_ || stop_token.stop_requested()) && tasks_.empty()) break; task = std::move(tasks_.front()); tasks_.pop_front(); } if (task) { try { task(); } catch (...) { LOG("brush package export worker task failed"); } } } } std::mutex mutex_; std::condition_variable cv_; std::deque> tasks_; bool stopping_ = false; std::jthread worker_; }; LegacyBrushPackageWorker& brush_package_worker() { static LegacyBrushPackageWorker worker; return worker; } NodePanelBrushPreset::PPBRInfo to_legacy_ppbr_info( const pp::app::BrushPackageExportRequest& request, const NodeDialogExportPPBR& dialog) { NodePanelBrushPreset::PPBRInfo info; info.author = request.author; info.email = request.email; info.url = request.url; info.descr = request.description; info.header_image = dialog.m_header_image; info.export_data = request.export_data; info.dest_path = request.destination_path; return info; } class LegacyBrushPackageExportServices final : public pp::app::BrushPackageExportServices { public: LegacyBrushPackageExportServices( App& app, NodeDialogExportPPBR& dialog, LegacyBrushPackageExportMode mode) noexcept : app_(app) , dialog_(dialog) , mode_(mode) { } void export_brush_package(std::string_view path, const pp::app::BrushPackageExportRequest& request) override { const auto path_string = std::string(path); const auto info = to_legacy_ppbr_info(request, dialog_); auto presets = app_.presets; if (mode_ == LegacyBrushPackageExportMode::desktop_async_close_and_message) { auto* app = &app_; auto dialog = std::static_pointer_cast(dialog_.shared_from_this()); brush_package_worker().post([app, presets, dialog, path_string, info] { BT_SetTerminate(); if (presets) { presets->export_ppbr(path_string, info); } const auto plan = pp::app::plan_brush_package_export_success_dialog(path_string); app->ui_task([dialog, plan] { if (dialog) { pp::panopainter::close_legacy_dialog_node(*dialog); } App::I->message_box(plan.title, plan.message, plan.show_cancel); }); }); return; } if (presets) { presets->export_ppbr(path_string, info); } } private: App& app_; NodeDialogExportPPBR& dialog_; LegacyBrushPackageExportMode mode_ = LegacyBrushPackageExportMode::inline_export_only; }; } // namespace pp::app::BrushPackageExportRequest make_legacy_brush_package_export_request(const NodeDialogExportPPBR& dialog) { pp::app::BrushPackageExportRequest request; request.author = dialog.txt_author ? dialog.txt_author->m_text : std::string(); request.email = dialog.txt_email ? dialog.txt_email->m_text : std::string(); request.url = dialog.txt_url ? dialog.txt_url->m_text : std::string(); request.description = dialog.txt_descr ? dialog.txt_descr->m_text : std::string(); request.destination_path = dialog.m_dest_path; request.export_data = dialog.export_check && dialog.export_check->checked; request.has_header_image = static_cast(dialog.m_header_image); return request; } pp::foundation::Status execute_legacy_brush_package_export( App& app, NodeDialogExportPPBR& dialog, const pp::app::BrushPackageExportRequest& request, std::string_view path, LegacyBrushPackageExportMode mode) { LegacyBrushPackageExportServices services(app, dialog, mode); return pp::app::execute_brush_package_export(path, request, services); } void complete_legacy_brush_package_export(NodeDialogExportPPBR& dialog, bool saved) { if (saved) { pp::panopainter::close_legacy_dialog_node(dialog); } } } // namespace pp::panopainter