Plan document export success messages
This commit is contained in:
@@ -649,6 +649,10 @@ Known local toolchain state:
|
|||||||
for image file exports, layer/frame collection directories, picked-directory
|
for image file exports, layer/frame collection directories, picked-directory
|
||||||
stems, and MP4 suggested names as JSON and is covered for file, collection,
|
stems, and MP4 suggested names as JSON and is covered for file, collection,
|
||||||
and suggested-name states.
|
and suggested-name states.
|
||||||
|
- `pano_cli plan-export-message` exposes `pp_app_core` export completion
|
||||||
|
dialog metadata for equirectangular image, layer/frame collection,
|
||||||
|
depth/cube, animation MP4, and timelapse success paths as JSON, including
|
||||||
|
platform-style destinations and suppressed/no-message paths.
|
||||||
- `pano_cli plan-export-start` exposes `pp_app_core` export availability
|
- `pano_cli plan-export-start` exposes `pp_app_core` export availability
|
||||||
planning for license-gated, demo-blocked, and missing-canvas states as JSON;
|
planning for license-gated, demo-blocked, and missing-canvas states as JSON;
|
||||||
the live image, layer, animation-frame, depth, and cube-face export dialogs
|
the live image, layer, animation-frame, depth, and cube-face export dialogs
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -519,6 +519,10 @@ stems, and MP4 suggested names used by the live export dialogs.
|
|||||||
used by live image, layer, animation-frame, depth, and cube-face export dialogs
|
used by live image, layer, animation-frame, depth, and cube-face export dialogs
|
||||||
plus MP4 animation and timelapse export dialogs before they call legacy
|
plus MP4 animation and timelapse export dialogs before they call legacy
|
||||||
canvas/recording export execution.
|
canvas/recording export execution.
|
||||||
|
`pano_cli plan-export-message` exposes the app-core export completion dialog
|
||||||
|
metadata now consumed by the live legacy export bridge for equirectangular,
|
||||||
|
layer/frame, depth/cube, animation MP4, and timelapse success reporting,
|
||||||
|
including platform-style destinations and no-message/suppressed branches.
|
||||||
`pano_cli plan-recording-session` exposes the app-core recording start, stop,
|
`pano_cli plan-recording-session` exposes the app-core recording start, stop,
|
||||||
clear, platform recorded-file cleanup, frame reset, and export progress-total
|
clear, platform recorded-file cleanup, frame reset, and export progress-total
|
||||||
decisions used by the live recording controls. Recording lifecycle and MP4
|
decisions used by the live recording controls. Recording lifecycle and MP4
|
||||||
@@ -655,6 +659,9 @@ choices, including image, layer, cube-face, depth, animation-frame, MP4, and
|
|||||||
timelapse dialog routing plus license/canvas gating. Export menu commands now
|
timelapse dialog routing plus license/canvas gating. Export menu commands now
|
||||||
dispatch through `DocumentExportMenuServices` in the shared app-shell bridge
|
dispatch through `DocumentExportMenuServices` in the shared app-shell bridge
|
||||||
before legacy export dialogs and renderer/video execution continue.
|
before legacy export dialogs and renderer/video execution continue.
|
||||||
|
Export success-message metadata now also comes from `pp_app_core` through
|
||||||
|
`pano_cli plan-export-message` and the legacy document-export bridge, reducing
|
||||||
|
the bridge to export execution, platform handoff, and retained threading.
|
||||||
`pano_cli plan-grid-operation` exposes app-core planning for grid heightmap
|
`pano_cli plan-grid-operation` exposes app-core planning for grid heightmap
|
||||||
pick/load/reload/clear, lightmap render capability/limit checks, and heightmap
|
pick/load/reload/clear, lightmap render capability/limit checks, and heightmap
|
||||||
commit used by the live grid panel. Grid execution now dispatches through
|
commit used by the live grid panel. Grid execution now dispatches through
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "app_core/app_dialog.h"
|
||||||
#include "foundation/result.h"
|
#include "foundation/result.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -71,6 +72,26 @@ enum class DocumentVideoExportKind {
|
|||||||
timelapse,
|
timelapse,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class DocumentExportSuccessKind {
|
||||||
|
equirectangular,
|
||||||
|
layers,
|
||||||
|
animation_frames,
|
||||||
|
depth,
|
||||||
|
cube_faces,
|
||||||
|
animation_mp4,
|
||||||
|
timelapse,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class DocumentExportSuccessDestination {
|
||||||
|
suppressed,
|
||||||
|
photos,
|
||||||
|
pictures_panopainter,
|
||||||
|
files_panopainter,
|
||||||
|
work_directory,
|
||||||
|
path,
|
||||||
|
generic_success,
|
||||||
|
};
|
||||||
|
|
||||||
struct DocumentExportMenuPlan {
|
struct DocumentExportMenuPlan {
|
||||||
DocumentExportMenuKind kind = DocumentExportMenuKind::jpeg;
|
DocumentExportMenuKind kind = DocumentExportMenuKind::jpeg;
|
||||||
DocumentExportMenuAction action = DocumentExportMenuAction::show_jpeg_dialog;
|
DocumentExportMenuAction action = DocumentExportMenuAction::show_jpeg_dialog;
|
||||||
@@ -83,6 +104,13 @@ struct DocumentExportCollectionTargetPlan {
|
|||||||
std::string_view suffix;
|
std::string_view suffix;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DocumentExportSuccessDialogPlan {
|
||||||
|
DocumentExportSuccessKind kind = DocumentExportSuccessKind::equirectangular;
|
||||||
|
DocumentExportSuccessDestination destination = DocumentExportSuccessDestination::suppressed;
|
||||||
|
AppMessageDialogPlan dialog;
|
||||||
|
bool show_dialog = false;
|
||||||
|
};
|
||||||
|
|
||||||
class DocumentExportMenuServices {
|
class DocumentExportMenuServices {
|
||||||
public:
|
public:
|
||||||
virtual ~DocumentExportMenuServices() = default;
|
virtual ~DocumentExportMenuServices() = default;
|
||||||
@@ -180,6 +208,32 @@ public:
|
|||||||
return DocumentExportMenuAction::show_jpeg_dialog;
|
return DocumentExportMenuAction::show_jpeg_dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr DocumentExportSuccessDestination document_export_equirectangular_platform_destination() noexcept
|
||||||
|
{
|
||||||
|
#if defined(__IOS__)
|
||||||
|
return DocumentExportSuccessDestination::photos;
|
||||||
|
#elif defined(__OSX__)
|
||||||
|
return DocumentExportSuccessDestination::pictures_panopainter;
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
return DocumentExportSuccessDestination::work_directory;
|
||||||
|
#else
|
||||||
|
return DocumentExportSuccessDestination::suppressed;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr DocumentExportSuccessDestination document_export_media_platform_destination() noexcept
|
||||||
|
{
|
||||||
|
#if defined(__IOS__)
|
||||||
|
return DocumentExportSuccessDestination::files_panopainter;
|
||||||
|
#elif defined(__OSX__)
|
||||||
|
return DocumentExportSuccessDestination::pictures_panopainter;
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
return DocumentExportSuccessDestination::work_directory;
|
||||||
|
#else
|
||||||
|
return DocumentExportSuccessDestination::suppressed;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr DocumentExportMenuPlan plan_document_export_menu_action(
|
[[nodiscard]] constexpr DocumentExportMenuPlan plan_document_export_menu_action(
|
||||||
DocumentExportMenuKind kind,
|
DocumentExportMenuKind kind,
|
||||||
bool has_canvas,
|
bool has_canvas,
|
||||||
@@ -230,6 +284,99 @@ public:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline DocumentExportSuccessDialogPlan plan_document_export_success_dialog(
|
||||||
|
DocumentExportSuccessKind kind,
|
||||||
|
DocumentExportSuccessDestination destination,
|
||||||
|
std::string_view detail = {})
|
||||||
|
{
|
||||||
|
DocumentExportSuccessDialogPlan plan;
|
||||||
|
plan.kind = kind;
|
||||||
|
plan.destination = destination;
|
||||||
|
if (destination == DocumentExportSuccessDestination::suppressed) {
|
||||||
|
return plan;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string message;
|
||||||
|
switch (kind) {
|
||||||
|
case DocumentExportSuccessKind::equirectangular:
|
||||||
|
plan.dialog.title = "Export Equirectangular";
|
||||||
|
switch (destination) {
|
||||||
|
case DocumentExportSuccessDestination::photos:
|
||||||
|
message = "Image exported to Photos";
|
||||||
|
break;
|
||||||
|
case DocumentExportSuccessDestination::pictures_panopainter:
|
||||||
|
message = "Image exported to Pictures/PanoPainter folder";
|
||||||
|
break;
|
||||||
|
case DocumentExportSuccessDestination::work_directory:
|
||||||
|
message = "Image exported to ";
|
||||||
|
message += detail;
|
||||||
|
break;
|
||||||
|
case DocumentExportSuccessDestination::suppressed:
|
||||||
|
case DocumentExportSuccessDestination::files_panopainter:
|
||||||
|
case DocumentExportSuccessDestination::path:
|
||||||
|
case DocumentExportSuccessDestination::generic_success:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DocumentExportSuccessKind::layers:
|
||||||
|
case DocumentExportSuccessKind::animation_frames:
|
||||||
|
plan.dialog.title = "Export Layers";
|
||||||
|
if (destination == DocumentExportSuccessDestination::files_panopainter) {
|
||||||
|
message = "Image layers exported to Files/PanoPainter";
|
||||||
|
} else if (destination == DocumentExportSuccessDestination::path) {
|
||||||
|
message = "Layers exported to: ";
|
||||||
|
message += detail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DocumentExportSuccessKind::depth:
|
||||||
|
plan.dialog.title = "Export 3D View + Depth";
|
||||||
|
if (destination == DocumentExportSuccessDestination::files_panopainter) {
|
||||||
|
message = "Image and depth exported to Files/PanoPainter";
|
||||||
|
} else if (destination == DocumentExportSuccessDestination::pictures_panopainter) {
|
||||||
|
message = "Image and depth exported to Pictures/PanoPainter folder";
|
||||||
|
} else if (destination == DocumentExportSuccessDestination::work_directory) {
|
||||||
|
message = "Image and depth exported to ";
|
||||||
|
message += detail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DocumentExportSuccessKind::cube_faces:
|
||||||
|
plan.dialog.title = "Export Cube Faces";
|
||||||
|
if (destination == DocumentExportSuccessDestination::files_panopainter) {
|
||||||
|
message = "Image and depth exported to Files/PanoPainter";
|
||||||
|
} else if (destination == DocumentExportSuccessDestination::pictures_panopainter) {
|
||||||
|
message = "Image and depth exported to Pictures/PanoPainter folder";
|
||||||
|
} else if (destination == DocumentExportSuccessDestination::work_directory) {
|
||||||
|
message = "Image and depth exported to ";
|
||||||
|
message += detail;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DocumentExportSuccessKind::animation_mp4:
|
||||||
|
plan.dialog.title = "Export Animation";
|
||||||
|
if (destination == DocumentExportSuccessDestination::path) {
|
||||||
|
message = "Animation exported to: ";
|
||||||
|
message += detail;
|
||||||
|
} else if (destination == DocumentExportSuccessDestination::generic_success) {
|
||||||
|
message = "Animation exported successfully.";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DocumentExportSuccessKind::timelapse:
|
||||||
|
plan.dialog.title = "Export Timelapse";
|
||||||
|
if (destination == DocumentExportSuccessDestination::path) {
|
||||||
|
message = "Timelapse exported to: ";
|
||||||
|
message += detail;
|
||||||
|
} else if (destination == DocumentExportSuccessDestination::generic_success) {
|
||||||
|
message = "Timelapse exported successfully.";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!plan.dialog.title.empty() && !message.empty()) {
|
||||||
|
plan.dialog.message = std::move(message);
|
||||||
|
plan.show_dialog = true;
|
||||||
|
}
|
||||||
|
return plan;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline pp::foundation::Result<DocumentExportFileTarget> make_document_export_file_target(
|
[[nodiscard]] inline pp::foundation::Result<DocumentExportFileTarget> make_document_export_file_target(
|
||||||
std::string_view work_directory,
|
std::string_view work_directory,
|
||||||
std::string_view document_name,
|
std::string_view document_name,
|
||||||
|
|||||||
@@ -10,6 +10,15 @@
|
|||||||
namespace pp::panopainter {
|
namespace pp::panopainter {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
void show_export_success_dialog(
|
||||||
|
App& app,
|
||||||
|
const pp::app::DocumentExportSuccessDialogPlan& plan)
|
||||||
|
{
|
||||||
|
if (plan.show_dialog) {
|
||||||
|
app.message_box(plan.dialog.title, plan.dialog.message, plan.dialog.show_cancel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class LegacyDocumentExportServices final : public pp::app::DocumentExportServices {
|
class LegacyDocumentExportServices final : public pp::app::DocumentExportServices {
|
||||||
public:
|
public:
|
||||||
explicit LegacyDocumentExportServices(App& app) noexcept
|
explicit LegacyDocumentExportServices(App& app) noexcept
|
||||||
@@ -26,20 +35,18 @@ public:
|
|||||||
{
|
{
|
||||||
auto* app = &app_;
|
auto* app = &app_;
|
||||||
app_.canvas->m_canvas->export_equirectangular(target.path, [app, target] {
|
app_.canvas->m_canvas->export_equirectangular(target.path, [app, target] {
|
||||||
#if defined(__IOS__)
|
#if __WEB__
|
||||||
app->message_box("Export Equirectangular", "Image exported to Photos");
|
|
||||||
#elif defined(__OSX__)
|
|
||||||
app->message_box("Export Equirectangular", "Image exported to Pictures/PanoPainter folder");
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
app->message_box("Export Equirectangular", "Image exported to " + app->work_path);
|
|
||||||
#elif defined(__QUEST__)
|
|
||||||
(void)target;
|
|
||||||
#elif __WEB__
|
|
||||||
app->ui_task([app, target] {
|
app->ui_task([app, target] {
|
||||||
app->save_prepared_file(target.path, target.suggested_name, [](const std::string&, bool) { });
|
app->save_prepared_file(target.path, target.suggested_name, [](const std::string&, bool) { });
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
(void)target;
|
(void)target;
|
||||||
|
show_export_success_dialog(
|
||||||
|
*app,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::equirectangular,
|
||||||
|
pp::app::document_export_equirectangular_platform_destination(),
|
||||||
|
app->work_path));
|
||||||
#endif
|
#endif
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -48,7 +55,12 @@ public:
|
|||||||
{
|
{
|
||||||
auto* app = &app_;
|
auto* app = &app_;
|
||||||
app_.canvas->m_canvas->export_layers(target.stem_path, [app, target] {
|
app_.canvas->m_canvas->export_layers(target.stem_path, [app, target] {
|
||||||
app->message_box("Export Layers", "Layers exported to: " + target.stem_path);
|
show_export_success_dialog(
|
||||||
|
*app,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::layers,
|
||||||
|
pp::app::DocumentExportSuccessDestination::path,
|
||||||
|
target.stem_path));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +68,11 @@ public:
|
|||||||
{
|
{
|
||||||
auto* app = &app_;
|
auto* app = &app_;
|
||||||
app_.canvas->m_canvas->export_layers(target.stem_path, [app] {
|
app_.canvas->m_canvas->export_layers(target.stem_path, [app] {
|
||||||
app->message_box("Export Layers", "Image layers exported to Files/PanoPainter");
|
show_export_success_dialog(
|
||||||
|
*app,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::layers,
|
||||||
|
pp::app::DocumentExportSuccessDestination::files_panopainter));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +80,12 @@ public:
|
|||||||
{
|
{
|
||||||
auto* app = &app_;
|
auto* app = &app_;
|
||||||
app_.canvas->m_canvas->export_anim_frames(target.stem_path, [app, target] {
|
app_.canvas->m_canvas->export_anim_frames(target.stem_path, [app, target] {
|
||||||
app->message_box("Export Layers", "Layers exported to: " + target.stem_path);
|
show_export_success_dialog(
|
||||||
|
*app,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_frames,
|
||||||
|
pp::app::DocumentExportSuccessDestination::path,
|
||||||
|
target.stem_path));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +93,11 @@ public:
|
|||||||
{
|
{
|
||||||
auto* app = &app_;
|
auto* app = &app_;
|
||||||
app_.canvas->m_canvas->export_anim_frames(target.stem_path, [app] {
|
app_.canvas->m_canvas->export_anim_frames(target.stem_path, [app] {
|
||||||
app->message_box("Export Layers", "Image layers exported to Files/PanoPainter");
|
show_export_success_dialog(
|
||||||
|
*app,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_frames,
|
||||||
|
pp::app::DocumentExportSuccessDestination::files_panopainter));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,13 +105,12 @@ public:
|
|||||||
{
|
{
|
||||||
auto* app = &app_;
|
auto* app = &app_;
|
||||||
app_.canvas->m_canvas->export_depth(std::string(document_name), [app] {
|
app_.canvas->m_canvas->export_depth(std::string(document_name), [app] {
|
||||||
#if defined(__IOS__)
|
show_export_success_dialog(
|
||||||
app->message_box("Export 3D View + Depth", "Image and depth exported to Files/PanoPainter");
|
*app,
|
||||||
#elif defined(__OSX__)
|
pp::app::plan_document_export_success_dialog(
|
||||||
app->message_box("Export 3D View + Depth", "Image and depth exported to Pictures/PanoPainter folder");
|
pp::app::DocumentExportSuccessKind::depth,
|
||||||
#elif defined(_WIN32)
|
pp::app::document_export_media_platform_destination(),
|
||||||
app->message_box("Export 3D View + Depth", "Image and depth exported to " + app->work_path);
|
app->work_path));
|
||||||
#endif
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,13 +118,12 @@ public:
|
|||||||
{
|
{
|
||||||
auto* app = &app_;
|
auto* app = &app_;
|
||||||
app_.canvas->m_canvas->export_cube_faces(std::string(document_name), [app] {
|
app_.canvas->m_canvas->export_cube_faces(std::string(document_name), [app] {
|
||||||
#if defined(__IOS__)
|
show_export_success_dialog(
|
||||||
app->message_box("Export Cube Faces", "Image and depth exported to Files/PanoPainter");
|
*app,
|
||||||
#elif defined(__OSX__)
|
pp::app::plan_document_export_success_dialog(
|
||||||
app->message_box("Export Cube Faces", "Image and depth exported to Pictures/PanoPainter folder");
|
pp::app::DocumentExportSuccessKind::cube_faces,
|
||||||
#elif defined(_WIN32)
|
pp::app::document_export_media_platform_destination(),
|
||||||
app->message_box("Export Cube Faces", "Image and depth exported to " + app->work_path);
|
app->work_path));
|
||||||
#endif
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,13 +145,22 @@ public:
|
|||||||
auto path_string = std::string(path);
|
auto path_string = std::string(path);
|
||||||
if (asynchronous_) {
|
if (asynchronous_) {
|
||||||
Canvas::I->export_anim_mp4(path_string, [app, path_string] {
|
Canvas::I->export_anim_mp4(path_string, [app, path_string] {
|
||||||
app->message_box("Export Animation", "Animation exported to: " + path_string);
|
show_export_success_dialog(
|
||||||
|
*app,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_mp4,
|
||||||
|
pp::app::DocumentExportSuccessDestination::path,
|
||||||
|
path_string));
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::I->export_anim_mp4(path_string, [app] {
|
Canvas::I->export_anim_mp4(path_string, [app] {
|
||||||
app->message_box("Export Animation", "Animation exported successfully.");
|
show_export_success_dialog(
|
||||||
|
*app,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_mp4,
|
||||||
|
pp::app::DocumentExportSuccessDestination::generic_success));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +172,12 @@ public:
|
|||||||
std::thread([app, path_string] {
|
std::thread([app, path_string] {
|
||||||
BT_SetTerminate();
|
BT_SetTerminate();
|
||||||
app->rec_export(path_string);
|
app->rec_export(path_string);
|
||||||
app->message_box("Export Timelapse", "Timelapse exported to: " + path_string);
|
show_export_success_dialog(
|
||||||
|
*app,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::timelapse,
|
||||||
|
pp::app::DocumentExportSuccessDestination::path,
|
||||||
|
path_string));
|
||||||
}).detach();
|
}).detach();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -158,7 +195,12 @@ public:
|
|||||||
if (asynchronous_) {
|
if (asynchronous_) {
|
||||||
(void)path;
|
(void)path;
|
||||||
} else {
|
} else {
|
||||||
app_.message_box("Export Timelapse", "Timelapse exported successfully.");
|
(void)path;
|
||||||
|
show_export_success_dialog(
|
||||||
|
app_,
|
||||||
|
pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::timelapse,
|
||||||
|
pp::app::DocumentExportSuccessDestination::generic_success));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -899,6 +899,37 @@ if(TARGET pano_cli)
|
|||||||
LABELS "app;integration;desktop-fast"
|
LABELS "app;integration;desktop-fast"
|
||||||
PASS_REGULAR_EXPRESSION "\"command\":\"plan-export-target\".*\"kind\":\"name\".*\"suggestedName\":\"demo-timelapse\"")
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-export-target\".*\"kind\":\"name\".*\"suggestedName\":\"demo-timelapse\"")
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_export_message_equirect_work_smoke
|
||||||
|
COMMAND pano_cli plan-export-message --kind equirectangular --destination work --detail D:/Paint)
|
||||||
|
set_tests_properties(pano_cli_plan_export_message_equirect_work_smoke PROPERTIES
|
||||||
|
LABELS "app;integration;desktop-fast"
|
||||||
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-export-message\".*\"kind\":\"equirectangular\".*\"destination\":\"work-directory\".*\"showDialog\":true.*\"title\":\"Export Equirectangular\".*\"message\":\"Image exported to D:/Paint\"")
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_export_message_layers_files_smoke
|
||||||
|
COMMAND pano_cli plan-export-message --kind layers --destination files)
|
||||||
|
set_tests_properties(pano_cli_plan_export_message_layers_files_smoke PROPERTIES
|
||||||
|
LABELS "app;integration;desktop-fast"
|
||||||
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-export-message\".*\"kind\":\"layers\".*\"destination\":\"files-panopainter\".*\"showDialog\":true.*\"message\":\"Image layers exported to Files/PanoPainter\"")
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_export_message_timelapse_success_smoke
|
||||||
|
COMMAND pano_cli plan-export-message --kind timelapse --destination success)
|
||||||
|
set_tests_properties(pano_cli_plan_export_message_timelapse_success_smoke PROPERTIES
|
||||||
|
LABELS "app;integration;desktop-fast"
|
||||||
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-export-message\".*\"kind\":\"timelapse\".*\"destination\":\"generic-success\".*\"showDialog\":true.*\"message\":\"Timelapse exported successfully\\.\"")
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_export_message_suppressed_smoke
|
||||||
|
COMMAND pano_cli plan-export-message --kind depth --destination suppressed)
|
||||||
|
set_tests_properties(pano_cli_plan_export_message_suppressed_smoke PROPERTIES
|
||||||
|
LABELS "app;integration;desktop-fast;fuzz"
|
||||||
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-export-message\".*\"kind\":\"depth\".*\"destination\":\"suppressed\".*\"showDialog\":false.*\"title\":\"\".*\"message\":\"\"")
|
||||||
|
|
||||||
|
add_test(NAME pano_cli_plan_export_message_rejects_unknown
|
||||||
|
COMMAND pano_cli plan-export-message --kind nope)
|
||||||
|
set_tests_properties(pano_cli_plan_export_message_rejects_unknown PROPERTIES
|
||||||
|
LABELS "app;integration;desktop-fast;fuzz"
|
||||||
|
WILL_FAIL TRUE
|
||||||
|
PASS_REGULAR_EXPRESSION "\"command\":\"plan-export-message\".*\"message\":\"unknown export message kind\"")
|
||||||
|
|
||||||
add_test(NAME pano_cli_plan_cloud_upload_clean_smoke
|
add_test(NAME pano_cli_plan_cloud_upload_clean_smoke
|
||||||
COMMAND pano_cli plan-cloud-upload)
|
COMMAND pano_cli plan-cloud-upload)
|
||||||
set_tests_properties(pano_cli_plan_cloud_upload_clean_smoke PROPERTIES
|
set_tests_properties(pano_cli_plan_cloud_upload_clean_smoke PROPERTIES
|
||||||
|
|||||||
@@ -218,6 +218,115 @@ void collection_export_target_plan_selects_platform_destination(pp::tests::Harne
|
|||||||
PP_EXPECT(harness, picked_layers.suffix == "_layers");
|
PP_EXPECT(harness, picked_layers.suffix == "_layers");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void export_success_dialog_plans_image_destinations(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto photos = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::equirectangular,
|
||||||
|
pp::app::DocumentExportSuccessDestination::photos);
|
||||||
|
const auto pictures = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::equirectangular,
|
||||||
|
pp::app::DocumentExportSuccessDestination::pictures_panopainter);
|
||||||
|
const auto work = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::equirectangular,
|
||||||
|
pp::app::DocumentExportSuccessDestination::work_directory,
|
||||||
|
"D:/Paint");
|
||||||
|
|
||||||
|
PP_EXPECT(harness, photos.show_dialog);
|
||||||
|
PP_EXPECT(harness, photos.dialog.title == "Export Equirectangular");
|
||||||
|
PP_EXPECT(harness, photos.dialog.message == "Image exported to Photos");
|
||||||
|
PP_EXPECT(harness, pictures.dialog.message == "Image exported to Pictures/PanoPainter folder");
|
||||||
|
PP_EXPECT(harness, work.dialog.message == "Image exported to D:/Paint");
|
||||||
|
}
|
||||||
|
|
||||||
|
void export_success_dialog_plans_collection_destinations(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto layers_path = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::layers,
|
||||||
|
pp::app::DocumentExportSuccessDestination::path,
|
||||||
|
"D:/Paint/demo_layers/demo");
|
||||||
|
const auto frames_path = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_frames,
|
||||||
|
pp::app::DocumentExportSuccessDestination::path,
|
||||||
|
"D:/Paint/demo_frames/demo");
|
||||||
|
const auto layers_collection = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::layers,
|
||||||
|
pp::app::DocumentExportSuccessDestination::files_panopainter);
|
||||||
|
const auto frames_collection = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_frames,
|
||||||
|
pp::app::DocumentExportSuccessDestination::files_panopainter);
|
||||||
|
|
||||||
|
PP_EXPECT(harness, layers_path.dialog.title == "Export Layers");
|
||||||
|
PP_EXPECT(harness, layers_path.dialog.message == "Layers exported to: D:/Paint/demo_layers/demo");
|
||||||
|
PP_EXPECT(harness, frames_path.dialog.message == "Layers exported to: D:/Paint/demo_frames/demo");
|
||||||
|
PP_EXPECT(harness, layers_collection.dialog.message == "Image layers exported to Files/PanoPainter");
|
||||||
|
PP_EXPECT(harness, frames_collection.dialog.message == "Image layers exported to Files/PanoPainter");
|
||||||
|
}
|
||||||
|
|
||||||
|
void export_success_dialog_plans_depth_and_cube_destinations(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto depth_files = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::depth,
|
||||||
|
pp::app::DocumentExportSuccessDestination::files_panopainter);
|
||||||
|
const auto depth_pictures = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::depth,
|
||||||
|
pp::app::DocumentExportSuccessDestination::pictures_panopainter);
|
||||||
|
const auto depth_work = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::depth,
|
||||||
|
pp::app::DocumentExportSuccessDestination::work_directory,
|
||||||
|
"D:/Paint");
|
||||||
|
const auto cube_work = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::cube_faces,
|
||||||
|
pp::app::DocumentExportSuccessDestination::work_directory,
|
||||||
|
"D:/Paint");
|
||||||
|
|
||||||
|
PP_EXPECT(harness, depth_files.dialog.title == "Export 3D View + Depth");
|
||||||
|
PP_EXPECT(harness, depth_files.dialog.message == "Image and depth exported to Files/PanoPainter");
|
||||||
|
PP_EXPECT(harness, depth_pictures.dialog.message == "Image and depth exported to Pictures/PanoPainter folder");
|
||||||
|
PP_EXPECT(harness, depth_work.dialog.message == "Image and depth exported to D:/Paint");
|
||||||
|
PP_EXPECT(harness, cube_work.dialog.title == "Export Cube Faces");
|
||||||
|
PP_EXPECT(harness, cube_work.dialog.message == "Image and depth exported to D:/Paint");
|
||||||
|
}
|
||||||
|
|
||||||
|
void export_success_dialog_plans_video_destinations(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto animation_path = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_mp4,
|
||||||
|
pp::app::DocumentExportSuccessDestination::path,
|
||||||
|
"D:/Paint/animation.mp4");
|
||||||
|
const auto animation_success = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_mp4,
|
||||||
|
pp::app::DocumentExportSuccessDestination::generic_success);
|
||||||
|
const auto timelapse_path = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::timelapse,
|
||||||
|
pp::app::DocumentExportSuccessDestination::path,
|
||||||
|
"D:/Paint/timelapse.mp4");
|
||||||
|
const auto timelapse_success = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::timelapse,
|
||||||
|
pp::app::DocumentExportSuccessDestination::generic_success);
|
||||||
|
|
||||||
|
PP_EXPECT(harness, animation_path.dialog.title == "Export Animation");
|
||||||
|
PP_EXPECT(harness, animation_path.dialog.message == "Animation exported to: D:/Paint/animation.mp4");
|
||||||
|
PP_EXPECT(harness, animation_success.dialog.message == "Animation exported successfully.");
|
||||||
|
PP_EXPECT(harness, timelapse_path.dialog.title == "Export Timelapse");
|
||||||
|
PP_EXPECT(harness, timelapse_path.dialog.message == "Timelapse exported to: D:/Paint/timelapse.mp4");
|
||||||
|
PP_EXPECT(harness, timelapse_success.dialog.message == "Timelapse exported successfully.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void export_success_dialog_suppresses_unsupported_destinations(pp::tests::Harness& harness)
|
||||||
|
{
|
||||||
|
const auto suppressed = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::depth,
|
||||||
|
pp::app::DocumentExportSuccessDestination::suppressed);
|
||||||
|
const auto invalid_combo = pp::app::plan_document_export_success_dialog(
|
||||||
|
pp::app::DocumentExportSuccessKind::equirectangular,
|
||||||
|
pp::app::DocumentExportSuccessDestination::files_panopainter);
|
||||||
|
|
||||||
|
PP_EXPECT(harness, !suppressed.show_dialog);
|
||||||
|
PP_EXPECT(harness, suppressed.dialog.title.empty());
|
||||||
|
PP_EXPECT(harness, !invalid_combo.show_dialog);
|
||||||
|
PP_EXPECT(harness, invalid_combo.dialog.message.empty());
|
||||||
|
}
|
||||||
|
|
||||||
void export_start_allows_valid_canvas_state(pp::tests::Harness& harness)
|
void export_start_allows_valid_canvas_state(pp::tests::Harness& harness)
|
||||||
{
|
{
|
||||||
PP_EXPECT(
|
PP_EXPECT(
|
||||||
@@ -552,6 +661,11 @@ int main()
|
|||||||
harness.run("picked directory export builds stem", picked_directory_export_builds_stem);
|
harness.run("picked directory export builds stem", picked_directory_export_builds_stem);
|
||||||
harness.run("video export builds suggested name", video_export_builds_suggested_name);
|
harness.run("video export builds suggested name", video_export_builds_suggested_name);
|
||||||
harness.run("collection export target plan selects platform destination", collection_export_target_plan_selects_platform_destination);
|
harness.run("collection export target plan selects platform destination", collection_export_target_plan_selects_platform_destination);
|
||||||
|
harness.run("export success dialog plans image destinations", export_success_dialog_plans_image_destinations);
|
||||||
|
harness.run("export success dialog plans collection destinations", export_success_dialog_plans_collection_destinations);
|
||||||
|
harness.run("export success dialog plans depth and cube destinations", export_success_dialog_plans_depth_and_cube_destinations);
|
||||||
|
harness.run("export success dialog plans video destinations", export_success_dialog_plans_video_destinations);
|
||||||
|
harness.run("export success dialog suppresses unsupported destinations", export_success_dialog_suppresses_unsupported_destinations);
|
||||||
harness.run("export start allows valid canvas state", export_start_allows_valid_canvas_state);
|
harness.run("export start allows valid canvas state", export_start_allows_valid_canvas_state);
|
||||||
harness.run("export start blocks demo only when license required", export_start_blocks_demo_only_when_license_required);
|
harness.run("export start blocks demo only when license required", export_start_blocks_demo_only_when_license_required);
|
||||||
harness.run("export start reports missing canvas after license gate", export_start_reports_missing_canvas_after_license_gate);
|
harness.run("export start reports missing canvas after license gate", export_start_reports_missing_canvas_after_license_gate);
|
||||||
|
|||||||
@@ -168,6 +168,12 @@ struct PlanExportTargetArgs {
|
|||||||
std::string suffix;
|
std::string suffix;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PlanExportMessageArgs {
|
||||||
|
std::string kind = "equirectangular";
|
||||||
|
std::string destination = "work";
|
||||||
|
std::string detail = "D:/Paint";
|
||||||
|
};
|
||||||
|
|
||||||
struct PlanExportStartArgs {
|
struct PlanExportStartArgs {
|
||||||
bool requires_license = false;
|
bool requires_license = false;
|
||||||
bool license_valid = true;
|
bool license_valid = true;
|
||||||
@@ -1943,6 +1949,123 @@ pp::foundation::Result<pp::app::DocumentExportMenuKind> parse_document_export_me
|
|||||||
pp::foundation::Status::invalid_argument("unknown export menu kind"));
|
pp::foundation::Status::invalid_argument("unknown export menu kind"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* document_export_success_kind_name(pp::app::DocumentExportSuccessKind kind) noexcept
|
||||||
|
{
|
||||||
|
switch (kind) {
|
||||||
|
case pp::app::DocumentExportSuccessKind::equirectangular:
|
||||||
|
return "equirectangular";
|
||||||
|
case pp::app::DocumentExportSuccessKind::layers:
|
||||||
|
return "layers";
|
||||||
|
case pp::app::DocumentExportSuccessKind::animation_frames:
|
||||||
|
return "animation-frames";
|
||||||
|
case pp::app::DocumentExportSuccessKind::depth:
|
||||||
|
return "depth";
|
||||||
|
case pp::app::DocumentExportSuccessKind::cube_faces:
|
||||||
|
return "cube-faces";
|
||||||
|
case pp::app::DocumentExportSuccessKind::animation_mp4:
|
||||||
|
return "animation-mp4";
|
||||||
|
case pp::app::DocumentExportSuccessKind::timelapse:
|
||||||
|
return "timelapse";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "equirectangular";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* document_export_success_destination_name(
|
||||||
|
pp::app::DocumentExportSuccessDestination destination) noexcept
|
||||||
|
{
|
||||||
|
switch (destination) {
|
||||||
|
case pp::app::DocumentExportSuccessDestination::suppressed:
|
||||||
|
return "suppressed";
|
||||||
|
case pp::app::DocumentExportSuccessDestination::photos:
|
||||||
|
return "photos";
|
||||||
|
case pp::app::DocumentExportSuccessDestination::pictures_panopainter:
|
||||||
|
return "pictures-panopainter";
|
||||||
|
case pp::app::DocumentExportSuccessDestination::files_panopainter:
|
||||||
|
return "files-panopainter";
|
||||||
|
case pp::app::DocumentExportSuccessDestination::work_directory:
|
||||||
|
return "work-directory";
|
||||||
|
case pp::app::DocumentExportSuccessDestination::path:
|
||||||
|
return "path";
|
||||||
|
case pp::app::DocumentExportSuccessDestination::generic_success:
|
||||||
|
return "generic-success";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "suppressed";
|
||||||
|
}
|
||||||
|
|
||||||
|
pp::foundation::Result<pp::app::DocumentExportSuccessKind> parse_document_export_success_kind(
|
||||||
|
std::string_view kind)
|
||||||
|
{
|
||||||
|
if (kind == "equirectangular" || kind == "equirect" || kind == "image") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessKind>::success(
|
||||||
|
pp::app::DocumentExportSuccessKind::equirectangular);
|
||||||
|
}
|
||||||
|
if (kind == "layers") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessKind>::success(
|
||||||
|
pp::app::DocumentExportSuccessKind::layers);
|
||||||
|
}
|
||||||
|
if (kind == "animation-frames" || kind == "frames") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessKind>::success(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_frames);
|
||||||
|
}
|
||||||
|
if (kind == "depth") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessKind>::success(
|
||||||
|
pp::app::DocumentExportSuccessKind::depth);
|
||||||
|
}
|
||||||
|
if (kind == "cube-faces" || kind == "cube") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessKind>::success(
|
||||||
|
pp::app::DocumentExportSuccessKind::cube_faces);
|
||||||
|
}
|
||||||
|
if (kind == "animation-mp4" || kind == "mp4") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessKind>::success(
|
||||||
|
pp::app::DocumentExportSuccessKind::animation_mp4);
|
||||||
|
}
|
||||||
|
if (kind == "timelapse") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessKind>::success(
|
||||||
|
pp::app::DocumentExportSuccessKind::timelapse);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessKind>::failure(
|
||||||
|
pp::foundation::Status::invalid_argument("unknown export message kind"));
|
||||||
|
}
|
||||||
|
|
||||||
|
pp::foundation::Result<pp::app::DocumentExportSuccessDestination> parse_document_export_success_destination(
|
||||||
|
std::string_view destination)
|
||||||
|
{
|
||||||
|
if (destination == "suppressed" || destination == "none") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessDestination>::success(
|
||||||
|
pp::app::DocumentExportSuccessDestination::suppressed);
|
||||||
|
}
|
||||||
|
if (destination == "photos") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessDestination>::success(
|
||||||
|
pp::app::DocumentExportSuccessDestination::photos);
|
||||||
|
}
|
||||||
|
if (destination == "pictures" || destination == "pictures-panopainter") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessDestination>::success(
|
||||||
|
pp::app::DocumentExportSuccessDestination::pictures_panopainter);
|
||||||
|
}
|
||||||
|
if (destination == "files" || destination == "files-panopainter") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessDestination>::success(
|
||||||
|
pp::app::DocumentExportSuccessDestination::files_panopainter);
|
||||||
|
}
|
||||||
|
if (destination == "work" || destination == "work-directory") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessDestination>::success(
|
||||||
|
pp::app::DocumentExportSuccessDestination::work_directory);
|
||||||
|
}
|
||||||
|
if (destination == "path") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessDestination>::success(
|
||||||
|
pp::app::DocumentExportSuccessDestination::path);
|
||||||
|
}
|
||||||
|
if (destination == "success" || destination == "generic-success") {
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessDestination>::success(
|
||||||
|
pp::app::DocumentExportSuccessDestination::generic_success);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pp::foundation::Result<pp::app::DocumentExportSuccessDestination>::failure(
|
||||||
|
pp::foundation::Status::invalid_argument("unknown export message destination"));
|
||||||
|
}
|
||||||
|
|
||||||
const char* cloud_upload_action_name(pp::app::CloudUploadAction action) noexcept
|
const char* cloud_upload_action_name(pp::app::CloudUploadAction action) noexcept
|
||||||
{
|
{
|
||||||
switch (action) {
|
switch (action) {
|
||||||
@@ -2234,6 +2357,7 @@ void print_help()
|
|||||||
<< " plan-export-start [--requires-license] [--demo] [--no-canvas]\n"
|
<< " plan-export-start [--requires-license] [--demo] [--no-canvas]\n"
|
||||||
<< " plan-export-menu --kind jpeg|png|layers|cube-faces|depth|animation-frames|animation-mp4|timelapse [--demo] [--no-canvas]\n"
|
<< " plan-export-menu --kind jpeg|png|layers|cube-faces|depth|animation-frames|animation-mp4|timelapse [--demo] [--no-canvas]\n"
|
||||||
<< " plan-export-target --kind file|collection|stem|name --doc-name NAME [--work-dir DIR] [--directory DIR] [--extension EXT] [--suffix SUFFIX]\n"
|
<< " plan-export-target --kind file|collection|stem|name --doc-name NAME [--work-dir DIR] [--directory DIR] [--extension EXT] [--suffix SUFFIX]\n"
|
||||||
|
<< " plan-export-message --kind equirectangular|layers|animation-frames|depth|cube-faces|animation-mp4|timelapse --destination photos|pictures|files|work|path|success|suppressed [--detail TEXT]\n"
|
||||||
<< " plan-cloud-upload [--no-canvas] [--new-document] [--unsaved]\n"
|
<< " plan-cloud-upload [--no-canvas] [--new-document] [--unsaved]\n"
|
||||||
<< " plan-cloud-browse [--no-canvas] [--selected-file FILE]\n"
|
<< " plan-cloud-browse [--no-canvas] [--selected-file FILE]\n"
|
||||||
<< " plan-cloud-upload-all [--file-count N] [--no-progress-ui]\n"
|
<< " plan-cloud-upload-all [--file-count N] [--no-progress-ui]\n"
|
||||||
@@ -3588,6 +3712,74 @@ int plan_export_menu(int argc, char** argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pp::foundation::Status parse_plan_export_message_args(
|
||||||
|
int argc,
|
||||||
|
char** argv,
|
||||||
|
PlanExportMessageArgs& args)
|
||||||
|
{
|
||||||
|
for (int i = 2; i < argc; ++i) {
|
||||||
|
const std::string_view key(argv[i]);
|
||||||
|
if (key == "--kind") {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||||
|
}
|
||||||
|
args.kind = argv[++i];
|
||||||
|
} else if (key == "--destination") {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||||
|
}
|
||||||
|
args.destination = argv[++i];
|
||||||
|
} else if (key == "--detail") {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
return pp::foundation::Status::invalid_argument("missing value for option");
|
||||||
|
}
|
||||||
|
args.detail = argv[++i];
|
||||||
|
} else {
|
||||||
|
return pp::foundation::Status::invalid_argument("unknown option");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pp::foundation::Status::success();
|
||||||
|
}
|
||||||
|
|
||||||
|
int plan_export_message(int argc, char** argv)
|
||||||
|
{
|
||||||
|
PlanExportMessageArgs args;
|
||||||
|
const auto status = parse_plan_export_message_args(argc, argv, args);
|
||||||
|
if (!status.ok()) {
|
||||||
|
print_error("plan-export-message", status.message);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto kind = parse_document_export_success_kind(args.kind);
|
||||||
|
if (!kind) {
|
||||||
|
print_error("plan-export-message", kind.status().message);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto destination = parse_document_export_success_destination(args.destination);
|
||||||
|
if (!destination) {
|
||||||
|
print_error("plan-export-message", destination.status().message);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto plan = pp::app::plan_document_export_success_dialog(
|
||||||
|
kind.value(),
|
||||||
|
destination.value(),
|
||||||
|
args.detail);
|
||||||
|
std::cout << "{\"ok\":true,\"command\":\"plan-export-message\""
|
||||||
|
<< ",\"state\":{\"kind\":\"" << json_escape(args.kind)
|
||||||
|
<< "\",\"destination\":\"" << json_escape(args.destination)
|
||||||
|
<< "\",\"detail\":\"" << json_escape(args.detail)
|
||||||
|
<< "\"},\"plan\":{\"kind\":\"" << document_export_success_kind_name(plan.kind)
|
||||||
|
<< "\",\"destination\":\"" << document_export_success_destination_name(plan.destination)
|
||||||
|
<< "\",\"showDialog\":" << json_bool(plan.show_dialog)
|
||||||
|
<< ",\"title\":\"" << json_escape(plan.dialog.title)
|
||||||
|
<< "\",\"message\":\"" << json_escape(plan.dialog.message)
|
||||||
|
<< "\"}}\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
pp::foundation::Status parse_plan_cloud_upload_args(
|
pp::foundation::Status parse_plan_cloud_upload_args(
|
||||||
int argc,
|
int argc,
|
||||||
char** argv,
|
char** argv,
|
||||||
@@ -11187,6 +11379,10 @@ int main(int argc, char** argv)
|
|||||||
return plan_export_target(argc, argv);
|
return plan_export_target(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (command == "plan-export-message") {
|
||||||
|
return plan_export_message(argc, argv);
|
||||||
|
}
|
||||||
|
|
||||||
if (command == "plan-cloud-upload") {
|
if (command == "plan-cloud-upload") {
|
||||||
return plan_cloud_upload(argc, argv);
|
return plan_cloud_upload(argc, argv);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user