feat(ui): add show in file manager button to screenshot view

- Add Tools::open_file_manager helper with Windows and Linux support.
- Ensure screenshot directory is created before scanning.
- Add localization keys for en_US and zh_CN.
This commit is contained in:
2026-08-07 19:49:53 +08:00
parent 4fef8e195a
commit d7cb178c2b
4 changed files with 74 additions and 6 deletions

View File

@@ -48,5 +48,6 @@
"item.stone.name": "stone", "item.stone.name": "stone",
"item.water.name": "water", "item.water.name": "water",
"item.pig_spawn_egg.name": "pig spawn egg", "item.pig_spawn_egg.name": "pig spawn egg",
"screenshot.no_screenshot": "No Screenshot" "screenshot.no_screenshot": "No Screenshot",
"button.show_in_file_manager": "Show In File Manager"
} }

View File

@@ -48,5 +48,6 @@
"item.stone.name": "石头", "item.stone.name": "石头",
"item.water.name": "水", "item.water.name": "水",
"item.pig_spawn_egg.name": "猪猪刷怪蛋", "item.pig_spawn_egg.name": "猪猪刷怪蛋",
"screenshot.no_screenshot": "没有截图" "screenshot.no_screenshot": "没有截图",
"button.show_in_file_manager": "在文件管理器中显示"
} }

View File

@@ -0,0 +1,57 @@
#pragma once
#include "Cubed/tools/log.hpp"
#include <filesystem>
#include <string>
#ifdef _WIN32
// clang-format off
#include <windows.h>
#include <shellapi.h>
// clang-format on
#elif __linux__
#include <cstdlib>
#endif
namespace Cubed::Tools {
inline void open_file_manager(const std::filesystem::path& path) {
#ifdef _WIN32
ShellExecuteW(nullptr, L"open", path.wstring().c_str(), nullptr, nullptr,
SW_SHOWNORMAL);
#elif __linux__
constexpr const char* FILE_MANAGERS[] = {"nautilus", "dolphin", "thunar",
"nemo", "pcmanfm"};
auto is_available = [](const char* exe) {
std::string cmd = std::string("command -v ") + exe + " >/dev/null 2>&1";
return std::system(cmd.c_str()) == 0;
};
const std::string QUOTED = "\"" + path.string() + "\"";
for (const char* fm : FILE_MANAGERS) {
if (!is_available(fm)) {
continue;
}
std::string cmd = std::string(fm) + " " + QUOTED + " >/dev/null 2>&1 &";
if (std::system(cmd.c_str()) == 0) {
return;
}
}
// Fallback: let the system choose a handler.
if (is_available("xdg-open")) {
std::string cmd = "xdg-open " + QUOTED + " >/dev/null 2>&1 &";
if (std::system(cmd.c_str()) == 0) {
return;
}
}
Logger::warn("Failed to open file manager for {}", path.string());
#endif
}
} // namespace Cubed::Tools

View File

@@ -4,6 +4,7 @@
#include "Cubed/localization.hpp" #include "Cubed/localization.hpp"
#include "Cubed/render/renderer.hpp" #include "Cubed/render/renderer.hpp"
#include "Cubed/scene/screenshot_scene.hpp" #include "Cubed/scene/screenshot_scene.hpp"
#include "Cubed/tools/file_utils.hpp"
#include "Cubed/ui/button.hpp" #include "Cubed/ui/button.hpp"
#include "Cubed/ui/column_layout.hpp" #include "Cubed/ui/column_layout.hpp"
#include "Cubed/ui/row_layout.hpp" #include "Cubed/ui/row_layout.hpp"
@@ -45,6 +46,7 @@ void ScreenshotUI::update_layout(int width, int height) {
constexpr float IMAGE_SCALE = 0.25; constexpr float IMAGE_SCALE = 0.25;
ScrollView* sv = nullptr; ScrollView* sv = nullptr;
fs::create_directories(path);
if (fs::exists(path)) { if (fs::exists(path)) {
for (auto& entry : fs::recursive_directory_iterator(path)) { for (auto& entry : fs::recursive_directory_iterator(path)) {
if (!fs::is_regular_file(entry)) { if (!fs::is_regular_file(entry)) {
@@ -109,20 +111,27 @@ void ScreenshotUI::update_layout(int width, int height) {
.set_color(Color::WHITE) .set_color(Color::WHITE)
.set_anchor(Anchor::CENTER); .set_anchor(Anchor::CENTER);
} }
auto& return_button = bg->add_child<Button>(); auto& bottom_row = bg->add_child<RowLayout>();
bottom_row.set_spacing(10);
bottom_row.set_anchor(Anchor::BOTTOM_CENTER).set_offset({0, -30});
auto& open_file = bottom_row.add_child<Button>();
open_file.set_default_image(texture_manager)
.set_text(tr("button.show_in_file_manager"))
.set_clicked(
[]() { Tools::open_file_manager(Renderer::SCREENSHOT_PATH); });
auto& return_button = bottom_row.add_child<Button>();
return_button.set_default_image(texture_manager); return_button.set_default_image(texture_manager);
return_button.set_anchor(Anchor::BOTTOM_CENTER);
return_button.set_offset({0, -30});
return_button.set_text(tr("button.return")); return_button.set_text(tr("button.return"));
return_button.set_clicked( return_button.set_clicked(
[this]() { m_scene.scene_manager().request_pop(); }); [this]() { m_scene.scene_manager().request_pop(); });
if (sv) { if (sv) {
float scroll_height = height - sv->get_offset().y + float scroll_height = height - sv->get_offset().y +
return_button.get_offset().y - bottom_row.get_offset().y -
return_button.height(); return_button.height();
sv->set_height(std::max(0.0f, scroll_height)); sv->set_height(std::max(0.0f, scroll_height));
} }
auto& rect = bg->add_child<Rect>(); auto& rect = bg->add_child<Rect>();
rect.set_fill_parent(true); rect.set_fill_parent(true);
rect.set_color(Color::BLACK).set_alpha(0.5f); rect.set_color(Color::BLACK).set_alpha(0.5f);